Ruby on rails Rails嵌套属性不以一对一关系保存(仅限API)

Ruby on rails Rails嵌套属性不以一对一关系保存(仅限API),ruby-on-rails,ruby,Ruby On Rails,Ruby,出于某种原因,在使用accepts\u nested\u attributes\u时,我的一对一关系都没有保存在rails中 例如,有一个用户表和一个概要文件表。它们之间有直接的关系,每个用户都需要有一个配置文件 因此,在POST/users/上,有必要为用户创建关联的配置文件 然而,由于某些原因,这并没有发生,我得到了一个空列冲突错误,因为尽管允许,我的所有嵌套属性都被忽略 我的用户模型如下: 类用户:销毁 ... 验证:password,password:true,on::create 验证

出于某种原因,在使用accepts\u nested\u attributes\u时,我的一对一关系都没有保存在rails中

例如,有一个用户表和一个概要文件表。它们之间有直接的关系,每个用户都需要有一个配置文件

因此,在POST/users/上,有必要为用户创建关联的配置文件

然而,由于某些原因,这并没有发生,我得到了一个空列冲突错误,因为尽管允许,我的所有嵌套属性都被忽略

我的用户模型如下:

类用户<应用程序记录 用巫术认证你! 属性写入器:配置文件属性 有很多:帐户,外键:'users\u id' 有一个:配置文件,外键:'user\u id' 有多个:身份验证,:依赖=>:销毁 ... 验证:password,password:true,on::create 验证:电子邮件,状态:true,唯一性:true,格式:{with:URI::MailTo::email_REGEXP} 创建前:设置用户类型 保存前:生成配置文件 接受:profile的\u嵌套\u属性\u,如果::all\u blank,则拒绝\u 接受\u嵌套的\u属性\u用于:身份验证 ... 终止 配置文件模型如下所示:

类配置文件<应用程序记录 属于:用户,外键:'user\u id',多态:true,可选:true 属性访问器:名字,:姓氏 ... 验证\u日期:生日,在:->{16.years.ago},在\u消息“必须至少16岁”之前,允许\u nil:true 验证:profile_image,url:{allow_nil:true,no_local:true} 验证:名字,状态:true 验证:姓氏,状态:true 验证:性别,枚举:性别 ... 终止 和UsersController创建方法

def创建 user=user.create user_参数 raise RBError::ValidationError.newuser.errors,除非user.save 响应user.as_json,:已创建 终止 私有的 def用户参数 参数要求:数据 .许可证:电子邮件、密码、电话号码、{ 配置文件属性:[ :名字,:姓氏,:性别,:出生日期,:个人资料\u图像 ] } 终止 JSON请求如下所示:

{
    "data": {
        "email": [omitted],
        "password": [omitted],
        "profile_attributes": {
            "first_name": "John",
            "last_name": "Doe"
        }
    }
}
使用此响应错误

 "#<ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR:  null value in column \"first_name\" violates not-null constraint\nDETAIL:  Failing row contains (23, 31, null, null, null, null, 2019-08-10 11:49:40.021683, 2019-08-10 11:49:40.021683, null, null).\n: INSERT INTO \"profiles\" (\"user_id\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3) RETURNING \"id\">",
因此,正如您所看到的,请求中发送的所有属性都被完全忽略。我不知道为什么,这让我抓狂。我似乎找不到任何与我的问题有点类似的东西

所有的参数都是允许的,剖面模型的验证工作也如预期的那样

 Parameters: {"data"=>{"email"=>"sample@fgmail.com", "password"=>"[FILTERED]", "profile_attributes"=>{"first_name"=>"John", "last_name"=>"Doe"}}, "user"=>{}}
<ActionController::Parameters {"email"=>"sample@fgmail.com", "password"=>[OMITTED], "profile_attributes"=><ActionController::Parameters {"first_name"=>"John", "last_name"=>"Doe"} permitted: true>} permitted: true>
切勿在Rails模型*中使用attr_writer或attr_accessor

attr_accessor :first_name, :last_name
将通过读取数据库架构覆盖ActiveRecord已经创建的setter。这些setter不仅设置实例变量,还触发脏跟踪,该跟踪跟踪应保存到数据库的模型更改

您的验证仍将通过,因为@first\u name和@last\u name不是零,但当您调用@user.save ActiveRecord::AttributeMethods::Dirtychanges\u to\u save时,first\u name和:last\u name的值将为零

attr\u writer:profile\u属性实际上更糟糕。您正在使用的是一个更高级的元编程版本:

class User < ApplicationRecord
  def profile_attributes=(hash)
    self.build_profile(hash)
  end
end

在保存:build\u profile之前,build\u profile方法做什么?另外,为什么要在配置文件模型上定义attr\u访问器:first\u name、:last\u name?first_name和last_name应该由ActiveRecord定义,可能您已经覆盖了first和last name的访问器,这就是它不起作用的原因。attr_writer也可能发生同样的事情:用户模型上的profile_属性,它也应该由ActiveRecord直接定义。老实说,我不知道为什么会有访问器和写入器,我在那里添加了它,希望它能工作,因为没有它它它仍然不能工作。是的,我对rails有点陌生build_profile是由ActiveRecord为所有关系定义的,比如你可以称之为build_*并且据我所知,它应该用关联的属性建立/创建关系OK,尝试删除attr_writer:profile_attributes行,然后在User和attr_accessor:first_name中保存:build_profile,:您的代码中配置文件中的姓氏。您不应该需要它们,所有这些东西都应该通过ActiveRecord提供。然后试试看它是否有效,也许有帮助。*嗯,几乎从来没有。但至少不要将它用于表支持的属性、关联或任何应该用attributes API完成的事情。谢谢。最终对我起作用的是这样的东西:user=user.newuser_params user.build_profile user_params[:profile_attributes]
class User < ApplicationRecord
  def profile_attributes=(value)
    @profile_attributes = value
  end
end
def new
  @user = User.new
  @user.build_profile
end