htmlruby-on-railsform-helpers

How to set rails form helper with counter


my Model structur is:

<CheckBreak id: 1, procedure_id: "1", br_typ_id: 1, 
lok_typ: nil, lok_nr: nil, log_gestellnr: nil, auftrag: nil, 
bemerkungen: nil, date1: nil, pruefer: nil, sachkundiger: nil, 
freigeber: nil, lok_bremse_soll: nil, lok_bremse_ist: nil, 
zug_bremse_soll: nil, zug_bremse_ist: nil, einzeldruck: nil, 
dauerdruck: nil, c1_nr: nil, c1_point: nil, c1_io: nil, c1_nio: nil,
c1_inst_io: nil, c1_date: nil, c1_users: nil, c2_nr: nil,
c2_point: nil, c2_io: nil, c2_nio: nil, c2_inst_io: nil, 
c2_date: nil, c2_users: nil, c3_nr: nil, c3_point: nil, c3_io: nil, 
c3_nio: nil, c3_inst_io: nil, c3_date: nil, c3_users: nil, 
c4_nr: nil, c4_point: nil, c4_io: nil, c4_nio: nil, c4_inst_io: nil, 
c4_date: nil, c4_users: nil, c5_nr: nil, c5_point: nil, c5_io: nil, 
c5_nio: nil, c5_inst_io: nil, c5_date: nil, c5_users: nil, 
c6_nr: nil, c6_point: nil, c6_io: nil, c6_nio: nil, c6_inst_io: nil, c6_date: nil, c6_users: nil, c7_nr: nil, c7_point: nil, c7_io: nil, 
c7_nio: nil, c7_inst_io: nil, c7_date: nil, c7_users: nil, 
c8_nr: nil, c8_point: nil, c8_io: nil, c8_nio: nil, c8_inst_io: nil, 
c8_date: nil, c8_users:......

Now i will write my rails form code with a counter var.

like this

<% counter = 1%>
 
    <tr>
      <td><%= form.check_box : <%=counter%>_io%> </td>
      <td class="th-sm" align=center><%= form.check_box :c1_nio%></td>
      ...
    </tr>

    <% counter += 1%>`

How can i do this? Is there an name for this kind of code reduction?

I found a very dirty solution. The term called iteration

i can use in the form pure html tags with embeded ruby

    <input type="text" name="check_break[c<%=counter%>_users]" id="check_break_c<%=counter%>_users">

But this is so ugly and it feels so wrong.

i have to consider my DB-Model architecture. I will start a new post to that Question.


Solution

  • While you could generate the inputs dynamically with something like:

    <%= 1.upto(9).each do |number| %>
      <%= form.label :"c#{number}nio" %>
      <%= form.check_box :"c#{number}nio" %>
      # ...
    <%= end %>
    

    Your gut feeling that something is off is very right. Having an insane number of columns and potential nulls per row is not a viable solution.

    Instead normalize the data and think of it in terms of tables with relations between them:

    # make sure you set the correct types and choose a name that matches your domain
    rails g model thing check_break:references nr point io nio inst_io date user
    

    Then create a one to many assocation:

    class CheckBreak < ApplicationRecord
      has_many :things
      accepts_nested_attributes_for :things
    end
    
    class Thing < ApplicationRecord
      belongs_to :check_break
    end
    

    And then use fields_for to create nested inputs for each nested record:

    <%= form.fields_for(:things) do |thing_form| %>
      <%= thing_form.label :nio %>
      <%= thing_form.check_box :nio %>
      # ...
    <% end %>
    

    This will automatically result in an array of hashes in the params[:things_attibutes] attribute.

    def check_break_params
      params.require(:check_break)
            .permit(
              :foo,
              :bar,
              things_attibutes: %i[nr point io nio inst_io date user]
            )
    end
    

    See Rails Guides: Building Complex Forms.