0

Submit_tag not submitting selected ids of the checkbox_tag.

here is the code :

<%= form_tag pattendance_attendances_path, method: :put do %>
  <% if coordinator_signed_in? || admin_signed_in? %>
    <ul class="list-group">
    <li class="list-group-item">
    <%= radio_button_tag "round", 1 , true %> Round 1</li>
    <li class="list-group-item">
    <%= radio_button_tag "round", 2 %> Round 2  </li>
    <li class="list-group-item">
    <%= radio_button_tag "round", 3 %> Round 3  </li>
    <li class="list-group-item">
    <%= radio_button_tag "round", 4 %> Round 4  </li>
    <li class="list-group-item">
    <%= radio_button_tag "round", 5 %> Round 5  </li>
    </li>       
    <li class="list-group-item">
      <%= radio_button_tag "mark_present", "present" , true %> Present <br>
      <%= radio_button_tag "mark_present", "absent" %>Absent 
    </li><br>
    <li class="list-group-item">
    <%= submit_tag "Mark Attendance"%></li>
  </ul>
  <% end %>
  </div>
 <div class="table-responsive">  
 <div class="col-md-8">
 <table class="table table-hover">
 <thead>
 <tr>
  <th>Mark</th>
  <th><%= model_class.human_attribute_name(:team_id) %> ID</th>
  <th><%= model_class.human_attribute_name(:event_id) %> Name</th>
  <th><%= model_class.human_attribute_name(:round) %></th>
  <th><%= model_class.human_attribute_name(:status) %></th>
  <th><%=t '.actions', :default => t("helpers.actions") %></th>
 </tr>
</thead>
<tbody>
 <% @attendances.each do |attendance| %>
  <tr>
    <td><%= check_box_tag "a_ids[]", attendance.id %></td> 
    <td><%= attendance.team_id %></td>
    <td><%= attendance.event_id %></td>
    <td><%= attendance.round %></td>
    <td><%= attendance.status %></td>
    <td>
      <%if admin_signed_in? %>
      <%= link_to t('.edit', :default => t("helpers.links.edit")),
                  edit_attendance_path(attendance), :class => 'btn btn-default btn-xs' %>
      <%= link_to t('.destroy', :default => t("helpers.links.destroy")),
                  attendance_path(attendance),
                  :method => :delete,
                  :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
                  :class => 'btn btn-xs btn-danger' %>

      <%end%>
      <%= link_to t('.show', :default => t("helpers.links.View details")),
                   attendance, :class => 'btn btn-default btn-xs' %>  
       </td>
       </tr>
     <% end %>
     </tbody>
    </table>
     </div>
    </div>  
    <% end %>

Controller Code:

  def pattendance
params[:a_ids]
if params[:mark_present]=="present"
  Attendance.where(id: params[:a_ids]).update_all(status: 'Present', round: params[:round])
else
  Attendance.where(id: params[:a_ids]).update_all(status: 'Absent', round: params[:round])
end    
redirect_to attendances_url
end

The motive behind implementing this method is to mark attendance of all the teams registered in the particular event. The checkboxes are present to select multiple teams. I am selecting "Attendance.ids" because a team can participate in multiple events. So selecting Team IDS can mark attendance for the team in all the events. To make it unique for each event I'm using attendance ids.

After selecting rounds from radio buttons and status(present or absent) and clicking on mark attendance submit_tag it should update the values of the selected checkboxes. BUT Sometimes values are passed and sometimes they are not.

Please tell me what is the problem in this code. It would be really helpful.

Console : I tried to update the round of selected checkbox to "2" and status as "present"

  Parameters: {"utf8"=>"✓", "authenticity_token"=>"2uzivV42tLjwuUd+QyEHvL6tCa8ZCE8xRbgJ5k7ueEcV9oaQt5yLafKmZTiFceZEY9B3wyY52qxL1f0hvqQ47A==", "round"=>"2", "mark_present"=>"present", "commit"=>"Mark Attendance"}

Coordinator Load (0.1ms)
SELECT "coordinators".* FROM "coordinators" WHERE "coordinators"."id" = ? ORDER BY "coordinators"."id" ASC LIMIT 1 [["id", 1]] SQL (0.2ms)
UPDATE "attendances" SET "status" = 'Present', "round" = 1 WHERE "attendances"."id" IS NULL Attendance Load (0.1ms) SELECT "attendances".* FROM "attendances" WHERE "attendances"."id" IS NULL Redirected to http://localhost:3000/attendances Completed 302 Found in 5ms (ActiveRecord: 0.4ms)

It didn't pass the selected checkbox values after clicking on submit button. The values don't update when I go back from show page to index page. But after refreshing it works consistently

Gagan Gupta
  • 1,189
  • 7
  • 19
  • You can't use `checked="checked"` in a Ruby context. All you're doing is creating a local variable named `checked` which has the value of `"checked"`. – user229044 Mar 07 '16 at 14:51
  • Thanks pointing it out. But this can solve my problem ? – Gagan Gupta Mar 07 '16 at 14:52
  • actually it is an attribute which pre-selects the radio buttons when the form loads, now all the radio buttons are not pre-selected. – Gagan Gupta Mar 07 '16 at 14:55
  • No, you are wrong. That isn't how Ruby works. The 3rd argument to `radio_button_tag` is a *boolean* which indicates whether the field is checked. You're using `checked="checked"` which works **purely by coincidence**. The correct way to check the radio tag by default is to simply use `radio_button_tag "round", 1, true`. – user229044 Mar 07 '16 at 15:01
  • Thanks I've changed my code but still there is some problem :| submit button is not working properly everytime :( – Gagan Gupta Mar 07 '16 at 15:05
  • Would you mind updating your question with the new code and the error? – ezuk Mar 07 '16 at 15:17
  • I have updated the code and also included error/bug – Gagan Gupta Mar 07 '16 at 15:35

3 Answers3

1

I'll give you some points for creativity - but there is a much simpler way to accomplish creating / updating multiple associations at once.

First make sure you have the modeling down:

class Event < ActiveRecord::Base
  has_many :registrations, dependent: :destroy
  has_many :teams, through: :registrations
  has_many :rounds, dependent: :destroy
  has_many :attendences, through: :rounds
  validates_uniqueness_of :name
end

class Team < ActiveRecord::Base
  has_many :registrations, dependent: :destroy
  has_many :events, through: :registrations
  has_many :attendences, dependent: :destroy
  has_many :rounds, through: :attendences

  validates_uniqueness_of :name
end

# Many To Many Join model between Event and Team
class Registration < ActiveRecord::Base
  belongs_to :event
  belongs_to :team
end

class Round < ActiveRecord::Base
  belongs_to :event
  has_many :attendences, dependent: :destroy
  has_many :attending_teams, through: :attendences, source: :team
end

class Attendence < ActiveRecord::Base
  belongs_to :team
  belongs_to :round
  has_one :event, through: :round
end

You'll notice here that we are using a table for "rounds" - if you are modeling a domain such as a conference you definatly want a table to store each sub event (class, talk etc). You don't want to use a weak implicit linking in your attendences table!

Armed with this creating a form for a round which lets you set which lets you set which teams have participated is a breeze:

<%= form_for(@round) |f| %>
  <div class="field">
    <% f.label(:attending_teams_ids) %>
    <% f.collection_check_boxes(:attending_teams_ids, @round.event.teams, :id, :name) %>
  </div> 
  <% f.submit %>
<% end %>

Rails has many useful helpers like collection_check_boxes for creating inputs from an association.

If you needed to update multiple Rounds at once you would use accepts_nested_attributes together with fields_for. However this is a pretty advanced topic and whole tutorial in itself so I'll leave it up to you to read a few tutorials and figure it out.

max
  • 96,212
  • 14
  • 104
  • 165
  • Thanks a lot for designing it for me , I really appreciate it. :) I will implement this code but I have to make the above code work as well. I am not able to figure out the problem. – Gagan Gupta Mar 08 '16 at 05:05
0

I think the problem is that check_box_tags don't send any value when not checked, so unless you check at least one check box in the attendances group, you won't get anything in the a_ids parameter in the controller.

For this to work, you'd need to reset the a_ids param to a blank value if no check box checked. I.e. add something like this in your controller:

 def pattendance
   params[:a_ids] ||= []
   ...
 end

See also the "small gotcha" section in this SO question.

Community
  • 1
  • 1
Matouš Borák
  • 15,606
  • 1
  • 42
  • 53
  • Thanks for your reply. The link you have provided performs a different task. In that application the user wants to remove categories (which are already checked) by removing the checks from them. Here my case is completely different. Though I tried to implement this code but it didn't help at all. :( – Gagan Gupta Mar 07 '16 at 16:42
  • The link should have further explained the Rails behavior when using multiple `check_box_tag`s with an array param - that the param is totally undefined in the controller when no check_box is checked. I can see nothing wrong with your code, I even took the code and tested it and the behavior was consistent - I got the error you describe only when NO check box was checked. So are you claiming that you get the `a_ids` param nil even if you HAVE checked a check box? If so, the error must come from somewhere else, I think. – Matouš Borák Mar 07 '16 at 17:35
  • Thanks for testing my code. If you have encountered consistent behavior then what can be the problem in mine ? -_- Yeah I am also thinking now that error can be from somewhere else but how can it be ? – Gagan Gupta Mar 08 '16 at 04:59
  • The values don't update when I go back from show page to index page. But after refreshing it works consistently. – Gagan Gupta Mar 08 '16 at 05:28
  • Sorry, can you clarify the last comment? Are you using the back browser button (in that case no wonder you see historical, not updated, data)? And also, what have the show and index actions have in common with the edit form you posted in the Q? I have to say, I am confused. – Matouš Borák Mar 08 '16 at 08:09
  • Okay, Let me clarify it. **Index page :** which shows all the values of the **Attendance table**.The data will be shown in tabular structure and checkboxes are present in each row of this table to select rows. **Show page: (View details link)** It will show the stored data for each row. For example: **localhost:3000/attendances/1** .There is back button on **localhost:3000/attendances/1 ** .Which redirects us to index page of attendances. Got it ? – Gagan Gupta Mar 08 '16 at 08:20
  • I see. Are you using this form of the back link - `link_to 'Back', :back` ? If so, this particular link form uses `javascript:history.back()` so it is equivalent to clicking the browser back button and you will indeed return to a historical index page (there is no request done to get there). In such case you would need to use proper index path in the link, something like `link_to 'Back', attendances_path` instead. – Matouš Borák Mar 08 '16 at 08:42
  • I am using `<%=link_to 'back' , attendances_path %>` to back to attendances page. – Gagan Gupta Mar 08 '16 at 08:46
  • Hmm. So what is your workflow then? You go to the index page, select one or few attendances, click the submit button, get redirected by the controller back to the index page (as you have shown in the controller action in the question)? By that time you should see updated values. Is your workflow different? – Matouš Borák Mar 08 '16 at 08:56
  • Yes you are right. After clicking on submit button I redirect to same index page. – Gagan Gupta Mar 08 '16 at 09:10
  • And do you see updated values after the redirect? Or at what exact moment in the workflow you see a problem? – Matouš Borák Mar 08 '16 at 09:23
  • Suppose I clicked on view details. Which will direct me to the show page. And on show page if I click on back button (link_to) i get redirected to the attendances index page. Then if i select values and press submit button it doesnt update values. But clicking on submit button again then it updates the values. – Gagan Gupta Mar 08 '16 at 09:29
  • Sorry Gagan, I'm running out of ideas. I can see nothing wrong with your code. And there should be no difference on the behavior of the index page, regardless of where from you've been redirected to it. – Matouš Borák Mar 08 '16 at 09:53
  • Don't say sorry. I really appreciate your help a lot. :) and even I ran out of ideas and was trying hard before posting this question here. Thanks for giving your time to this question. :) – Gagan Gupta Mar 08 '16 at 09:56
0

I solved this problem by moving my JS to onReady as turbolinks was caching the page.

Gagan Gupta
  • 1,189
  • 7
  • 19