Rails - 新用户构建依赖电子邮件并验证两者?
Rails - new User builds dependent Email and validates both?
我正在构建一个快速的 Rails 项目,允许用户管理他们的电子邮件地址。用户可以有很多电子邮件,但是其中一个(并且只有一个)电子邮件必须标记为 'primary'(用于登录),并且没有主电子邮件就不能存在用户。
我一直在努力让它正常工作 - 它对我来说似乎太循环了。我需要建立一个用户,然后是电子邮件,但我不想将用户保存到数据库中,除非电子邮件是有效的,直到用户被保存(因为 validates :user, presence: true
约束)。
接受嵌套资源似乎不适用于 .new
(适用于 .create
),如果我的电子邮件未通过验证,用户仍显示为有效。
在尝试从单一表单中为 building/validating multiple/dependent 模型找到好的资源(或 SO 问题)时遇到了困难。
最 Rails 的方法是什么?
用户
has_many :emails
has_one :primary_email, -> { where(primary: true) }, class_name: "Email"
accepts_nested_attributes_for :primary_email
validates :first_name, presence: true
validates :last_name, presence: true
validates :birthday, presence: true
validates :password_digest, presence: true
电子邮件
belongs_to :user
validates :user, presence: true
validates :address, presence: true, uniqueness: {
case_sensitive: false
}
用户控制器
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
# do something
else
# show @user.errors
end
end
private
def user_params
params.require(:user).permit(
:first_name,
:last_name,
:birthday,
:password,
:password_confirmation,
:primary_email_attributes => [:address]
)
end
编辑
Email 模型还包含以下字段:
- label = 字符串,例如。 'Personal'、'Work'、等等
- primary = boolean,是否标记为主邮箱
- confirmation_code = 创建时自动生成,用于确认所有权
- confirmed = boolean,是否被确认
class User
user has_many :emails
user has_one :primary_email, -> { where(primary: true) }, class_name: "Email", autosave: true
after_initialize {
build_primary_email if new_record?
}
end
class Email
# use gem https://github.com/balexand/email_validator
validates :my_email_attribute, :email => true
end
因此,在用户初始化其构建 primary_email 之后,该记录已经关联,或者至少在可以保存的情况下将会关联。自动保存功能非常棒——如果由于验证错误而无法保存主电子邮件,则用户也不能。应该开箱即用,我现在在公共汽车上,无法检查。干杯
更多信息:http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
如果任何关联的验证失败,它们的错误消息将应用于父级。这意味着,父级模型(在您的情况下是用户)有错误,这就是为什么无法保存的原因!这就是你要找的。
我会将主要电子邮件存储为公共字段,并以其他方式存储其他电子邮件。我更愿意将额外的电子邮件存储在另一个字段中,即数组而不是关联的 table。您不应将主要电子邮件存储在另一个 table 中。试想一下,每次您需要授权用户或只是收到他的电子邮件时,您都会对 db 执行额外的请求。
这个月前post。
在不将主要电子邮件存储为用户属性的情况下,使用户和电子邮件在不同模型中保持规范化的解决方案是使用 inverse_of
:
User.rb
class User < ActiveRecord::Base
has_many :emails, inverse_of: :user, dependent: :destroy
accepts_nested_attributes_for :emails
validates :emails, presence: true
end
Email.rb
class Email < ActiveRecord::Base
belongs_to :user, inverse_of: :emails
validates :user, presence: true
end
这允许使用内存中的对象执行验证,而不是通过数据库调用(即正在验证对象关联,而不是数据库中是否存在 id/record)。因此它们都通过了验证,并且都可以保存在同一个交易中。
参见:https://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations
我正在构建一个快速的 Rails 项目,允许用户管理他们的电子邮件地址。用户可以有很多电子邮件,但是其中一个(并且只有一个)电子邮件必须标记为 'primary'(用于登录),并且没有主电子邮件就不能存在用户。
我一直在努力让它正常工作 - 它对我来说似乎太循环了。我需要建立一个用户,然后是电子邮件,但我不想将用户保存到数据库中,除非电子邮件是有效的,直到用户被保存(因为 validates :user, presence: true
约束)。
接受嵌套资源似乎不适用于 .new
(适用于 .create
),如果我的电子邮件未通过验证,用户仍显示为有效。
在尝试从单一表单中为 building/validating multiple/dependent 模型找到好的资源(或 SO 问题)时遇到了困难。
最 Rails 的方法是什么?
用户
has_many :emails
has_one :primary_email, -> { where(primary: true) }, class_name: "Email"
accepts_nested_attributes_for :primary_email
validates :first_name, presence: true
validates :last_name, presence: true
validates :birthday, presence: true
validates :password_digest, presence: true
电子邮件
belongs_to :user
validates :user, presence: true
validates :address, presence: true, uniqueness: {
case_sensitive: false
}
用户控制器
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
# do something
else
# show @user.errors
end
end
private
def user_params
params.require(:user).permit(
:first_name,
:last_name,
:birthday,
:password,
:password_confirmation,
:primary_email_attributes => [:address]
)
end
编辑
Email 模型还包含以下字段:
- label = 字符串,例如。 'Personal'、'Work'、等等
- primary = boolean,是否标记为主邮箱
- confirmation_code = 创建时自动生成,用于确认所有权
- confirmed = boolean,是否被确认
class User
user has_many :emails
user has_one :primary_email, -> { where(primary: true) }, class_name: "Email", autosave: true
after_initialize {
build_primary_email if new_record?
}
end
class Email
# use gem https://github.com/balexand/email_validator
validates :my_email_attribute, :email => true
end
因此,在用户初始化其构建 primary_email 之后,该记录已经关联,或者至少在可以保存的情况下将会关联。自动保存功能非常棒——如果由于验证错误而无法保存主电子邮件,则用户也不能。应该开箱即用,我现在在公共汽车上,无法检查。干杯
更多信息:http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
如果任何关联的验证失败,它们的错误消息将应用于父级。这意味着,父级模型(在您的情况下是用户)有错误,这就是为什么无法保存的原因!这就是你要找的。
我会将主要电子邮件存储为公共字段,并以其他方式存储其他电子邮件。我更愿意将额外的电子邮件存储在另一个字段中,即数组而不是关联的 table。您不应将主要电子邮件存储在另一个 table 中。试想一下,每次您需要授权用户或只是收到他的电子邮件时,您都会对 db 执行额外的请求。
这个月前post。
在不将主要电子邮件存储为用户属性的情况下,使用户和电子邮件在不同模型中保持规范化的解决方案是使用 inverse_of
:
User.rb
class User < ActiveRecord::Base
has_many :emails, inverse_of: :user, dependent: :destroy
accepts_nested_attributes_for :emails
validates :emails, presence: true
end
Email.rb
class Email < ActiveRecord::Base
belongs_to :user, inverse_of: :emails
validates :user, presence: true
end
这允许使用内存中的对象执行验证,而不是通过数据库调用(即正在验证对象关联,而不是数据库中是否存在 id/record)。因此它们都通过了验证,并且都可以保存在同一个交易中。
参见:https://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations