Rails: Running more than one rake task at once? - ruby-on-rails

Been loving rails, but still struggling with how long it takes to run tasks from the command line.
I'm wondering if it's possible to combine multiple rake tasks without reloading the environment each time. For example, if I run
rails generate rspec:install && rails generate model test_model title:string && rake db:migrate
it will spend 10 seconds loading up rails to run the rspec install, then another ten seconds to load up the environment for generate model, then another for the migration. Is there a way to keep the same environment open for all 3 commands?

Take a look at the rails-sh gem - it boots the Rails environment, and then presents a command line interface, so you can run your command within it. There are limitations when using it (I don't think you can change your RAILS_ENV), but for your use-case, it should be perfect.
If your commands are just rake tasks, you can use spaces to separate them, e.g.:
rake db:migrate && rake db:test:clone_structure
would become
rake db:migrate db:test:clone_structure

Related

What is the difference between rails and rake?

What is the difference between commands rake and rails in Ruby?
Which one is faster and why?
The difference is in what binary is being called.
If you were to call bundle exec which rake within your Rails app root directory, you'd get something like /home/[USERNAME]/.rbenv/versions/2.5.5/bin/rake and for bundle exec which rails, you'd get /home/[USERNAME]/.rbenv/versions/2.5.5/bin/rails. From there you can cat (cat /home/[USERNAME]/.rbenv/versions/2.5.5/bin/rake) both these paths and see similar code is being ran for each, but the end of the files is different.
rails
gem "railties", version
load Gem.bin_path("railties", "rails", version)
rake
gem "rake", version
load Gem.bin_path("rake", "rake", version)
Here they're both calling load on Gem.bin_path but with different arguments, which are attempting to load separate gems in. You can follow the code further by running a irb/pry/rails console, and setting up the needed require 'rubygems' and version = ">= 0.a", then run Gem.bin_path("railties", "rails", version) and Gem.bin_path("rake", "rake", version) to see what the load is actually trying to run. I'll admit it'll become a bit of a rabbit hole before you come across the logic that eventually ends up identifying a rake task argument passed to rails and it proxy's it to Rake and stop there and defer to this SO answer for the rest.
When rails is ran and passed arguments which were intended to be ran by rake, it will attempt to first find if it was an actual argument intended to be given to the rails command, determine that it wasn't, then attempt to run it as a rake command for you for overall naming simplicity added in by the Rails team in Rails v4.
So which is faster to run? rake for actual rake tasks, as it'll bypass the extra logic in needing to determine it was being passed rake arguments. But also rails specific arguments cannot be ran with rake e.g. bundle exec rake generate will not work (unless you have a generate task). If in doubt, run bundle exec rails --help and in at least Rails v5, it'll output which arguments are rails specific and which are rake specific.
rake is a Make-like program implemented in Ruby.
rails is a web framework, which also has some rake tasks.
This means that you can have a ruby program with rake but without rails, but not the other way around.
By itself, rake will be faster because you don't need to load the whole rails application.
But when launching a rake task, it can have dependencies, for example the :environment dependency in a rails app, which tells rake to load the rails environment and quite a bit of your application depending on the current environment.
In this case, the initialization of a rake task may take as long as a rails command.
Please note that the actual task run needs also to be taken into account, it can be very short or take several minutes.
For example, rake db:migrate, which is a rails task available by default, runs the migrations on the database, which can be time-consuming if the database is already populated and/or you have a lot of migrations

rails routes vs rake routes [duplicate]

I'm new to rails. I noticed when generating data migration in rails 5, some people use rails db:migrate over rake db:migrate. Can someone explain the difference between the rails vs rake command in database migration? Does it mean rake command is obsolete in rails 5?
many thanks
Rails core team decided to have consistency by enabling rails command to support everything that rake does.
For example in Rails 5 commands like db:migrate, db:setup, db:test etc which are part of rake command in Rails 4 are now being supported by rails command. However you can still choose to use rake to run those commands similar to how they were run in Rails 4. This is because Rails community has introduced Rake Proxy instead of completely moving the command options from rake to rails.
What happens internally is that when rails db:migrate command is executed, Rails checks if db:migrate is something that rails natively supports or not. In this case db:migrate is not natively supported by rails, so Rails delegates the execution to Rake via Rake Proxy.
If you want to see all the commands that is supported by rails in Rails 5 then you can get a long list of options by executing rails --help.

rails db:migrate vs rake db:migrate

I'm new to rails. I noticed when generating data migration in rails 5, some people use rails db:migrate over rake db:migrate. Can someone explain the difference between the rails vs rake command in database migration? Does it mean rake command is obsolete in rails 5?
many thanks
Rails core team decided to have consistency by enabling rails command to support everything that rake does.
For example in Rails 5 commands like db:migrate, db:setup, db:test etc which are part of rake command in Rails 4 are now being supported by rails command. However you can still choose to use rake to run those commands similar to how they were run in Rails 4. This is because Rails community has introduced Rake Proxy instead of completely moving the command options from rake to rails.
What happens internally is that when rails db:migrate command is executed, Rails checks if db:migrate is something that rails natively supports or not. In this case db:migrate is not natively supported by rails, so Rails delegates the execution to Rake via Rake Proxy.
If you want to see all the commands that is supported by rails in Rails 5 then you can get a long list of options by executing rails --help.

Automatically running rake tasks when you switch branches in git

Whenever I switch branches I am having to run the commands:
rake db:drop
rake db:migrate
rake db:setup
Is there a way to automatically run these commands in terminal for my application? I am developing a ruby on rails application and have many branches on GitHub. Is there a file I can add to that will automatically run this command?
For example, I will do this "git checkout branch101"
and then I want to run the 3 commands above.
Save this shell script to the file /path/to/repo/.git/hooks/post-checkout, and make it executable.
#! /bin/sh
# Start from the repository root.
cd ./$(git rev-parse --show-cdup)
# drop migrate and set up.
rake db:drop
rake db:migrate
rake db:setup
What you're looking for is something like Guard that runs your test suite whenever code changes in your repo. You should be able to tweak Guard to run your rake tasks instead of tests.
Railscasts has a great screencast explaining the Guard.
After a quick google search, looks like there's a gem available that can run rake tasks for you: guard-rake . Unfortunately, it doesn't seem to be widely used though.

Do I have to run rake db:test:load each time manually before runnings tests?

I'm new to Ruby on Rails.
I'm trying to set up a simple WebApp via Scaffolding. And using RSpec for my tests. Now after the scaffold command:
rails generate scaffold VideoSegment file_path:string short_name:string description:string
I ran rake db:migrate, but thats clear, bringing the data to my development database.
But the tests where not green before I did:
rake db:test:load
To bring the schema of my development database to the test database. Isn't there a way to automate this step? Or do I have to load test database again after each scaffold?
PS: Of course I know Scaffold is not doing the finest things, but for my proof of concept need it's sufficient.
Thanks for any suggestions.
Whenever you run rspec it will prepare the test schema for you using the task: db:test:prepare
So after generating migrations you have to do rake db:migrate to update the development schema and then run you spec which will automatically prepare the test database for you.

Resources