【问题标题】:Rails Custom Nested Update not updatingRails 自定义嵌套更新未更新
【发布时间】:2012-11-16 23:25:13
【问题描述】:

我的应用有一个 Animal 模型,它有许多(并接受嵌套属性)包。在我的 Animals Controller 中,我创建了以下操作,以允许在一个单独的页面(以及一个单独的用户角色)中编辑某些 Animal(和嵌套的 Package)属性,而不是用于正常的 Animal 编辑。 (澄清一下,我有一个animals#edit 动作和页面,以及一个单独的animals#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

我单独的编辑/更新操作:

  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

问题是,当我在日志页面(下面的代码)中点击提交按钮时,它会刷新页面,但是 a) 没有任何通知(小问题),并且 b) 更重要的是,没有实际更新包裹信息。重要的是,如果我更新了 animal.weight 属性(这里唯一可修改的 ANIMAL 属性),那就可以了。只是不是嵌套的包属性。

帮助?我真的很难过。我一直在摆弄这个,试图让它发挥作用。下面是一些可能相关的代码:

在我的 routes.rb 文件中(动物资源上方):

match '/animals/:animal_id/log' => "animals#log", as: :log

这是我的日志视图:

<%= 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 %>

这里是每个包调用的“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>

编辑 -- 应要求提供更多代码

package.rb(只是相关的)——我避开了下面的问题(这次;我以前肯定犯过这个错误)。我将 lbs/oz 转换为 lbs with percent 的方法有可能在这里受到责备,但它看起来对我来说是正确的:

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(仅相关):

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

查看了我的服务器日志(对我来说比开发日志更容易理解),以深入了解这一点,并注意到两件奇怪的事情。根本没有错误,但是 1)它似乎在我加载页面时执行了 GET,但在我点击提交时没有执行请求的 PUT,并且 2)可能因此,唯一的参数传递了(传递为GET 请求的一部分)是动物 ID;没有传递包属性。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 routing controller nested-attributes


    【解决方案1】:

    你能发布你的模型代码吗?想到的一个常见“问题”是在您的情况下,在动物模型的attr_accessible 中添加package_attributes。它不会引发错误,但会隐藏在开发日志中,在 SQL 条目之前,您会看到批量分配警告。

    【讨论】:

    • 就这么做了。感谢您的回复!就 SO 响应最近而言,我一直处于负面状态。也许我的问题变得越来越奇怪:)
    • 那么@Sasha——这回答了你的问题吗?如果是这样,您能否将其标记为已接受。如果没有,它看起来确实像 animal.rb 类具有所需的 :packages_attributes 访问器,但可能在 after_create 回调之间存在冲突,这表明它正在执行 accepts_nested_attributes_for 自动执行的工作。检查您的 development.log 以了解实际发生的情况。
    • 嗯,基于上述,我一直无法解决问题。在这种特殊情况下不使用 after_create 回调。它在另一个页面上(成功地)用于创建与动物相关联的包装对象,并在制作动物时具有特定属性。而且由于我在那里有 :packages_attributes 行,所以我仍然不知道发生了什么。我正要深入开发日志看看。
    • 所以在我的日志中,根本没有错误,但是 1)它似乎在我加载页面时执行了 GET,但在我点击提交时没有执行请求的 PUT,并且 2)可能因此,唯一传递的参数(作为 GET 请求的一部分传递)是动物 ID;没有传递任何包属性。
    • 你能发布日志输出吗?我认为您可能希望分解您的日志操作以遵循编辑(为表单构建对象)/更新(从表单更新对象)范例。我的想法是,这种组合操作既可以处理表单对象的构建,也可以根据您的参数 if 语句更新所述对象?将其分成两个动作也可以让您更清晰地定义路线,例如match '/animals/:animal_id/log' =&gt; "animals#log", as: :log, :via =&gt; :getmatch '/animals/:animal_id/log' =&gt; "animals#log", as: :log, :via =&gt; :put 用于实际更新。
    【解决方案2】:

    attr_accessor 不会触发回调。您必须使变量“脏”。更多信息here

    在你的package.rb:

    def actual_lbs=(val)
      true_weight_will_change!
      @actual_lbs=val
    end
    

    这将使得当它设置actual_lbs 变量时,它会“弄脏”数据库中的一个变量,从而触发回调。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-29
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2018-01-29
      • 1970-01-01
      相关资源
      最近更新 更多