Why it runs twice when seed in rails? - ruby-on-rails

I just put puts "test" in the seeds file , when I run rake db:seed, I saw there are 2 lines "test"

I'm experiencing this when I load tasks in my Rails code, for example
# config/initializers/rake_load_tasks.rb
# DO NOT USE THIS, IT WILL CAUSE rails db:seed TO RUN TWICE
require "rake"
Rails.application.load_tasks

Related

How to run default rake tasks in Rails 5?

Here's a layup for someone...
Back in Rails <= 4 days we'd run our test suite by simply typing $ rake at the command line, thanks to defaults in Rakefile:
task default: [:rubocop, :spec, :teaspoon]
but in Rails 5 it's not so apparent how to run default rake tasks now that rake has been replaced by rails. rails alone gives a list of possible commands rails responds to but doesn't run the specs. rails test seems logical but it tries to run minitest which we don't use. rails spec will run Rspec but not teaspoon or rubocop.
Where did this go? And why is something so apparently simple so hard for me to look up myself?
rails default
executes those tasks for me on Rails 5.2.1, though I couldn't find it documented anywhere.
Just create a new rake task that runs the other ones:
lib/tasks/my_extensions.rake
task :my_test do
Rake::Task[:foo].invoke
Rake::Task[:bar].invoke
end
# or the short version:
# task my_test: [:foo, :bar]
task :foo do
puts "FOO"
end
task :bar do
puts "BAR"
end
Run rails my_test and you will see FOO and BAR printed in your console.
If you don't know where to place the file to write the code above, check your /Rakefile:
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require_relative 'config/application'
Rails.application.load_tasks
It says to write them inside lib/tasks and end them with .rake, you don't need to require them. In your specific question, change my code from :foo and :bar to your specific tasks :rubocop :spec :teaspoon.
However, it looks like you are doing some BDD or TDD cycle. Check out rails Guard, it might help you better. I use it in my project and it works perfectly.

How to invoke RSpec inside a rake task?

We wrote some tests that are necessary, but very slow. So we configured RSpec to exclude them except on Solano, where we set up an ENV variable.
# spec_helper
unless ENV['RUN_ALL_TESTS'] == 'true'
config.filter_run_excluding :slow
end
That works, but I'm trying to write a rake task we can call to run every test locally by setting that same ENV variable and then running the suite. I'm having trouble figuring out how to trigger RSpec. This is what I've got now:
# all_tests.rake
require 'rspec/core/rake_task'
desc 'Run all tests, even those usually excluded.'
task all_tests: :environment do
ENV['RUN_ALL_TESTS'] = 'true'
RSpec::Core::RakeTask.new(:spec)
end
When I run it, it doesn't run any tests.
Most of the stuff I found is for triggering a rake task inside of a test, testing a rake task, or setting up a Rakefile. We're using rspec-rails, our default rake task is already set up.
To run RSpec through its rake integration, you need to both define a task and invoke it:
# all_tests.rake
require 'rspec/core/rake_task'
# Define the "spec" task, at task load time rather than inside another task
RSpec::Core::RakeTask.new(:spec)
desc 'Run all tests, even those usually excluded.'
task all_tests: :environment do
ENV['RUN_ALL_TESTS'] = 'true'
Rake::Task['spec'].invoke
end
Rake::Task['spec'].invoke did nothing when you tried it because rake turns a task name which is not a name of a defined task but is a file name into a Rake::FileTask, both on the command line and in Rake::Task. You had no 'spec' task defined, but you have a spec directory, so rake spec ran without error and did nothing.
I had a similar problem where bundle exec rake default would properly create an RSpec::Core::RakeTask, but bundle exec rake spec would instead create a a Rake::FileTask on the spec directory, with with bundle exec rake spec --trace outputting:
** Invoke spec (first_time, not_needed)
It turned out that rspec-rails was in the :test gem group, where it needed (per the docs) to be in both :test and :development.
Interestingly (?), once I did that, gems that had previously only been in the :test group were also available from the specs even when launched with RAILS_ENV=development. I assume that rspec-rails engages in some magic environment shenanigans behind the scenes.

Rails's Rake task takes exceptionally long to execute? [duplicate]

