derDaywalker derDaywalker - 1 year ago 124
Ruby Question

rails I18n wrong parameter order in route (id as locale and id is nil)

I want to internationalize an external code (see github) with i18n for rails. I have read the guide for Rails Internationalization (I18n) API. Translating the text is not a problem, but the underlying code seems not to work properly anymore in all situations. Unfortunately, I'm not a rails/ruby expert.

From the log:

FATAL -- : ActionView::Template::Error (No route matches
{:action=>"edit", :controller=>"plans", :format=>nil, :id=>nil,
:locale=>115} missing required keys: [:id]):

So the problem is, that the parameter for the id (=115) is passed as locale instead as id.

To get i18n working I added the following code into app/controllers/application_controller.rb:

before_action :set_locale


def set_locale
I18n.locale = params[:locale] || I18n.default_locale

def default_url_options(options = {})
{ locale: I18n.locale }.merge options

Moreover, I wrapped the original routes in config/routes.rb:

Dmptool2::Application.routes.draw do
scope "(:locale)", locale: /en|de/ do
a lot of original routes

Therefore, the question is, is there a missing route or is there a problem inside the code or is it just my fault. Besides translating text and buttons, I haven't changed the original code. The original routes.rb can be found on github (sry, I can't post the link because I don't have enough reputation).
Any suggestions / help would be perfect.

I think I'm a little bit closer. Maybe now it's more clear, why it isn't working.
First of all the "full" stacktrace:

F, [2015-05-04T16:43:58.600384 #19289] FATAL -- :
ActionView::Template::Error (No route matches {:action=>"edit", :controller=>"plans", :format=>nil, :id=>nil, :locale=>#<Plan id: 158, name: "asdfe", requirements_template_id: 59, solicitation_identifier: "",
submission_deadline: nil, visibility: :public, created_at: "2015-05-04 14:41:33", updated_at: "2015-05-04 14:43:48", current_plan_state_id: 300>} missing required keys: [:id]):
3: The plan "<%= @vars[:plan].name %>" has been completed.
5: If you have questions pertaining to this action, please visit the DMP Overview page at <%= edit_plan_url(@vars[:plan]) %>
7: <%= render :partial => 'users_mailer/notification_boilerplate.text.erb' %>
app/views/users_mailer/dmp_owners_and_co_committed.text.erb:5:in `_app_views_users_mailer_dmp_owners_and_co_committed_text_erb__754483862330985648_69917281861000'
app/mailers/users_mailer.rb:32:in `notification'
app/models/concerns/plan_email.rb:50:in `block in email_dmp_saved'
app/models/concerns/plan_email.rb:49:in `email_dmp_saved'
app/models/plan_state.rb:31:in `update_current_plan_state'
app/controllers/plan_states_controller.rb:97:in `create_plan_state'
app/controllers/plan_states_controller.rb:73:in `committed'

If I hit the "done" Button on the webpage, the function
is called, wich calls
. Within the definition of create_plan_state, there is the statement
plan_state = PlanState.create( plan_id:, state: state, user_id:
. This triggers a callback for
after_create: update_current_plan_state

def update_current_plan_state
#update the current plan pointer in the plan model
p = self.plan
p.current_plan_state_id =!

Now, this triggers
after_save: email_dmp_saved

def email_dmp_saved
if current_state.state == :committed
users = self.users
users.delete_if {|u| !u[:prefs][:dmp_owners_and_co][:committed]}
users.each do |user|
{:user => user, :plan => self } ).deliver

I think the definition of the notification is not important. But the 3rd last line calls "dmp_owners_and_co_committed", which is defined as:

Hello <%= @vars[:user].full_name %>,

The plan "<%= @vars[:plan].name %>" has been completed.

If you have questions pertaining to this action, please visit the DMP Overview page at <%= edit_plan_url(@vars[:plan]) %>

<%= render :partial => 'users_mailer/notification_boilerplate.text.erb' %>

And in _notification_boilerplate.text.erb there is:

You may change your notification preferences at <%= edit_user_url(@vars[:user].id) %>#tab_tab2 .

I think the problem is
. Because if I add some random text as parameter it works...:

and in _notification:

The question is, why is it working? Is there a way to print the created route? Because in the stacktrace the route doesn't match because format and id is nil. Now I want to see the new route in order to know where my random string "de" is placed.

Answer Source

Looks like your routes are expecting two params, and ordering it as it comes. There's a way to avoid it by using a named hash into the params passed:

edit_plan_url(id: @vars[:plan].id)

The Rails Automagic will use the symbol to identify the param and avoid the problem.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download