How to debug Rails I18N lookup? - ruby-on-rails

In the Rails docs there seem to be different default locations for I18N strings, depending if the I18N-lookup was initiated from a view, model / validation, controller, helper, ..., if it's a label, etc...
How can I see where Rails is trying to lookup things by default, e.g. when I just use t('.something') ?

You can monkey patch the I18N backend in development mode to print out the I18n keys that are looked up in the backend.
Check here:
http://www.unixgods.org/Rails/where_is_Rails_trying_to_lookup_L10N_strings.html

the standalone I18n.t does not prefix your translation key in any way, here are the helper methods/modules that are responsible for the rails' magic:
(click on the "source" link below the methods' description to see what's happening inside)
ActionView:
http://api.rubyonrails.org/classes/ActionView/Helpers/TranslationHelper.html#method-i-t
scope_key_by_partial
ActiveModel:
http://api.rubyonrails.org/classes/ActiveModel/Translation.html#method-i-i18n_scope
AbstractController
http://api.rubyonrails.org/classes/AbstractController/Translation.html

The solution above does not help find what file a key is being looked up in. I did not find any elegant solution to this, below is the best method I came up with. The instructions would have to be adapted for a production box.
Open up a rails console bundle exec rails c
Run I18n.load_path.join("\n") and copy this to your clipboard. If you use pry with some clipboard helpers, just run copy in the console
Open up a new terminal window and run pbpaste | ack 'en.yml$' | xargs ack 'key:' This will print out a list of files containing the key I18n is trying to access

In rails 3.2 (maybe also lower versions), a span is produced by the t - helper in views that shows you which key was searched for the translation. This isn't a solution for all cases (from controller and so on), but I think it can be the answer for a lot of people who search for this question, where the full monkey patch from above would be over the top (the monkey patch also works for me in i18n 0.7.0 and gives more detail)
title="translation missing: de.<path to key>"

If the translation you're trying to debug is being set in the controller, there is a simple solution:
Set a variable in the controller to a tag that's doesn't exist and read the path return by the translation missing warning.
For instance in the controller
#test = t('.choco_pizza')
In your view:
<%= #test %>
Will return:
translation missing: fr.unexpected_namespace.controller_name.action_name.choco_pizza

Related

How to delete a helpers file in Rails 5?

I'm new to Rails, and after using rails g controller Users to generate a users controller, I decided to remove (i.e., rm) the generated helper in app/helpers/users.rb, because I realized I didn't need it. It seems ugly to keep a bunch of empty files around to me. This broke my app. When I try to visit any page in my, or run a test, I get this error: Couldn't find UsersHelper, expected it to be defined in helpers/users_helper.rb.
I fixed it by manually re-creating that file, but how do I get rid of it? Is that just not supported?
Edits based on questions people asked
The helper does not appear to be referenced explicitly anywhere, grep -Ri UsersHelper . only returns results for the module itself and a bootsnap cache file. The same command with :helper 'user' or 'helpers/users' returns nothing.
If Rails is telling you that it can't find UsersHelper then it means that the module is called somewhere else in the project. When the page shows you the couldn't find message, it should also indicate the offending file where UsersHelper is being included (same with the test output). If you remove this reference, you should have no problem removing the module (or directory).
I sort of figured out the issue, but I still don't understand it.
I am using some url helper functions: user_url(:id) and new_user_url, and these apparently require the helpers to exist even though they are not explicitly defined there. If anyone can explain in more depth what's going on, I'd appreciate it.

Is it possible to have hyphens in a yaml key for use in my I18n en.yml file?

For example :
en:
foobar-does-not-work: 'This is my value'
Then if I do :
t(foobar-does-not-work) # => returns nil
This will not parse in Ruby's yml. Is there some way to make it work though? My keys are based on URL's which have dashes ( - ) in them.
Which version of ruby are you using? Can you show us your code and the error?
It works for me:
> require 'yaml'
> YAML.load_file('foo.yml')
{"en"=>{"foobar-does-not-work"=>"This is my value"}}
And it works when I add it to my en.yml:
> I18n.t('foobar-does-not-work')
=> "This is my value"
Have you checked the value of I18n.locale?
Clearly there is an underlying problem that needs to be ferreted out. There is very good tool which analyzes your i18n YAML as the Rails app, which I have found extremely helpful in debug.
Install and run this gem i18n-tasks: https://github.com/glebm/i18n-tasks.
To create a comprehensive report of the your i18n components:
$ i18n-tasks health
From their spec:
This gem analyses code statically for key usages, such as I18n.t('some.key'), in order to:
Report keys that are missing or unused.
Pre-fill missing keys, optionally from Google Translate.
Remove unused keys.
Thus addressing the two main problems of i18n gem design:
Missing keys only blow up at runtime.
Keys no longer in use may accumulate and introduce overhead, without you knowing it.
I'm not sure the gem was intended to be used as an i18n debug tool, but I have found it to be useful for debugging hard to find problems in i18n.
I think you are just using the wrong key when calling the t method. Remove 'en' from the key. It should be:
t('foobar-does-not-work')

How to use the `:include:` directive using RDoc?

I am using Ruby on Rails 3.0.7 and I am writing some documentation for my application using RDoc. Since I have not found on the Web some good documentation with examples, what I would like to know is how to use the :include: directive at all.
Can you make me an example of using that in application files?
Here is the doc: http://rdoc.rubyforge.org/RDoc/Markup.html
And here is a very basic example:
First a ruby file, say /tests/my_func.rb
#:include: doc.txt
def my_function
puts "yo"
end
Then a doc /tests/documentations/doc.txt
This describes the method very well
In command line (executed from /tests):
rdoc -i /Users/benjaminroth/Sites/Tests/rdoc/descriptions
AIUI, :include: allows you to (surprise) include the contents of another file, keeping the same indentation level of the block in which the include appears.
It will look for the named file in the current directory, but it's something you can override by means of the --include switch.
If you want an example, this could prove useful.

Accessing the app name from inside a rails template when generating rails app

I'm messing around with rails 2.3 templates and want to be able to use the app name as a variable inside my template, so when I use...
rails appname -m path/to/template.rb
...I want to be able to access appname inside template.rb. Anyone know how to do this?
Thanks
I was looking for an answer to this question. unfortunately the answer above (#root) doesn't seem to work in Rails 3.
Here's the variables you can access in Rails 3 app templates (even easier):
#app_name
#app_path
Thanks for the answers. Mike Woodhouse, you were so close. Turns out, all you need to do to access the appname from inside your rails template is...
#root.split('/').last
The #root variable is the first thing created when initializing templates and is available inside your rails templates. RAILS_ROOT does not work.
In Rails 3, use the app_name attribute.
See the documentation for the Rails::Generators::AppGenerator.
I ran into a similar problem, none of the variables listed above were available to me in Rails 4. I found that #name was available while running
rails plugin new engines/dummy -m my_template.rb
There are other useful variables available from within the template. You can see for yourself and play around by utilizing pry. Inside my template I added
require 'pry'; binding.pry
and then ran ls to show a list of available instance variables
ls -i
instance variables:
#_initializer #app_path #behavior #destination_stack #extra_entries #name #output_buffer #shell
#_invocations #args #builder #dummy_path #gem_filter #options #rails_template #source_paths
#after_bundle_callbacks #author #camelized #email #in_group #original_name #shebang
There's probably a more straightforward way, but this seems to work:
RAILS_ROOT.split('/').last
EDIT: Bleah - this got voted down once, and the voter was right. If I'd read the question more carefully, I'd have noticed the 2.3 and template.rb elements. Apologies.
I suspect that RAILS_ROOT won't have been created at the point that you need the app name. Looking at ruby\lib\ruby\gems\1.8\gems\rails-2.2.2\bin\rails, however, almost the first thing that happens is this:
app_path = ARGV.first
It's used at the end of the script to allow a chdir and freeze to be done if needed - I didn't know I could insta-freeze at creation, so I learned something new at least. ARGV then gets used here:
Rails::Generator::Scripts::Generate.new.run(ARGV, :generator => 'app')
which quickly gets us to the place where ARGV is really handled:
rails-2.3.1\lib\rails_generator\scripts.rb
where I see
Rails::Generator::Base.instance(options[:generator], args, options).command(options[:command]).invoke!
Somewhere below here is probably where the templating gets handled. I'm afraid I'm at a very early stage with 2.3 and templating is an area that I haven't looked at yet.
Does that help any better than my first effort?
RAILS_ROOT will give you the absolute path to your root directory. Your app name will be the portion of the string after the final '/' which you can grab in any number of ways.
EDIT: Not quite enough to get the job done. Mike and Dan iron it out below.
I believe the preferred way now is to call Rails.root and no longer RAILS_ROOT. Apparently someone on planet rails has an aversion to uppercase or some similar important reason. As of 2.3.5 they both appear to work.
I was getting error
`template': undefined local variable or method `app_name'
ruby 1.9.2p290, rails 3.2.11, thor 0.18.0, Windows
but with rails 2.3 generator:
class DynanavGenerator < Rails::Generators::Base
(can't be sure whether this error happened under rails 3.0.9 or earlier)
changed class definition to be:
class DynanavGenerator < Rails::Generators::NamedBase
which then gave:
No value provided for required arguments 'name'
I then added a 'name' ("something" below):
rails generate dynanav something --force
which gave the original error, so I then added:
def app_name
#name.titleize
end
to the class and all was well.
As of Rails 4 (maybe earlier versions?), use Rails.application.class to get the application name. For example, if your app is named Fizzbuzz, here are a few ways you might access it:
rails(development)> Rails.application.class
=> Fizzbuzz::Application
rails(development)> Rails.application.class.name
=> "Fizzbuzz::Application"
rails(development)> Rails.application.class.parent
=> Fizzbuzz
rails(development)> Rails.application.class.parent.to_s
=> "Fizzbuzz"

Rails: how do you access RESTful helpers?

I'm trying to work through this guide to Rails routing, but I got stuck in section 3.3:
Creating a RESTful route will also make available a pile of helpers within your application
and then they list some helpers like photos_url, photos_path, etc.
My questions:
Where can I find the complete list of helpers that is "made available?"
Is there a way to call the helpers in the console? I created an app, then opened up the console with script/console. I tried to call one of the helpers on the console like this:
>> entries_url
But got:
NameError: undefined local variable or method `entries_url' for #<Object:0x349a4>
from (irb):8
You have several questions in there, most of which have already been answered by people below.
The answer to one that wasn't fully addressed however, is: yes you can use the script/console to see where your routes go. Just type in app.[route_helper] and it will respond with the path. For example app.users_path will return /users/
So for your example type app.entries_url for the full URL - or app.entries_path for its relative path within the console.
rake routes at the command line should get you that list.
I think this may be what you are looking for ... http://topfunky.com/clients/peepcode/REST-cheatsheet.pdf
You can access other helpers in the console by prepending "helper."; ie. helper.progress_box (assuming #progress_box exists of course)
From memory, you can't call url/path helpers from the console for some reason.

Resources