Run two ruby scripts from rake task - ruby-on-rails

So this is a simple rake task:
task :map_reduce do
puts 'Running map reduce scripts...'
ruby "#{PADRINO_ROOT}/map_reduce/raw_visits_map.rb '03-08-2016' 90" && ruby "#{PADRINO_ROOT}/map_reduce/raw_visits_reducer.rb"
end
The first script outputs the result in STDOUT to be further read by the so called 'reducer'.
In the terminal, I am able to run those two scripts like:
ruby first_script.rb param1 param2 | ruby second_script.rb
So the second script can read from STDOUT like
res = ARGF
But how can I line up the 2 executions inside that rake task?
How I wrongfully tried it's not working.

It might be easier to require the ruby class directly into your rake task, but if you want to run a script from a rake task you can run any shell code in Ruby using backticks, like this:
`ruby first_script.rb param1 param2 | ruby second_script.rb`

Perhaps you should use backticks or the %x syntax.
Also see answers to: Ruby, Difference between exec, system and %x() or Backticks

Related

Environment variables not correctly set

I am using whenever gem. I wanted to set my env variables prior to the scheduled task. The 2nd line in the code below was the command I wanted to run in my schedule.rb file. But looks like I can't get it done so I commented it out and tried in different ways. Still nothing seems to work. Printing env inside the ruby code seems to show the needed variable correctly, but after running 'bundle exec whenever' and checking in the terminal with env command, the variables do not seem to be there. What is wrong here ?
every :hour do
# Run shell script to assign variables and continue the rake task
#system "for line in `cat config/myEnvFile.env` ; do export $line ; done"
f = File.open("config/myEnvFile.env", "r")
f.each_line do |line|
j = line.split(" ")
arr = j.first.split("=")
system "export #{arr[0]}=#{arr[1]}"
system "env"
# This line below is also another way but still nothing works
ENV[arr[0]] = arr[1]
end
rake "task:continue_doing_my_task"
end
The code in your every-block is executed when whenever --update-crontab runs, not every hour.
You need to make the command generated by rake "task:continue_doing_my_task" load these variables, either exporting them in-line using bash syntax (which gets ugly) or using dotenv as suggested in the comment by #Anthony.
See my answer to your follow-up question, which explains this in more detail.

How to use an alias or function in zsh to check for a socket and run the appropriate command?

I have an interesting problem when using Zeus with Rails. My shell script writing is lacking to say the least.
Ok, so zeus boots a rails app in under a second and makes tests etc. much faster. However, you must append zeus before any rails command. Example, zeus generate controller or zeus rake db:migrate. I would rather keep the regular rails commands while running zeus. Example, rails generate controller or rake db:migrate.
I have these 3 commands aliased
alias rails='zeus'
alias rspec='zeus rspec'
alias rake='zeus rake'
However, if zeus is not running, I get this error
error: Can't connect to master. Run zeus start first.
So the problem I'm trying to solve is I would like to use the same rails commands whether zeus is running or not
Now when I run zeus start it seems that zeus.sock is present. So I guess I could check for the presence of zeus.sock in a function and then set up the alias accordingly. Im just not sure the best way to do this. I know that -S is true if file exists and is a socket. something like
if [ -S zeus.sock ]; then
# not sure where to go from here
Anybody have a suggestion on the best way to do this?
thanks in advance
You can use a function, perhaps like this:
zrail() {
if [ -S zeus.sock ]; then
zeus $*
else
rails $*
fi
}
Then you call it like:
zrail generate controller

Run Rails commands outside of console

With my large application, the Rails console takes a while to load up. Is there a way to single commands more easily?
I'd also like to be able to automate stuff, and echo "query" | rails console isn't a great way to do things.
Thoughts?
EDIT: What about a long-running process that I can ping queries to whenever I have need?
There are two main ways to run commands outside console:
Rake task which depends on :environment
rails runner (previously script/runner), eg:
$ rails runner "query"
Both are pretty well documented on the rails guide: https://guides.rubyonrails.org/command_line.html#bin-rails-runner
Both of these methods will still take the same time as a console to fire up, but they are useful for non-interactive tasks.
Just pipe it in:
echo 'puts Article.count' | bundle exec rails c
It should now be a lot faster than when then the question was originally asked, because of Spring. It's not immediate, but still a lot faster than spinning up the whole app. Use this for the fast lane, it should run in under a second (assuming your required command is fast):
echo 'puts Article.count' | spring rails c
If you really want a single long-running process, you could easily do it by creating a controller action that simply runs whatever you POST to it, then send commands to it using curl behind an alias. The action would of course be completely insecure and should be triple-guarded against running anywhere near production, but it would be easy to setup.
Solution: bundle exec command allows us to run an executable script in the specific context of the project's bundle - making all gems specified in the Gemfile available to require in Ruby application. In addition it eventually avoids any conflicts with other versions of rake installed globally.
echo '<command>' | bundle exec rails c
for more information look at the documentation of bundler
example:
configuration_item=$(echo 'ConfigurationManager.getKey("authentication_method")' | bundle exec rails c )
echo $configuration_item
#output:
MFA_authentication

