Loading Rails environment and classes from an independent gem - ruby-on-rails

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.

Related

Rails adding translations to a running rails environment

Is there a way to manually inject a translation through the Rails console ?
Suppose I am working on a dev environment, and I want to test some code in a production console (eg to test some statistics on real data).Problem is, the code I want to test relies on new translations that didn't exist (or were changed) in the production environment.
So my code returns a lot of translation_missing
Can I inject the missing translations ? Via a hash or a YML file ?
I18n.load_translations(hash_or_file)
Usually Application instances that serve http requests (for example running under Unicorn/Puma) are not available via Rails console. When someone login to production server and type $RAILS_ENV=production rails c it starts another application process. Translations dictionary is a kind of in-memory cache and usually it is not possible to change that cache for/from another process (in general). You can reload translations only for application instance that started by Rails console, but not for running server.
Only one way to hot reload translations is adding kind of a hook into source code of application to re-read YAML file, but it seems better just restart application server.
UPDATE: For testing purposes I18n cache could be modified like:
I18n.backend.send(:translations)[:en][:date][:formats][:default] = "%Y-%Z"

Are *all* specs for an engine expected to live in the dummy Rails app?

I'm using RSpec to test some engine models.
My preference would be to test the parts that are independent from the (dummy) app outside of the app. I'd prefer to have non-app tests live at the top level and not be hidden in spec/dummy/spec.
The problem is that by default (AFAICT) engine initializers aren't run if the engine isn't mounted.
Should I just go with what appears to be expected, i.e., put all my specs in the dummy app and run RSpec from the dummy app's directory, even when the tests aren't related to the app as a whole?
Or should I run initializers from a top-level spec helper for the non-app specs? Or some other way?
If I do, are there dummy app repercussions?
If you have a dummy app, you do not have to have your specs in the dummy app dir structure.
The following is a simplified version of what permitters v0.0.1 uses.
In spec/spec_helper.rb:
ENV['RAILS_ENV'] = 'test'
app_path = File.expand_path("../dummy", __FILE__)
$LOAD_PATH.unshift(app_path) unless $LOAD_PATH.include?(app_path)
# if require rails, get uninitialized constant ActionView::Template::Handlers::ERB::ENCODING_FLAG (NameError)
require 'rails/all'
require 'config/environment'
require 'db/schema'
require 'rails/test_help'
require 'rspec/rails'
# rspec config, etc.
Beyond that, I want to say that all of the modifications I made in the dummy app in spec/dummy were either to allow it to be run in different versions of Rails (3.1.x, 3.2.x, and 4.0.x) or because I was configuring things for the gem in the dummy app.
I also currently like using the appraisal gem and TravisCI for continuous integration. The setup I'm using allows me to test in various versions of Rails with various versions of gems and not a lot of maintenance overhead. It needs a little cleanup, but it works well.
If you wanted to not load the Rails environment for a certain set of specs (i.e. not load Rails for some specs_, you could definitely do that. You could just set an env var in the task definition in the Rakefile or at command-line and then look for that in spec_helper.rb to determine whether to load things or not. Then you could have various Rake tasks that spawn new processes that set the env var or not depending on whether a set of tests needs Rails. I wouldn't necessarily worry about that though if everything is meant to be run in Rails, unless you really need to isolate it.
For more info on different ways to test with dummy apps, you might see this question: Strategies for gem tests to ensure the gem works with Rails 3.x and 4.0.

How do I develop and distribute a Ruby CLI app with a backing database?

I'm writing a command line program that maintains state in a database. Are there any templates for setting up an app folder structure similar to Rails? I.e. have infrastructure for:
Having all files in lib, app, etc directories auto-required in all of those files
Having multiple database environments like dev, test, prod
Having Rake tasks for runnning tests in a test database
So, this is essentially a Rails layout but without anything to do with serving web-pages.
Once I have this kind of app, I want to distribute it via a gem, but have it initialize a database in the user's home directory when installed, maybe in ~/.myapp.
What would you recommend?
If you just want a gem based application you could look into this guys development here:
http://www.acmesprockets.com/node/24
You could just forgo Rails and using stock ruby with OptionParser and ActiveRecord or Sequel.

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.

Using ActiveRecord models in a gem - how to handle database config

I have several active record models in a rails app and I would like to extract these models into a gem so that I can easily use them in several web apps. The process seems pretty straight forward, except for passing along the configuration for the models. Do I:
Add the configuration yaml file to the gem, thus assuring the databases will always be the same across all apps - seems rigid, esp for testing and dev, though the databases for production will always be consistent.
Use the ActiveRecord hooks to look for a database.yml file in the config directory with the database defined? If so, which hooks should I use?
This is a stupid idea. If you have a better way to handle this, I'm all ears. I'd prefer not to copy and paste.
You should use the host rails app's database config. Your plugin or gem should contain just the database migrations, and a rake task to run them from the host rails app (e.g. myplugin:db:migrate)
If your models need some other configuration file, you should create a rake task (e.g. myplugin:install) to copy it to your host app's config directory. (This task can call the db:migrate task automatically as well.)
Why do you want to embed the database.yml file inside the gem? Each rails application should use it's own database.yml
I would put all the models into a plugin and include that in each rails application that needs the models.

Resources