Load Capistrano's environment in rails console - ruby-on-rails

What's the best way to load the Capistrano environment within the rails console?
I'd like to access the variables and methods capistrano is using in deploys such as latest_release, source etc.
Ruby debug isn't efficient when trying to hack out complicated capistrano tasks.

Within the Rails console is probably not practical as the two environments would likely come into conflict. In an interactive console isn't hard, though. You could add a Capistrano task that simply spins up one:
task :console do
require 'irb'
$config = self
ARGV.clear
IRB.start
end
This exposes the current configuration object as the global $config. Although using a global variable is a bit ugly, I couldn't find a way to switch the default context of IRB from the main object.

Related

How to tell RSpec to restart Rails before an example is run?

Is it possible to tell rspec to restart Rails before an example is run? I'm building an Engine that hooks into the Rails initialization process and the users can make some configuration changes, in an initializer, that impact how Rails and the Engine are configured. I want to be able to simulate those configuration changes, restart rails and test the result.
I haven't done this feat yet, but as best practice I think your engine tests should be part of the engine and should have minimal dependencies.
Some approaches I've seen and believe you should try and combine:
Mock a minimal parent rails app to test your engine.
Write multiple dummy apps to test with.
Instead of loading the entire rails application, you can split spec_helper and rails_helper in smaller parts, also gaining in setup time.
You can write custom rake tasks to switch environment before spawning a new test thread.
You can also overwrite at runtime the configuration values which reflect in your test (plus: use dependency injection!).
If your initializer is complex enough, you could extract it in a testable helper and wire it up in your test initializers.
Also, there seems to be a gem for that: Combustion.

Loading Rails environment and classes from an independent gem

I have an app environment that we validate using an automated script. It populates some setup data in the Rails app and then sends a number of requests to validate some external workflows. Afterwards it removes the setup data from the database and cleans up other associated files.
The problem is I can’t have the scripts (currently rake tasks) in the application code. The script code needs to be independent from the application codebase for regulatory reasons.
Can anyone provide a way to load the Rails environment and classes in the rails application from a gem?
Right now I check the gem is run from the application root folder and then require the Rails environment.
require Dir.pwd + '/config/boot’
The issue is I can’t figure out how to reference the Rails app classes.
I think this is the proper way to load a Rails app (found in config.ru): require ::File.expand_path('../config/environment', __FILE__). In fact you can copy and paste that into a regular irb session to turn it into a 'rails console' session.
So the key seems to be to require your config/environment and that should allow you to use your app models normally.

change rails environment from within ruby file then change back

I have a test-automation app that runs tests against user params against a rails app.
The tests execution in the Ruby app looks like this:
config = RSpec.configuration
json_formatter = RSpec::Core::Formatters::JsonFormatter.new(config.out)
reporter = RSpec::Core::Reporter.new(json_formatter)
config.instance_variable_set(:#reporter, reporter)
RSpec::Core::Runner.run(["#{Rails.root}/spec/features/example_spec.rb"])
puts json_formatter.output_hash
This works great but runs in the current environment, i.e. development.
I want to change the Rails environment so that this code is executed in the test environment and then change it back.
Does anyone know how to do this?
thanks
Richard
You can always change the environment for a single (or set of) commands like this in unix-like environments:
RAILS_ENV=testing bundle exec rspec
or whatever you need to execute. You could, for example, define a custom rake task that contains your spec-running logic and call that as I outlined above.
Using this concept and taking it a step further, you could execute shell commands directly from Ruby and have a custom environment variable set for only this command. In this shell commands you could execute arbitrary Ruby code (e.g. via ruby -e ...) or even call another Ruby file that properly initializes whatever you need within your desired environment.
I think it would be really bad practice to try to change the current environment from within your code, even if it is somehow possible. I would personally stick with a custom, dedicated, rake task which I can call from my command line with whatever environment I need.

run ruby script in rails application

This may be a stupid question but I was just wondering where, or if its possible to run a ruby script which is kind of unrelated to the rails application I would like it to run in. To clarify, I am working on an automation test suite that is written mainly in bash, but I want to create a front end (my rails application) that allows other users to run automated tests not through the command line. So I guess basically I want a user to select certain parameters, from a database or form fields, then take those parameters and pass them to a ruby script which calls my bash automation script.
I hope this is clear. Thanks!
If you want to call a script from a rails app it gets complex. You would want to use a background job or some sort of queue to run these jobs because they do block the server and your users would be waiting for the call to complete and the results to load, most likely hitting a timeout.
See delayed_job
and you might want to try creating a small wrapper script in ruby that can interface with your application.
Good luck!
for short tasks you should use system or popen
when tasks are longer then they are still needed in case of delayed_job
You can add a script to your scripts folder in the root of your rails app. Start your script like this:
your script can be [name here].rb
The reason why we load in the environment is so we can use rails models and rails related things in your script:
#!/bin/env ruby
ENV['RAILS_ENV'] = "production" # Set to your desired Rails environment name
require '/[path to your rails app on your server]/config/environment.rb'
require 'active_record'
If you want to run this on your server, then you have to edit your crontab on your server. Or you can use the whenever gem (which I''m having trouble with, but the entire universe doesn't). Conversely, if you have heroku, then there's the heroku scheduler that makes running scripts easy.
You can run Ruby code with rails runner.
… let us suppose that you have a model called “Report”. The Report model has a class method called generate_rankings, which you can call from the command line using
$ rails runner 'Report.generate_rankings'
Since we have access to all of Rails, we can even use the Active Record finder method to extract data from our application.
$ rails runner 'User.pluck(:email).each { |e| puts e }'
charles.quinn#highgroove.com
me#seebq.com
bill.gates#microsoft.com
obie#obiefernandet.com
Example taken from The Rails 5 Way by Obie Fernandez.

How to use a Rails environment variable in Capistrano deploy script?

If I have a constant in my Rails environment.rb, for example...
SOME_CONSTANT = 3
Is it possible to access this in my capistrano deploy.rb somehow? It seems simple but I can't figure out how.
This ended up working:
created a file config/initializers/my_constant.rb
put my constant in there (rails automatically loads files there so I can use the constant in my app)
then in deploy.rb added load 'config/initializers/my_constant' so it could be used there as well.
You should access it via the ENV[] hash (this is a Ruby thing), here is an example using the TERM environmental variable.
puts "Your Terminal is #{ENV['TERM']}"
If you need a ruby constant, from your rails environment, you should load it:
require 'config/environment'
Beware that this will load your whole application environment, you should think to use something like AppConfig, or SimpleConfig (insert other tool here) to store configurations, then you need only load the tool, which processes your config files.
Why not define these constants in a file in lib/ and then require the file in both your Rails app and your Capfile?
As the value is not only used by the rails app, I would probably store such configuration information in a language agnostic format (yaml, json, ini, xml) which can be easily parsed by different tools without fear of possible side effects.

Resources