rake --tasks takes about 18s to run. This is just the time it takes to load all the tasks, as a result any task I define will take at least this amount of time to run :
$time rake --tasks
rake db:clean # Cleaning up database
rake passenger:restart # Restart Application
rake spec # Run specs
real 0m18.816s
user 0m7.306s
sys 0m5.665s
My Rakefile :
$: << "."
require "rubygems"
require "rspec/core/rake_task"
desc "Run those specs"
task :spec do
RSpec::Core::RakeTask.new(:spec) do |t|
t.rspec_opts = %w{--colour --format progress}
t.pattern = 'spec/*_spec.rb'
end
end
task :default => :spec
Any idea why rake takes to much times ?
Thanks
Try spring
Command line will look like:
spring rake -T
It will take more time running the first time, but subsequent runs will be very fast.
This solution worked for me: Faster rake tasks in Rails.
I had to do a little variation where I created a lib/tasks/no_rails directory and put all the Rake files which do not need Rails in there and loaded only those using the above method.
I like the solution Pratik mentions for the general case of loading rails for tasks that need it and not for those that don't, for any rake task without having to remember beforehand.
A less-invasive method to run a rake task that doesn't need rails is to use the -f rake option to tell rake to use a particular Rakefile. This way, rake won't go looking for rake tasks in all of rails.
For example, assuming your task above is in a file called Rakefile at the top level of your project and your Rakefile doesn't do anything that loads Rails like require File.expand_path('../config/application', __FILE__), you can do:
$ rake -f Rakefile spec
and it should run your spec task much faster. Try $ time rake -f Rakefile -T; I did this with a rails-independent Rakefile of mine and got:
real 0m1.543s
user 0m1.308s
sys 0m0.201s
The downside is you have to remember to specify this option every time, and not to specify it if you want to run a rake task from rails like rake db:migrate.
The entire rails environment has to be loaded, therefore even simple rake tasks such as rake --tasks take a while. Opening a console with rails console or script/console takes a similar time. You may try to hack Ruby or Rails to speed up rake, but too much optimization can be bad if you want to switch to a newer version later. Since the rails environment must be loaded, cleaning up routes may also help.

How to run a rake task right after rspec initializes the database

I have a Rails 2.2 app that I'm supporting and one thing that needs to be done before the app start is a small rake task to initialize and make sure the database is properly set. How can I get this task run right after rspec initializes the database. I run rspec using the rails spec command.
You could put a simple system call to your spec_helper.rb file.
An Example could look like this
# run rake task
`rake your_task RAILS_ENV=test`
RSpec.configure do |config|
...
end

MIgrations and Rspec

I'm developing a Rails application with Rspec for unit testing.
Weeks ago, Rspec used to migrate the database to the last version automatically when executing 'rake spec', but now it doesn't do it automatically, I have to implement everything for myself.
This happens in test environment, because my development data doesn't desappear.
Is my fault? I didn't change anything, I think :)
Typically what I do is use an alias command that runs both migrate and prepares the test database.
rake db:migrate && rake db:test:prepare
In your .bashrc just create an alias command like so and then run migrate_databases whenever you need to.
alias migrate_databases='rake db:migrate && rake db:test:prepare'
My solution for Rails 4:
in spec/spec_helper.rb or anywhere in testing environment initialization code:
# Automigrate if needs migration
if ActiveRecord::Migrator.needs_migration?
ActiveRecord::Migrator.migrate(File.join(Rails.root, 'db/migrate'))
end
UPD: As Dorian kindly pointed out in comments, you don't need to check separately if there are any pending migrations, because ActiveRecord::Migrator.migrate already does this behind the scenes. So you can effectively use just this one line:
ActiveRecord::Migrator.migrate(File.join(Rails.root, 'db/migrate'))
Rails 4.1 forward you can use:
ActiveRecord::Migration.maintain_test_schema!
Add at the top of your spec_helper.rb or rails_helper.rb and you're good to go. More info here.
Here's my workaround:
Rakefile:
require File.expand_path('../config/application', __FILE__)
require 'rake'
require "rspec/core/rake_task"
MyApp::Application.load_tasks
desc "Run specs"
RSpec::Core::RakeTask.new(:spec)
task :run_specs => ['db:test:clone', :spec] do
end
task :default => :run_specs
Then I run $ rake run_specs
for some reason default task doesn't default to run_specs
See if you have the following in your spec_helper.rb? Everytime you run specs, RSpec checks if there are pending migrations.
#Checks for pending migrations before tests are run.
#If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
This works even when Rails is not loaded and only does one SQL query most of the time.
if defined?(ActiveRecord::Migrator)
ActiveRecord::Migrator.migrate(File.join(Rails.root, 'db', 'migrate'))
end

Resources