How do you write a task to run tests in Rails 3?

I would like to write rake tasks to customize tests. For example, to run unit tests, I created a file with the following code and saved it as lib/tasks/test.rake:
task :do_unit_tests do
cd #{Rails.root}
rake test:units
end
Running rake do_unit_tests throws an error: can't convert Hash into String.
Working in Rails 3.0.7 and using built-in unit test framework.
Thanks.
There is no need to cd. You can simply...
task :do_unit_tests do
Rake::Task['test:units'].invoke
end
But if you really want to cd, that's how you call shell instructions:
task :do_unit_tests do
sh "cd #{Rails.root}"
Rake::Task['test:units'].invoke
end
Well, in fact there is a shorter version. The cd instruction have a special alias as Chris mentioned in the other answer, so you can just...
task :do_unit_tests do
cd Rails.root
Rake::Task['test:units'].invoke
end
If you want to go further, I recommend Jason Seifer's Rake Tutorial and Martin Fowler's Using the Rake Build Language articles. Both are great.
You're trying to interpolate a value that's not in a string, and you're also treating rake test:units like it were a method call with arguments, which it's not.
Change the cd line so you're calling the method with the value of Rails.root, and change the second line to be a shell instruction.
task :do_unit_tests do
cd Rails.root
`rake test:units`
end

running single rails unit/functional test

As title.
ruby test/functionals/whatevertest.rb doesn't work, that requires me to replace all require 'test_helper' to require File.dirname(__FILE__) + '/../test_helper'. For some reason most of those test templates have such issue, so I rather to see if there is a hack I could get around it.
The following answer is based on: How to run single test from rails test suite? (stackoverflow)
But very briefly, here's the answer:
ruby -I test test/functional/whatevertest.rb
For a specific functional test, run:
ruby -I test test/functional/whatevertest.rb -n test_should_get_index
Just put underscores in places of spaces in test names (as above), or quote the title as follows:
ruby -I test test/functional/whatevertest.rb -n 'test should get index'
Note that for unit tests just replace functional with unit in the examples above. And if you're using bundler to manage your application's gem dependencies, you'll have to execute the tests with bundle exec as follows:
bundle exec ruby -I test test/unit/specific_model_test.rb
bundle exec ruby -I test test/unit/specific_model_test.rb -n test_divide_by_zero
bundle exec ruby -I test test/unit/specific_model_test.rb -n 'test divide by zero'
Most importantly, note that the argument to the -n switch is the name of the test, and the word "test" prepended to it, with spaces or underscores depending on whether you're quoting the name or not. The reason is that test is a convenience method. The following two methods are equivalent:
test "should get high" do
assert true
end
def test_should_get_high
assert true
end
...and can be executed as either of the following (they are equivalent):
bundle exec ruby -I test test/integration/misc_test.rb -n 'test should get high'
bundle exec ruby -I test test/integration/misc_test.rb -n test_should_get_high
Try this:
ruby -Ilib:test test/functionals/whatevertest.rb
On Linux? why not try (cd test && ruby functionals/whatevertest.rb). Note, the parentheses are important as otherwise your current directory will change to the subdirectory. What it does is fork another shell, change to the subdirectory in it, and run the test.
If you are on Rails 4, then rake supports file / directory arguments. Example:
rake test test/unit/user_test.rb
rake test test/unit
The answer for the title question would be:
ruby unit/post_test.rb -n selected_test # use to run only one selected test
but for the body of the question tvanfosson gave a good answer.
After spending endless hours on this, I finally found the solution (in Rails 3.0.7) :
ruby -I test test/functional/users_controller_test.rb -n "/the_test_name/"
Note, this only works with underbars (_) in the command. It does not work with spaces!
Define the test with spaces as:
test "the test name" do
This solution uses pattern matching, so you can use part of the test name. If the test is "should do foo", then either of the following will work as well.
ruby -I test test/functional/alerts_controller_test.rb -n "/foo/"
ruby -I test test/functional/alerts_controller_test.rb -n "/do_foo/"
The following (with spaces) will not work:
ruby -I test test/functional/alerts_controller_test.rb -n "/do foo/"
most conventional method for 2 and 3 is:
ruby -I test test/functional/your_test_file.rb

Resources