user2012677
user2012677

Reputation: 5735

Make parameter accessible by two actions in same way. params[:user][:form]

Route:

edit action: /profiles/edit?form=address

Controller

before_action :form_type, only: %i[edit update]

def edit
end

def update
end

def form_type
     @form_type = params[:form] || params[:user][:form]
end

View

<%= simple_form_for current_user, url: profiles_path, wrapper: :input_group  do |f| %>
                <%= render_user_form(f, @form_type, self) %>
                <%= f.input :form, as: :hidden , :input_html => {value: @form_type} %>
                <div class="action">
                  <%= f.submit 'Update', class: ''%>
                </div>
<% end %>

When my parameters get passed to the controller, on the edit page, it passes through to params[:form], but for the update action it's accessible as params[:user][:form]. How do I get the edit page to also make the param accessible the same way as.. params[:user][:form].

I prefer to access as params[:user][:form], not as params[:form], for both actions, if possible.

Upvotes: 1

Views: 388

Answers (3)

nathanvda
nathanvda

Reputation: 50057

First, I believe the form-type (address, I wonder what the other options are? profile, account, details ...) is not saved to the user, it is just a parameter you need on the controller side to know which part of the profile to update (imho it would not make sense to save the form parameter in the profile). So I am guessing you have some kind of multi-page form and solve it this way.

Well the easiest way imho, is to keep your url as is, and in your form write:

<%= simple_form_for current_user, url: profiles_path, wrapper: :input_group  do |f| %>
  <%= render_user_form(f, @form_type, self) %>
  <%= hidden_field_tag :form, @form_type %>
  <div class="action">
    <%= f.submit 'Update', class: ''%>
  </div>
<% end %>

This will add a hidden field, but not in the context of the user, so it will just be params[:form]. This I believe will be more correct.

Secondly, I have some small remarks with regards to your approach:

  • why not use profile singular? It is imho your intention to send the user to their profile (and there is only one, right?). In your routes you can write resource :profile. See documentation for singular resource (which coincidentally uses the profile example)
  • why not use nested resources for the different parts of a profile: this could also more naturally map to your data-model (or maybe it should): a user has an address (and probably more than one --a current, a delivery, invoicing, ...), has extra info, and then your urls would look like profile/address/edit (and then you would not have to handle the render_user_form with a form-type so akwardly).

Upvotes: 2

Chiperific
Chiperific

Reputation: 4686

Updated with @Max's corrections

Your issue is with how you are passing the param to the edit controller action (which is a GET request) vs. how the form passes params to the update controller action (which is a POST request, so the form values are in the request body).

With GET requests, everything you pass past the ? gets "parameterized".

When you pass /profiles/edit?form=address then params[:form] is available.

When your form submits, the form builder creates nested inputs by naming them with a model_name[attribute] convention.

To achieve what you asked, you can just do /profiles/edit?user[form]=address

IMHO, you should do params[:form] in both contexts instead of params[:user][:form].

You can get params[:form] in your partial by not using the simple_form helpers.

Try a standard text_field_tag instead of a f.field tag. Make sure to set the HTML name value as form:

text_field_tag 'form' @form_type

Then when you render the view, you should see something like this:

what you have: <input id="user_form" name="user[form]" type="text" />

what you want: <input id="form" name="form" type="text" />

Also, I'd suggest switching your param to form_type since SimpleForm might use #user_form as the ID of the form (<form id="user_form" ...>) and that would make any Javascript lookups by ID get conflicty.

Upvotes: 0

max
max

Reputation: 101811

Rails (technically its Rack) nests inputs by the name attribute. So if you submit this form:

<form action="/somepath">
  <input name="foo" value="1" type/>
  <input name="bar[baz]" value="2" type/>
  <input name="moo[woo]" value="3"/>
  <input type="submit" value="send">
</form>

You would get the following params hash:

{ 
   foo: 1,
   bar: {
     baz: 2
   },
   moo: {
     woo: 3
   }
}

The raw parameters would look like:

foo=1&bar[baz]=2&moo[woo]=3

Rack treats these parameters the same way regardless if they are sent via the query string or in the form body.

So if you want to pass the key as params[:user][:form] in the query you want the url /profiles/edit?user[form]=address.

You can create a link by:

# Im just guessing the name of the helper
<%= link_to 'Edit', profiles_edit_path(user: { form: 'address' }) %>

Upvotes: 1

Related Questions