【问题标题】:Custom Active Admin form inputs for has_and_belongs_to_many relationshiphas_and_belongs_to_many 关系的自定义 Active Admin 表单输入
【发布时间】:2012-10-29 22:52:05
【问题描述】:

我有一个非常简单的模型

class Lifestyle < ActiveRecord::Base
  attr_accessible :name
  has_and_belongs_to_many :profiles
end

Profilehas_and_belongs_to_many 关系

class Profile < ActiveRecord::Base
  attr_accessible ...

  belongs_to :occupation

  has_and_belongs_to_many :lifestyles
  accepts_nested_attributes_for :lifestyles
end

我想使用 ActiveAdmin 来编辑 Profile 对象,同时将 Lifestyles 分配给配置文件。它应该类似于处理belongs_to :occupation,因为这会由 ActiveAdmin 自动分类到一个带有可用职业的选项的保管箱中。

我尝试使用 has_many 表单构建器方法,但这只让我显示一个表单以输入 Lifestyle 的名称,并且在提交时返回错误。

    f.object.lifestyles.build
    f.has_many :lifestyles do |l|
      l.input :name
    end

我得到的错误:

Can't mass-assign protected attributes: lifestyles_attributes

对我来说完美的方法是构建几个复选框,一个用于数据库中的每个生活方式。选中表示生活方式与配置文件相关联,未选中表示删除关系。

我非常怀疑这是否可以使用 ActiveAdmin 而不必创建非常复杂的逻辑来处理这个问题。 如果您能提出您的意见并建议我是应该走这条路还是采取不同的方式,我将不胜感激。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 forms associations activeadmin


    【解决方案1】:

    经过一番研究,我准备回答我自己的问题。

    首先,我要感谢@Lichtamberg 提出的修复建议。但是,这只会使事情复杂化(也涉及安全性,尽管在这种情况下不是问题),并且无助于我达到理想的解决方案。

    挖掘更多,我发现这是Rails中非常常见的场景,它实际上在Ryan Bates' screencast no #17中进行了解释。

    因此,在Rails中,如果你有一个has_and_belongs_to_many(简称HABTM)关联,你可以通过这个方法轻松设置其他关联对象的id:

    profile.lifestyle_ids = [1,2]
    

    如果您为 Lifestyle_ids 设置了 attr_accessible,这显然适用于表单:

    class Profile < ActiveRecord::Base
      attr_accessible :lifestyle_ids
    end
    

    在ActiveAdmin中,因为它使用Formtastic,你可以使用这个方法来输出正确的字段(这里是复选框):

    f.input :lifestyles, as: :check_boxes, collection: Lifestyle.all
    

    另外,我已经简化了我的表单视图,所以现在只是这样:

      form do |f|
        f.inputs # Include the default inputs
        f.inputs "Lifestlyes" do # Make a panel that holds inputs for lifestyles
          f.input :lifestyles, as: :check_boxes, collection: Lifestyle.all # Use formtastic to output my collection of checkboxes
        end
        f.actions # Include the default actions
      end
    

    好的,现在这在视图中完美呈现,但如果我尝试提交我的更改,它会给我这个数据库错误:

    PG::Error: ERROR:  null value in column "created_at" violates not-null constraint
    : INSERT INTO "lifestyles_profiles" ("profile_id", "lifestyle_id") VALUES (2, 1) RETURNING "id"
    

    我发现这是因为 Rails 3.2 不会自动更新 HABTM 关联表的时间戳(因为它们是额外的属性,而且 Rails 只处理 _id 属性。

    有两种解决方案可以解决此问题:

    1. 要么将关联转换为 hm:t (has_many, :through =&gt;)
    2. 或从表中删除时间戳

    我将选择 2),因为我永远不需要时间戳或任何额外的属性。

    我希望这可以帮助其他遇到同样问题的人。

    编辑: @cdesrosiers 最接近解决方案,但我在阅读他的答案之前已经写了这个答案。无论如何,这还是很棒的。我学到了很多东西。

    【讨论】:

    • +1 花时间详细回答您自己的问题。
    • 有趣的是,我不必手动指定collection(activeadmin 0.5.1,formtastic 2.2.1)。无论如何,答案都很好!
    【解决方案2】:

    Active Admin 在 formtastic 上创建了一个精简的 DSL(域特定语言),因此当您需要表单自定义时,最好查看 formastic doc。在那里,您会发现您可以使用f.input :lifestyles, :as =&gt; :check_boxes 来修改has_and_belongs_to_many 关系。

    我说“可能”是因为我自己没有针对您的特殊情况尝试过这个助手,但是这些东西往往会自动运行,所以试试吧。

    另外,你可能不需要accepts_nested_attributes_for :lifestyles,除非你真的想从profiles修改lifestyles的属性,我认为这在使用活动管理员时不是特别有用(只需修改lifestyles直接)。

    【讨论】:

    • 很好,很好的答案。我只是在写我自己的答案,并没有看到这一点。我最终想通了,Ryan Bates 的截屏视频帮助我了解了你在这里谈论的内容。我知道 Rails 有更聪明的方法:)
    【解决方案3】:

    添加

    attr_accessible :lifestyles_attributes
    

    f.e.:

    class AccountsController < ApplicationController
      attr_accessible :first_name, :last_name
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多