Rails adding translations to a running rails environment - ruby-on-rails

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"

Related

Rails 5: where to put start-up check that doesn't trigger unless serving the app?

I was hoping to put in some sanity checks on Rails (v5) application startup to ensure that all necessary ENV variables / configuration was properly set.
However, I want to run these checks only if I'm actually running the server. I don't want it happening any time the Rails environment is loaded, e.g., running tests, asset precompilation (including with RAILS_ENV=production), rails c, etc.
Is there a place in the Rails start-up chain that I could insert those sanity checks without affecting all Rails-related tasks?
This is an interesting challenge. The problem is that (virtually) the entire application is loaded regardless of whether you're running tests, pre-compiling assets or anything else. The only thing that's different is that you have the process residing in memory.
Have you considered creating a production validation task that you run in your deployment process prior to launching the server process?
EDIT : Additional Thoughts
Looking at the rails server command, it calls an instance of Rails::Server, a subclass of Rack::Server (whereas rails console calls an instance of Rails::Console).
You have two choices:
Task (Best Choice)
Create a rake task that you execute during your deployment process prior to starting the server process. It should raise an error if the configuration is not valid, which should halt your deployment process.
I strongly suggest this approach. It's self-contained, you can test it far easier, and you don't have to meddle with the internals of the server process.
Monkey Patch Rails::Server#start
Monkey patch Rails::Server (probably Server#start) so it runs your validation logic if it's running in a production environment. If it doesn't, throw an error. This is ugly, you won't be able to test it easily, and it violates my sense of order :P
I know you don't want this logic to run in production environment in non-server use cases but my production deployments are always configured completely regardless of what I do with them. I've been debating setting up a validation step myself.

Different environments included in Ruby on Rails

Can someone explain to me what the Rails environments are and what they do? I have tried researching myself, but could not find anything. From what I gather, the environments are:
Development
Productions
Test
Each "environment" is really just a config. You can launch your app in various different modes, and the modes are called "environments" because they affect the app's behaviour in lots of different ways. Ultimately, though, they are just configs.
BTW you can't have looked very hard when you looked "everywhere", because i just googled "rails environment" and the top result was this
http://guides.rubyonrails.org/configuring.html
which is the official explanation of configuring the rails environment.
From what you have provided in your question, it seems that you are asking:
"What are the difference between each environment configuration in Rails?"
Rails comes packages with 3 types of environments. Each have its own server, database, and configuration. See Rails Guides: Configuration for more information on options available to you.
Setting up the environment
To set your Rails environment, you will want to enter in command line:
export RAILS_ENV=<env>
Where <env> can be test, development, or production. Setting this environment variable is crucial, as it will determine what gems are installed, or what env is touched when running rails console or rails server.
Included in configuration is the gemset used for the app. When you run rails new, you will find a Gemfile with groups test, development, and production. These groups correspond to the environment currently set. When the environment is set to one of those, running bundle install installs all gems related to that group (and gems not listed in a group).
Included environments
test is designed for running tests/specs. This database will likely be bare bones, except for seeds you may call before running the suite. After each test is complete, the database will rollback to its state before the test began. I do not recommend launching rails server, as running tests (via MiniTest or RSpec) will do this for you, and close the server once the suite is finished.
development allows you to "test" your app with a larger database, typically a clone of production. This allows you to test actual real-world data without breaking production (the version that customers or end-users will experience). To view the development environment in action, change the RAILS_ENV and launch rails server. This is good for deciding how you want your pages to look (CSS, HTML). It is also good practice to briefly "test" your app yourself, clicking around making sure everything "looks" good and the JavaScript works.
production is reserved for the customer and end-user. Configuration includes the actual domain of the app, which ports to use, and initializers or tasks to run. You do not want to play around with your database, as it may be customer-impacting. Ideally, the app should work as best as it can, since this is considered your "final product."
Here are some good reads about Rails Environments
http://teotti.com/use-of-rails-environments/
and
https://signalvnoise.com/posts/3535-beyond-the-default-rails-environments
good luck !!

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.

Can I change config.cache_classes programatically in Rails 3?

I have some iPhone client tests that run against my development rails server. The whole suite runs an order of magnitude faster if I turn on class caching in the Rails config. On the other hand, that slows down development when I'm not actually running the tests.
I want the test suite to hit an action at the beginning to turn on class caching and another action at the end to turn class caching off again.
Is this even possible? If so, how?
Not without some serious hacking. Rails goes to quite a lot of trouble to make sure your files are reloaded on every request (when cache_classes=false). The value of the cache_classes configuration variable is used by initializers in several places not the least of which being:
using require to load ruby files when cache_classes is true (meaning they are no longer reloadable)
setting up dispatcher callbacks to reaload the application on every request when cache_classes is false
You do have access to the value of the cache_classes variable, and you can even change it if you like:
Rails.configuration.cache_classes = true
But, this will have no effect on the running rails instance as the initializers where that value is used only run once when the rails app starts up.
What this means is this, unless you're prepared to invest some serious time and hacking effort you can't really avoid a restart of your server. So, what you need to look at is controlling this restart process via your test suite.
For example you can try to restart rails from within rails. This would allow you to define an action that your test suite can hit right before it begins executing (to restart the server in the right mode), and another action which the server can hit after all tests have finished, to restart everything with cache_classes set to what it used to be. You would control the value of cache classes via an environment variable like this post suggests.
It would still require a bit of work to set all of this up and get it to hang together, but this is probably your best bet if you want an 'auto-magical' solution.
I don't think doing what you suggest will work.
But I suggest you may be looking for the wrong solution.
If what you want is to access your development database from your iphone testing,
then why not add a new environment.
Add a new file config/environments/iphone_dev.rb
require File.dirname(__FILE__)+"/development.rb"
config.cache_classes = true
And in your database.yml (or mongoid.yml or whatever)
iphone_dev:
host: localhost
database: my_app_development
There is no reason the database cant be the same
Now just run rails server -eiphone_dev -p3001
You should have a server, almost the same as your dev server,
but running on a different port, with caching enabled.

If you modify code in the Rails console will that affect a server running in parallel?

Is it possible to run "rails console" in one shell and then "rails server" in another and then have code changes in the console permeate to the running application? Presumably this isn't possible, but I'd just like to check if there is a way.
Edit: Both are running in the same environment. And by code changes I mean changes to class definitions (e.g. rewriting a method on the Post model).
If you modify any data, that will indeed permeate. However modifications to methods done on the fly by opening classes and "monkey-patching" them will not affect your running application - unless your modified method modifies data.
However, it is always advisable to run the console in a different environment with different data to avoid harming a running application.
If you are changing data in your console IN THE SAME ENVIRONMENT then it will be changed in the browser.

Resources