【问题标题】:Rails 4 - Order of has_many, through nested attributes in formRails 4 - has_many 的顺序,通过表单中的嵌套属性
【发布时间】:2015-11-11 03:06:46
【问题描述】:

tl,dr:如何确保我的 has_many 的顺序,通过嵌套属性,在构建中设置了属性值,总是被分配相同的嵌套参数哈希键号(0 , 1, etc.) 并且总是以相同的顺序出现在表单中?

希望我能描述一下,这样才有意义。我有一个小型原型应用程序,可以模拟两个账户(源账户和目标账户)之间的简单银行转账。我有一个Transfer 类、一个Account 类和一个TransferAccounts 类,它是TransferAccount 之间的many_to_many 关联的直通连接。

这是TransfersController 中的new 操作:

def new
  @transfer = Transfer.new
  @transfer.transfer_accounts.build(account_transfer_role: 'source').build_account
  @transfer.transfer_accounts.build(account_transfer_role: 'destination').build_account
  bank_selections
  account_selections
end  

还有强参数:

def transfer_params
  params.require(:transfer).
    permit(:name, :description,
           transfer_accounts_attributes:
             [:id, :account_id, :account_transfer_role,
              account_attributes:
                [:id, :bank_id, :name, :description, :user_name,
                 :password, :routing_number, :account_number
                ]
             ])
end

因此,与transfer 关联的两个transfer_accounts 各有一个account_transfer_role 属性,其中一个设置为source,另一个设置为destination.

现在,填写表单并提交时,控制台中的参数如下所示:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"xxxxxxxxxxxxxxxxxx==",
"transfer"=>{"name"=>"Test Transfer 2", "description"=>"Second test transfer",
"transfer_accounts_attributes"=>{"0"=>{"account_transfer_role"=>"source", "account_id"=>"1",
"account_attributes"=>{"bank_id"=>"1", "name"=>"George's Checking",
"description"=>"George's personal checking account", "user_name"=>"georgeckg",
"password"=>"[FILTERED]", "account_number"=>"111111111", "routing_number"=>"101010101",
"id"=>"3"}, "id"=>"3"}, "1"=>{"account_transfer_role"=>"destination", "account_id"=>"2",
"account_attributes"=>{"bank_id"=>"2", "name"=>"George's Savings",
"description"=>"George's personal savings account", "user_name"=>"georgesav",
"password"=>"[FILTERED]", "account_number"=>"111101111", "routing_number"=>"100100100",
"id"=>"4"}, "id"=>"4"}}}, "commit"=>"Update Transfer", "id"=>"2"}

如您所见,transfer_account_attributes 哈希中的每个 transfer_account 都有一个 id 键,可以是 01(例如 ..."0"=>{"account_transfer_role"=>"source"...) .现在,我一直在假设(我认为它可能会回来咬我,并且确实如此)因为它们在 new 操作中构建的顺序,source @ 987654338@ 总是有一个 0 的 id 键和 destination transfer_account 总是有一个 1 的 id 键,这导致我在控制器的其他地方使用这些 id 键,就好像 0 代表 source1 代表 destination

在我尝试创建新帐户或使用现有帐户、创建新帐户或编辑现有转账的不同排列时,一切似乎都运行良好,但突然出现了 destination 列在 first 和 source second,以前没有发生,导致条目现在具有与 0 关联的destination em> 和 source1 关联,破坏了上面提到的控制器中的代码。

为了更清楚,这里是表格:

#transfer_form
  = simple_form_for @transfer do |t|
    .form-inputs

      = t.input :name, label: 'Transfer Name'
      = t.input :description, required: false, label: 'Transfer Description'

      = t.simple_fields_for :transfer_accounts do |ta|

        - role = ta.object.account_transfer_role.titleize
        = ta.input :account_transfer_role, as: :hidden

        = ta.input :account_id, collection:    @valid_accounts,
                                include_blank: 'Select account...',
                                label:         "#{ role } Account",
                                error:         'Account selection is required.'

        .account_fields{id: "#{ role.downcase }_account_fields"}

          = ta.simple_fields_for :account do |a|

            = a.input :bank_id,        collection:    @valid_banks,
                                       include_blank: 'Select bank...',
                                       label:         "#{ role } Bank",
                                       error:         'Bank selection is required.',
                                       class:         "#{ role.downcase }_account_input_field"

            = a.input :name,           label:    "#{ role } Account Name",
                                       class:    "#{ role.downcase }_account_input_field"

            = a.input :description,    required: false,
                                       label:    "#{ role } Account Description",
                                       class:    "#{ role.downcase }_account_input_field"

            = a.input :user_name,      label:    "#{ role } Account User Name",
                                       class:    "#{ role.downcase }_account_input_field"

            = a.input :password,       label:    "#{ role } Account Password",
                                       class:    "#{ role.downcase }_account_input_field"

            = a.input :account_number, label:    "#{ role } Account Number",
                                       class:    "#{ role.downcase }_account_input_field"

            = a.input :routing_number, label:    "#{ role } Account Routing Number",
                                       class:    "#{ role.downcase }_account_input_field"

    = t.submit

我如何确保 source 始终是第一个,因此始终与 id 键 0 相关联> 和 destination 总是第二个,总是与 id 键 1 相关联?

【问题讨论】:

    标签: forms ruby-on-rails-4 activerecord nested-attributes strong-parameters


    【解决方案1】:

    答案似乎就像在我的Transfer 模型中更改:transfer_accounts 关联行一样简单:

    has_many  :transfer_accounts, inverse_of: :transfer
    

    到这里:

    has_many  :transfer_accounts, -> { order('account_transfer_role DESC') }, inverse_of: :transfer
    

    如果有人认为它没有像我认为的那样做,请告诉我,因为目前它似乎正在解决我的问题。

    【讨论】:

    • 您在这里所做的只是要求数据库按照account_transfer_role 的字母顺序将transfer_accounts 返还给您。这感觉很糟糕,因为这会影响您对transfer_accounts的所有查询,而您只需要按该顺序显示它们。
    猜你喜欢
    • 2014-03-25
    • 1970-01-01
    • 2016-03-23
    • 2021-08-12
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    相关资源
    最近更新 更多