achilles77
achilles77

Reputation: 335

proper syntax for a form_for in ruby

I am trying to write a form for an array

<%= form_for @user, html: {multipart:true} do |f| %>

 <%= render "shared/error_messages", object: f.object %>

<label for="user-amenities" class="top">Amenities</label>
    <ul class="group" id="user-amenities">
      <% User.amenities_list.each_with_index do |amenity, index| %>
        <li class="checkbox-li">
          <input type="checkbox" name="user_amenities_indicies[]" value="<%= index %>">
            <%= amenity %>
          </input>
        </li>
       </ul>
      <% end %>

However I am not utilizing the |f| and it is not saving the options in the amenities_indices. Any idea on how to refactor this code to utilize the f so the user information can be saved?

Upvotes: 1

Views: 77

Answers (2)

Richard Peck
Richard Peck

Reputation: 76784

Code Block

The refactoring you seek is basically that you need to use the f. with all your inputs

Reason being that if you call form_for, it essentially means you're calling a huge code block, in which every attribute needs to be bound to your form object, in order to render with your params hash correctly

In short - your form_for renders an HTML form, keeping the names of the <input> elements in line with the requirement of your application to load the params. The problem you have is that omitting the f. call will keep those inputs outside the scope for your params, leading to the issue you're seeing.

--

Save

If you don't have any associative data (which I've described below), you'll want to include your inputs in the f. code block:

<%= form_for @user do |f| %>
   <% User.amenities_list.each_with_index do |amenity, index| %>
      <%= f.check_box :user_amenities_indicies, index %>
   <% end %>
<% end %>

This will pass the checked values of the user_amenities_indicies checkboxes through to your controller. This should work, and is the correct syntax for you

--

fields_for

A further addition is that I don't know whether you're trying to populate associative data or not here - but if you were trying to create data for another model, you'll want to use fields_for:

#app/controllers/users_controller.rb
Class UsersController < ApplicationController
   def new 
      @user = User.new
      @user.user_amenities.build
   end 

   def create
      @user = User.new(user_params)
      @user.save
   end

   private

   def user_params
       params.require(:user).permit(:user, :params, user_amenities_attributes: [])
   end
end

This will allow you to create a form using fields_for, like this:

<%= form_for @user do |f| %>
   <%= f.fields_for :user_amenities do |ua| %>
       # fields for user_amenities
   <% end %>
<% end %>

Upvotes: 0

neo
neo

Reputation: 4116

Try simple_form https://github.com/plataformatec/simple_form/blob/master/README.md

What you're looking for is :collection and then :as

Upvotes: 1

Related Questions