I have an app where there’s a model Animal which has many Packages. I’m trying to create a form where the :true_weight attribute of a subset of the packages associated with a particular animal can be updated. This form is in a custom url/action (not show/new/edit or whatever). I feel like I’ve done most of it right, but it’s just not updating the packages. I’ll put my (abbreviated) code below and then explain what has and hasn’t been working. Pretty stumped by this:
package.rb
attr_accessible :true_weight # And irrelevant others
belongs_to :animal
animal.rb
attr_accessible :finalized, :name # And irrelevant others
has_many :packages
accepts_nested_attributes_for :packages
routes.rb
match '/animals/:animal_id/log' => "animals#log"
animals/log.html.erb
<%= form_for(@animal) do |f| %>
<div style="width: 200px">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
# This produces the subset of packages I want to be able to edit. It's an array
# of arrays, so that each render produces a separate table made from one of the
# inner arrays.
<% @animal.packages_for_log.each do |bundle| %>
<%= render partial: 'package_bundle', locals: {:bundle => bundle} %><br>
<% end %>
<h4>And then you'd allow addition of extra packages here.</h4>
<%= f.submit "Submit Animal Log", :class => "btn image-button right" %>
<% end %>
_package_bundle.html.erb
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Notes</th>
<th>Label</th>
<th>True Weight></th>
</tr>
</thead>
<tbody>
<% bundle.each do |package| %> <!-- Produces for each "bundle" the list of identical packages -->
<%= fields_for package do |p| %>
<% if package.order.user %>
<tr>
<td><%= package.name %></td>
<td><%= package.line.processed_notes %></td>
<td><%= "#{package.order.user.name.first(3).upcase}-#{package.id}" %></td>
<% if !package.true_weight %>
<td colspan=1><%= p.text_field :true_weight %></td
<% else %>
<td><%= package.true_weight.round(0) %>lb</td>
<% end %>
</tr>
<% end %>
<% end %>
<% end %>
</tbody>
</table>
animals_controller.rb (log is an animal action/view)
def log
@animal = Animal.find(params[:animal_id])
if @animal.update_attributes(params[:animal])
puts "Inside If Block"
@animal.toggle!(:finalized)
else
# I don't know about this. I wanted to redirect to the updated log page, with a flash
# but when I last tried that, it had some recursive error, or would update without my
# submitting.
render action: "log"
end
end
So. What is working:
- The if block in my animals controller is being accessed. But it looks like it’s possibly being accessed BEFORE I hit submit on my log page. (I searched for and found that puts line in the server logs). May just be misreading it.
- The form elements look right. I get a whole bunch of text boxes in the right places, and the information about each package that is being printed to the page in the table next to the text fields is correct.
- If I fill in Animal Name attribute at the top of the form, that attribute (of the animal) IS updated.
What isn’t working:
- When I submit, it redirects me to the animal show page (!?!?), with the flash that’s shown after the regular update action.
- The @animal.toggle!(:finalized) action doesn’t seem to do anything. Maybe, given 1 above, that boolean is being toggled twice? Back and forth?
- The big one — it doesn’t update my packages, at all.
Any ideas what’s going on here, or what I need to add? I’m really confused about what I’m not doing right.
Thanks!
EDIT — Per request, adding the code for my packages_for_log method (in the animal.rb file)
def packages_for_log
master = []
self.packages.each do |p|
if p.sold
# The master has sublists
if master.any?
counter = 0
# Check for matching list. Add if found.
master.each do |list|
if p.notes == list.first.notes && p.type == list.first.type
list << p
counter += 1 # Don't create list is appropriate one found.
end
end
if counter == 0
master << [p] if counter == 0 # Add as new list if list doesn't yet exist.
end
else # If master is empty, add the package to a new sub-list.
master << [p]
end
end
end
master.sort
end
Basically, packages have types and notes. I want the log to create a separate table for each package type/note. So I create an array, and then populate it with arrays where all the packages share the same type/notes. (First, I make sure they’re all sold. I don’t want the log page to show unsold packages.)
I think the problem here:
Default with this definition, Rails will create or update a record with information on form, so when you submit form, and rails check this is not a new record, it performed
updateaction, notlogaction. Try change to this :and submit form again and check if it works.
Edit: You’re not used
fields_forin:Add
fields_forand try again: