简体   繁体   English

无法使用带有Strong_parameters和嵌套属性的POST更新或创建记录

[英]Unable to update or create records using POST with strong_parameters and nested attributes

I can't figure out why my database records are not getting updated, or new records created, for that matter, when I POST from a form. 当我从表单中过帐时,我无法弄清楚为什么我的数据库记录没有得到更新或创建了新记录。

I am able to manually populate the database and create relationships: 我能够手动填充数据库并创建关系:

contact = Contact.first
command = Command.find(3)
contact.host_notification_commands << command

And I am also able to load this data info my form. 而且我还可以在我的表单中加载此数据信息。 What I can't figure out is how to update or add new records. 我不知道如何更新或添加新记录。 Everything i've tried so far has failed. 到目前为止,我尝试过的一切都失败了。

I have 3 models - Command , Contact and joined CommandsContact . 我有3个模型CommandContact和Joined CommandsContact commands_contacts join table is holing an extra attribute :notification_type , which could either be set to host or service , and my Contact model has 2 extra relationships setup to i can access :host_notification_commands and :service_notification_commands . commands_contacts联接表具有一个额外的属性:notification_type ,可以将其设置为主机服务 ,并且我的Contact模型设置了2个额外的关系,我可以访问:host_notification_commands:service_notification_commands This gives me an ability to do things like Contact.fist.host_notification_commands or Contact.find(3).service_notification_commands. 这使我能够执行诸如Contact.fist.host_notification_commandsContact.find(3).service_notification_commands.

It appears that no UPDATE or INSERT queries are ever firing up from the controller, when I to proper POST and I can't figure out how to debug that. 似乎没有UPDATEINSERT查询从控制器触发,当我执行正确的POST时,我不知道如何调试它。

Models 楷模

class Command < ActiveRecord::Base

  has_many :commands_contacts
  has_many :contacts, :through => :commands_contacts

end

class Contact < ActiveRecord::Base

    has_many :commands_contacts
    has_many :commands, :through => :commands_contacts

    has_many :host_notification_commands, -> { where commands_contacts: { :notification_type => 'host' } },
            :through => :commands_contacts,
            :class_name => 'Command', 
            :source => :command

    has_many :service_notification_commands, -> { where commands_contacts: { notification_type: 'service' } },
            :through => :commands_contacts,
            :class_name => 'Command', 
            :source => :command

    accepts_nested_attributes_for :commands, :host_notification_commands, :service_notification_commands

end

class CommandsContact < ActiveRecord::Base

    belongs_to :command
    belongs_to :contact

    accepts_nested_attributes_for :command

end

And after this everything falls apart. 在此之后,一切都崩溃了。

Controller 控制者

Due to the fact that I am using accepts_nested_attributes_for , I have to append _attributes to the names of my nested objects - :host_notification_commands and :service_notification_commands . 由于我正在使用accepts_nested_attributes_for ,因此我必须将_attributes附加到嵌套对象的名称- :host_notification_commands:service_notification_commands I'll change my form to submit it that way, but simple re-assignment works for an example sake. 我将更改表单以这种方式提交,但是出于示例目的,简单的重新分配有效。

def update
    contact = Contact.find_by_id(params[:id])
    contact.update(safe_params)
end    

private
def safe_params

    params[:contact][:host_notification_commands_attributes] = params[:contact][:host_notification_commands]
    params[:contact][:service_notification_commands_attributes] = params[:contact][:service_notification_commands]

    params.require(:contact)
        .permit(:contact_name, :host_notification_commands_attributes => [:id, :command_name, :command_line, :command_description],
                :service_notification_commands_attributes => [:id, :command_name, :command_line, :command_description])
end

Updating existing record results in: 更新现有记录结果:

#<ActiveRecord::RecordNotFound: Couldn't find Command with ID=2 for Contact with ID=1>

Of course it does not exist! 当然不存在! I am trying to create this relationship! 我正在尝试建立这种关系!

Adding a new one, I get: 添加一个新的,我得到:

#<ActiveRecord::RecordNotFound: Couldn't find Command with ID=1 for Contact with ID=>

Absolutely correct. 完全正确。 The user haven't even been created yet and relationship is not established with the commands, why is Rails trying to find it??? 用户甚至还没有创建,并且还没有通过命令建立关系,为什么Rails试图找到它?

I am also not seeing any update or insert queries being logged in the rails console, so i guess its not even getting to that point... 我也没有在Rails控制台中看到任何更新或插入查询,因此我想它甚至没有达到这一点...

D, [2015-01-20T18:01:30.336669 #95542] DEBUG -- :    (0.1ms)  BEGIN
D, [2015-01-20T18:01:30.338971 #95542] DEBUG -- :   Command Load (0.3ms)  SELECT `commands`.* FROM `commands` INNER JOIN `commands_contacts` ON `commands`.`id` = `commands_contacts`.`command_id` WHERE `commands_contacts`.`contact_id` = 1 AND `commands_contacts`.`notification_type` = 'host' AND `commands`.`id` IN (1, 3)
D, [2015-01-20T18:01:30.340555 #95542] DEBUG -- :   Command Load (0.2ms)  SELECT `commands`.* FROM `commands` INNER JOIN `commands_contacts` ON `commands`.`id` = `commands_contacts`.`command_id` WHERE `commands_contacts`.`contact_id` = 1 AND `commands_contacts`.`notification_type` = 'service' AND `commands`.`id` IN (4, 2)
D, [2015-01-20T18:01:30.341501 #95542] DEBUG -- :    (0.1ms)  ROLLBACK
#<ActiveRecord::RecordNotFound: Couldn't find Command with ID=2 for Contact with ID=1>
Completed 200 OK in 11ms (Views: 0.4ms | ActiveRecord: 0.9ms)

What am i missing over here? 我在这里想念什么?

EDIT: I guess i could abandon the idea of using strong_parameters , parse all POST params and then manually populate the database, but thats not very Rails-y. 编辑:我想我可以放弃使用strong_parameters的想法,解析所有POST参数,然后手动填充数据库,但是那不是Rails-y。

EDIT #2: Including params posted to the controller. 编辑2:包括发布到控制器的参数。

Data coming in as params[:contact] from the form 数据以params[:contact]形式输入

{
                     "contact_name" => "joe-user",
       "host_notification_commands" => [
        [0] {
                             "id" => 1,
                   "command_name" => "host-notify-by-email",
                   "command_line" => "/usr/local/bin/host-notify",
            "command_description" => "Host Alert",
                     "created_at" => "2015-01-19T17:24:12.000Z",
                     "updated_at" => "2015-01-21T03:29:03.000Z"
        },
        [1] {
                             "id" => 2,
                   "command_name" => "host-notify-by-pager",
                   "command_line" => "/usr/local/bin/host-notify-pager",
            "command_description" => "Host Alert by Pager",
                     "created_at" => "2015-01-19T17:24:33.000Z",
                     "updated_at" => "2015-01-19T17:24:33.000Z"
        }
    ],
    "service_notification_commands" => [
        [0] {
                             "id" => 4,
                   "command_name" => "service-notify-by-email",
                   "command_line" => "/usr/local/bin/service-notify",
            "command_description" => "Service Alert",
                     "created_at" => "2015-01-19T17:24:44.000Z",
                     "updated_at" => "2015-01-19T17:24:44.000Z"
        }
    ]
}

After going through strong_parameters it becomes this: 经过strong_parameters之后,它变成了:

Essentially the same thing, only with created_at and updated_at stripped and _attributes appended to the attribute names, so it works with accept_nested_attributes_for 本质上是一样的,只是剥离了created_atupdated_at并将_attributes附加到属性名称之后,因此它与accept_nested_attributes_for一起accept_nested_attributes_for

{
                                "contact_name" => "joe-user",
       "host_notification_commands_attributes" => [
        [0] {
                             "id" => 1,
                   "command_name" => "host-notify-by-email",
                   "command_line" => "/usr/local/bin/host-notify",
            "command_description" => "Host Alert"
        },
        [1] {
                             "id" => 2,
                   "command_name" => "host-notify-by-pager",
                   "command_line" => "/usr/local/bin/host-notify-pager",
            "command_description" => "Host Alert by Pager"
        }
    ],
    "service_notification_commands_attributes" => [
        [0] {
                             "id" => 4,
                   "command_name" => "service-notify-by-email",
                   "command_line" => "/usr/local/bin/service-notify",
            "command_description" => "Service Alert"
        }
    ]
}

EDIT #3: I have enabled MySQL query logging but I do not see UPDATE / INSERT queries executed at all. 编辑#3:我已启用MySQL查询日志记录,但我根本看不到执行UPDATE / INSERT查询。 How can i debug why contact.update(safe_params) is not doing anything? 我如何调试为什么contact.update(safe_params)没有做任何事情?

EDIT #4: As a simple test without AngularJS or POST being in the equation, I made a simple rake tasks that defines a JSON object and tries to update the db. 编辑#4:作为没有AngularJS或POST的简单测试,我做了一个简单的rake任务,该任务定义了JSON对象并尝试更新db。 I am getting the same issue, so Im pretty convinced the issue is somewhere in my models... but where??? 我遇到了同样的问题,因此我非常确信该问题在我的模型中某处...但是在哪里?

Please take a look at this Gist https://gist.github.com/pruchai/6afe74b170da2a3d307f 请看看这个要点https://gist.github.com/pruchai/6afe74b170da2a3d307f

When building a form and using nested_fields_for your form-structure is built correctly. 构建表单并使用nested_fields_for表单结构时,构建正确。 So ideally you would try first do it the "old fashioned way", check what is pushed to the server and mimick that. 因此,理想情况下,您将首先尝试以“老式方式”执行此操作,然后检查推送到服务器的内容并进行模拟。

So generally I do not do this by hand, but I maintain a gem to handle nested forms (cocoon), so if I am not mistaken, for the accepts_nested_attributes to work, the parameters have to look as follows: 因此,通常我不会手动执行此操作,但我会维护一个gem来处理嵌套表单(茧),因此,如果我没有记错的话, accepts_nested_attributes起作用,参数必须如下所示:

{
    "contact_name" => "joe-user",
    "host_notification_commands_attributes" => {
      "0" => {
        "id" => 1,
        "command_name" => "host-notify-by-email",
        "command_line" => "/usr/local/bin/host-notify",
        "command_description" => "Host Alert"
      },
      "1" => {
        "id" => 2,
        "command_name" => "host-notify-by-pager",
        "command_line" => "/usr/local/bin/host-notify-pager",
        "command_description" => "Host Alert by Pager"
      }
    },
    "service_notification_commands_attributes" => {
      "0" => {
        "id" => 4,
        "command_name" => "service-notify-by-email",
        "command_line" => "/usr/local/bin/service-notify",
        "command_description" => "Service Alert"
      }, 
      "12342233444444" => {
        "command_name" => "service-notify-by-email",
        "command_line" => "/usr/local/bin/service-notify",
        "command_description" => "Service Alert"
      }
    }
  }

So instead of an array the .._attributes should contain a hash. 因此, .._attributes不应包含数组,而应包含哈希。 The key is just the position in the (existing) array, I asuume. 关键在于(现有)数组中的位置,我认为。 In cocoon I fill this dummy index with some large number derived from the current time. 在茧中,我用从当前时间得出的一些大数字填充此虚拟索引 I assume this order should correspond to the default order for the relation. 我假设此顺序应与该关系的默认顺序相对应。 But if you hand down the "id" field, it is also possible rails uses that. 但是,如果您将“ id”字段交给您,那么Rails也可能会使用它。 Not sure. 不确定。 To destroy an existing element, you have to set the _destroy attribute (and allow it in the strong parameters as well). 要销毁现有元素,您必须设置_destroy属性(并在强参数中也允许它)。

Imho for new items the id should be empty, otherwise rails will assume the item exists (as generally ids are not generated on the client side). 恕我直言,新项目的id应该为空,否则Rails会假定该项目存在(因为通常不会在客户端生成ID)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 具有Mongoid和strong_parameters的嵌套_destroy属性 - Nested _destroy attribute with Mongoid and strong_parameters 如果在Rails 4中使用Mongoid时如何使用Strong_Parameters,如果它抛出了不允许的参数:嵌套属性上的(model_name)错误 - How to use Strong_Parameters in Rails 4 with Mongoid, if it throws Unpermitted parameters: (model_name) error on nested attributes 嵌套属性不适用于Simple_form,Decent_exposure,Strong_parameters - Nested Attributes not working with Simple_form, Decent_exposure, Strong_parameters Rails中使用datetime的strong_parameters - strong_parameters in Rails using datetime 在rails 3.2上的strong_parameters更新之后,如何更新嵌套对象? - How to update nested objects after strong_parameters update on rails 3.2? Strong_parameters不起作用 - Strong_parameters not working 如何使用strong_parameters允许除user_id之外的所有属性? - How to permit all attributes besides user_id using strong_parameters? Rails 4只更新嵌套属性的强参数 - rails 4 update only nested attributes strong parameters 使用Rails中的强参数一次创建或更新多个记录4 - Create or Update Multiple Records at a Single Time Using Strong Parameters in Rails 4 如何使用strong_parameters允许参数之一为任意哈希? - how to permit one of the parameters to be arbitrary hash using strong_parameters?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM