My app has an Animal model which has many (and accepts nested attributes for) Packages. In my Animals Controller, I created the following action to allow for the editing of certain Animal (and nested Package) attributes in a separate page (and for a separate user role) from that used for normal Animal editing. (To clarify, I have an animals#edit action and page, and a separate animals#log action and page, which ideally allow different user roles to edit different things about the animal):
我的应用程序有一个Animal模型,它包含许多(并接受嵌套属性)包。在我的动物控制器中,我创建了以下操作,以允许在单独的页面(以及单独的用户角色)中编辑某些动物(和嵌套包)属性,而不是用于正常动物编辑。 (为了澄清,我有一个动物#edit动作和页面,以及一个单独的动物#log动作和页面,理想情况下允许不同的用户角色编辑动物的不同内容):
def log
@animal = Animal.find(params[:animal_id])
if params[:animal]
if @animal.update_attributes(params[:animal])
# I want a basic reload (with flash) in cases of both success and failure.
redirect_to log_path(@animal), notice: "Animal update successful!"
else
redirect_to log_path(@animal), notice: "Update unsuccessful. Contact admin"
end
end
end
My separate edit/update actions:
我的单独编辑/更新操作:
def update
@animal = Animal.find(params[:id])
if @animal.update_attributes(params[:animal])
redirect_to @animal, notice: "Animal was successfully updated."
else
render action: "edit"
end
end
def edit
@animal = Animal.find(params[:id])
end
The problem is, when I hit my submit button in my log page (code below), it refreshes the page, but a) without any notice of any sort (minor problem), and b) more importantly, without actually updating the package information. Importantly, if I update the animal.weight attribute (the only ANIMAL attribute modifiable here), THAT works. Just not the nested package attributes.
问题是,当我点击我的日志页面中的提交按钮(下面的代码)时,它会刷新页面,但a)没有任何通知(小问题),b)更重要的是,没有实际更新包信息。重要的是,如果我更新animal.weight属性(这里唯一可修改的ANIMAL属性),那就有效。只是没有嵌套的包属性。
Help? I'm really stumped here. I've been fiddling with this forever trying to get it to work. Some possibly relevant code below:
救命?我真的很难过。我一直在努力摆弄它,试图让它发挥作用。一些可能相关的代码如下:
In my routes.rb file (above animal resources):
在我的routes.rb文件中(动物资源上方):
match '/animals/:animal_id/log' => "animals#log", as: :log
Here's my log view:
这是我的日志视图:
<%= form_for(@animal, :url => { :action => "log" }, :method => :put) do |f| %>
<div style="width: 200px">
<% if @animal.weight %>
<%= "Weight: #{@animal.weight}lbs" %>
<% else %>
<%= f.label "Weight (in lbs)" %>
<%= f.text_field :weight %>
<% end %>
</div>
# I'm cycling through each bundle to group "identical" packages in a table (one per bundle).
<% @animal.sold_bundles.each do |bundle| %> <!-- Packages are bundled by cut and prep notes -->
<%= render partial: 'package_bundle', locals: {:bundle => bundle, :f => f} %><br>
<% end %>
<%= f.submit "Submit Animal Log", :class => "btn image-button right" %>
<% end %>
And here's the "package_bundle" partial called for each bundle. It produces a table of packages, some editable (because of blank true_weight value) and some not:
这里是为每个包调用的“package_bundle”部分。它生成一个包表,一些可编辑(因为空白的true_weight值)而一些不是:
<table class="table">
<thead>
<tr>
<th>Cut Name</th>
<th>Prep Notes</th>
<th>Label</th>
<th>Actual Lbs</th>
<th>Actual Oz</th>
</tr>
</thead>
<tbody>
<!-- list of specified packages -->
<%= f.fields_for :packages, bundle do |p| %>
<tr>
<td><%= p.object.name %></td>
<td><%= "#{p.object.user.name.first(3).upcase}-#{p.object.id}" %></td>
<% if p.object.true_weight == nil || p.object.true_weight == 0 %>
<td colspan=1><%= p.text_field :actual_lbs %></td>
<td colspan=1><%= p.text_field :actual_oz %></td>
<% else %>
<td><%= p.object.true_weight.round(0) %> lb</td>
<td><%= ((p.object.true_weight % 1) * 16).round(2)%> oz </td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
EDIT -- More code on request
编辑 - 根据要求提供更多代码
package.rb (just what's relevant) -- I evaded the below gotcha (this time; I've definitely made that mistake before). It's a possibility that my method for converting lbs/oz to lbs with percent is to blame here, but it looks right to me:
package.rb(正好相关) - 我回避了下面的问题(这一次;我之前肯定犯了这个错误)。我的方法是将我的lbs / oz转换为百分之百的方法归咎于此,但它对我来说是正确的:
class Package < ActiveRecord::Base
attr_accessible :animal_id, :cut_id, :price, :line_id, :sold, :savings, :actual_lbs, :actual_oz, :true_weight
attr_accessor :actual_lbs, :actual_oz
belongs_to :animal
belongs_to :cut
belongs_to :line
before_update :to_true
def to_true
if self.sold
if self.order.status > 1 # This is the case for any package loaded on the log page
if self.actual_lbs && self.actual_oz
unless self.true_weight && self.true_weight > 0 # Don't overwrite legit true weights
percent = self.actual_oz / 16
self.update_attribute(:true_weight, self.actual_lbs + percent)
end
end
end
end
end
animal.rb (only relevant):
animal.rb(仅相关):
class Animal < ActiveRecord::Base
attr_accessible :breed, :name, :photo, :animal_type, :hanging_weight, :meat_weight,
:weight, :ranch_id, :butcher_id, :cow_mult, :pig_mult, :packages_attributes,
:lamb_mult, :goat_mult, :host_id, :final_sale, :opening_sale, :open, :no_sales
has_many :orders
has_many :packages
belongs_to :butcher
belongs_to :ranch
belongs_to :host
after_create :create_packages
accepts_nested_attributes_for :packages
Looked at my server log (easier for me to understand than the dev log), to get to the bottom of this, and notice two weird things. There's no error at all, but 1) It seems to execute the GET for the page when I load it, but not the requested PUT when I hit submit, and 2) Probably as a consequence, the only param passed (which is passed as part of the GET request) is the animal id; no package attributes are passed.
看着我的服务器日志(比起开发日志更容易理解),深入了解这一点,并注意到两个奇怪的事情。根本没有错误,但1)当我加载它时,它似乎执行页面的GET,但是当我点击提交时,它似乎不是请求的PUT,2)可能因此,唯一的参数传递(传递为GET请求的一部分)是动物id;没有传递包属性。
2 个解决方案
#1
1
attr_accessor
won't trigger callbacks. You have to make a variable "dirty". More info here.
attr_accessor不会触发回调。你必须使变量“脏”。更多信息在这里。
In your package.rb
:
在你的package.rb中:
def actual_lbs=(val)
true_weight_will_change!
@actual_lbs=val
end
This will make it such that when it sets the actual_lbs variable, it will "dirty" a variable that is in the database, thus firing the callbacks.
这将使得当它设置actual_lbs变量时,它将“弄脏”数据库中的变量,从而触发回调。
#2
2
Can you post your model code? A common "gotcha" that comes to mind is not adding, in your case, package_attributes
to the attr_accessible
on the animal model. It will not raise an error, but tucked into the development log, prior to the SQL entries, you will see the mass-assignment warning.
你能发布你的型号代码吗?想到的一个常见的“问题”是,在您的情况下,package_attributes不会添加到动物模型上的attr_accessible。它不会引发错误,但是在SQL条目之前隐藏到开发日志中,您将看到质量分配警告。
#1
1
attr_accessor
won't trigger callbacks. You have to make a variable "dirty". More info here.
attr_accessor不会触发回调。你必须使变量“脏”。更多信息在这里。
In your package.rb
:
在你的package.rb中:
def actual_lbs=(val)
true_weight_will_change!
@actual_lbs=val
end
This will make it such that when it sets the actual_lbs variable, it will "dirty" a variable that is in the database, thus firing the callbacks.
这将使得当它设置actual_lbs变量时,它将“弄脏”数据库中的变量,从而触发回调。
#2
2
Can you post your model code? A common "gotcha" that comes to mind is not adding, in your case, package_attributes
to the attr_accessible
on the animal model. It will not raise an error, but tucked into the development log, prior to the SQL entries, you will see the mass-assignment warning.
你能发布你的型号代码吗?想到的一个常见的“问题”是,在您的情况下,package_attributes不会添加到动物模型上的attr_accessible。它不会引发错误,但是在SQL条目之前隐藏到开发日志中,您将看到质量分配警告。