Reputation: 6466
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:
What isn't working:
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.)
Upvotes: 0
Views: 460
Reputation: 8604
I think the problem here:
<%= form_for(@animal) do |f| %>
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 update
action, not log
action. Try change to this :
<%= form_for(@animal), :url => { :action => "log" } do |f| %>
and submit form again and check if it works.
Edit: You're not used fields_for
in:
<% @animal.packages_for_log.each do |bundle| %>
<%= render partial: 'package_bundle', locals: {:bundle => bundle} %><br>
<% end %>
Add fields_for
and try again:
<%= fields_for @animal.packages_for_log.each do |bundle| %>
<%= render partial: 'package_bundle', locals: {:bundle => bundle} %><br>
<% end %>
Upvotes: 1