具有嵌套属性的 Best_In_Place 内联编辑

Posted

技术标签:

【中文标题】具有嵌套属性的 Best_In_Place 内联编辑【英文标题】:Best_In_Place inline edits with nested attributes 【发布时间】:2016-06-02 13:25:31 【问题描述】:

我目前正在尝试使用 best_in_place gem 在 html 表格中进行内联编辑。我在购物车的显示视图中展示了一辆购物车。在购物车的显示视图中,我可以添加 lineItems。创建 LineItem 时,还会创建一个带有 lineItem_id 的新可用记录,然后将其与其 lineitem 一起显示在购物车中。 Cart 和 LineItem 表都来自外部数据库,因此,我无法向其中添加列,这就是为什么我不能只向 LineItem 添加可用的布尔属性。

**cart.rb
class Cart << AR::Base
 has many LineItems
end

**line_item.rb
class LineItems <<AR::Base
 belongs_to Cart
 has_one :available 
 accepts_nested_attributes_for :available 
end

**available.rb
class Available<<AR::Base
 belongs_to LineItems
end


**views/cart/show.html.erb
@cart.lineitems.each do |line_items|
    <td><%= line_item.price %></td>
    <td><%=line_item.name %></td>
    <td><%= best_in_place line_item.available.boolean, :boolean, :path => line_items_path, :type =>  type: :checkbox, collection: %w[No Yes] %></td>  
end

我希望能够使用 best_in_place 在购物车显示视图上的 html 表中编辑 line_item.available.boolean,但我没有任何运气。任何帮助都会令人惊叹! =]我在阅读后知道使用嵌套属性是不可能的,但是如果我能以某种方式摆脱可用模型并在显示表中有一个字段,我可以为 line_item 编辑该字段以查看 lineItem 是否可用,那也太好了。我对任何想法持开放态度!

【问题讨论】:

【参考方案1】:

首先,我们需要修复您的代码中的一些语法问题:

@cart.lineitems.each do |line_item| # changed "line_items" to "line_item"
  <td><%= line_item.price %></td>
  <td><%=line_item.name %></td>
  <td><%= best_in_place line_item.available, :boolean, :path => line_items_path, type: :checkbox, collection: %w[No Yes] %></td>  # changed "line_item.available.boolean" to "line_item.available" and ":type =>  type: :checkbox" to "type: :checkbox"
end

现在,答案是:

正如我在this Github issue 中解释的那样,您需要将param 选项和url 选项(以前是path,但在v3.0.0 中已弃用)传递给best_in_place。

url 选项

默认 url 是 best_in_place 的第一个参数的更新操作。由于您的代码以best_in_place line_item.available 开头,因此默认为url_for(line_item.available.id)。但是,您希望它修补 LineItemsController 的更新操作,即url_for(line_item)

param 选项

默认情况下,param 选项假定您正在修补 AvailablesController,因此以下是 Rails 约定为了将 available.boolean 更新为值“1”所需的参数:

"available"=>"boolean"=>"1"

Available 的 ID 已经在 URL 中,因此您需要传递的唯一额外参数是 boolean 的新值。

但是,在您的情况下,您正在修补 LineItemsController 并且可用模型接受嵌套属性。这需要两个调整:

    LineItem 的 ID 已经在 URL 中,但可用的 ID 不是。我们在这里有两个选择:要么将可用的 ID 放入参数选项中,要么通过在模型中将 update_only: true 传递给 accepts_nested_attributes 使 ID 变得不必要。 update_only 方法可能不适合您,具体取决于您的用例,但我发现它在绝大多数情况下都是最简单的方法,并且免费增加了额外的安全层。

    布尔选项需要正确嵌套,即:

    line_items[available_attributes][boolean]
    

    这样,当它到达服务器时,参数将是:

    "line_item"=>"available_attributes"=>"id"=>"99","boolean"=>"1"
    # "99" is just an example of line_item.available.id
    

    请注意,您需要在控制器中允许这些属性,即:

    line_item.update(params.require(:line_item).permit(
      available_attributes: [:id, :boolean]))
    # You can remove `:id` if you are using the `update_only` option
    

综上所述,这是你最好的方法:

best_in_place line_item.available, :boolean, 
  type: :checkbox, 
  url: line_item_path(line_item.id),
  param: "line_item[available_attributes][id]=#line_item.available.id&line_item[available_attributes]"

但是,如果可能,请使用update_only 选项。

# line_item.rb
accepts_nested_attributes_for :available, update_only: true

看看它现在变得多么简单:

best_in_place line_item.available, :boolean, 
  type: :checkbox, 
  url: line_item_path(line_item.id),
  # Note: `url: line_item` might also work.
  # If someone can confirm this in a comment, I can update this answer
  param: "line_item[available_attributes]"

【讨论】:

感谢您的详尽回答。我之前遵循了这些指示,但我似乎遇到了与以前相同的错误。我收到“类的未定义方法可用路径”的错误。关于为什么会发生这种情况的任何想法?我没有可用模型的控制器,所以没有路线.. @Issac Betesh 好的。这通过将 path: 更改为 url: 来工作。不知道为什么,但确实如此!此外,在我的 line_items 控制器中,我确保将 available_attributes 包含到我的参数中,例如 - params.require(:line_item).permit(:price, :name, available_attributes: :[boolean]) 似乎path 很久以前就被url 弃用了。答案已更新。

以上是关于具有嵌套属性的 Best_In_Place 内联编辑的主要内容,如果未能解决你的问题,请参考以下文章

我如何将 country_select gem 与 best_in_place 编辑集成

JavaScript:具有 SRC 属性的内联脚本?

如何触发 best_in_place 事件

best_in_place 更新后保留原始值

内联元素的padding和margin

Django Admin 嵌套内联