有条件地在 Rails 中包含模块
Include module contionally in Rails
考虑具有重叠字段和功能的多个 ActiveRecord 类,并且其中许多重叠字段具有相同的验证。我正在尝试共享验证,但如果满足条件(基于模型的非重叠属性之一),则 运行 不共享代码。
class Book < ApplicationRecord
include SharedValidation
end
class Magazine < ApplicationRecord
include SharedValidation
end
module SharedValidation
extend ActiveSupport::Concern
include ActiveModel::Validations
validates_presence_of :name, :publisher, :author
end
假设 Magazine.is_deleted
是一个仅限杂志的字段,如果 is_deleted 为 false,我们只想 运行 共享验证。关于如何在 Class?
中实现这一点的任何想法
注意:我试图通过执行现场检测和评估来修改模块,但不确定这是否有意义或是否有效:
module SharedValidation
extend ActiveSupport::Concern
include ActiveModel::Validations
included do
proc do |rcd|
has_deleted_field = self.column_names.include?('is_deleted')
if (has_deleted_field && !rcd.is_deleted) || !has_deleted_field
validates_presence_of :name, :publisher, :author
end
end
end
end
看起来您可以将条件添加到验证方法(在 SharedModule 中),而不是有条件地包含模块。
使用您的样本:
class Book < ApplicationRecord
include SharedValidations
end
class Magazine < ApplicationRecord
include SharedValidations
end
module SharedValidations
extend ActiveSupport::Concern
include ActiveModel::Validations
def deleted
return unless self.class.column_names.include?("is_deleted")
is_deleted
end
included do
validates :name, :publisher, presence: true, unless: :deleted
end
end
杂志有 name
、publisher
和 is_deleted
栏。
书只有 name
, publisher
- 没有 is_deleted
.
看起来这个设置有效。
irb> book = Book.new()
=> #<Book id: nil, name: nil, publisher: nil, created_at: nil, updated_at: nil>
irb> book.valid?
=> false
irb> book.errors.full_messages
=> ["Name can't be blank", "Publisher can't be blank"]
irb> magazine = Magazine.new
=> #<Magazine id: nil, name: nil, publisher: nil, is_deleted: nil, created_at: nil, updated_at: nil>
irb> magazine.valid?
=> false
irb> magazine.errors.full_messages
=> ["Name can't be blank", "Publisher can't be blank"]
irb> magazine.is_deleted=true
=> true
irb> magazine.valid?
=> true
考虑具有重叠字段和功能的多个 ActiveRecord 类,并且其中许多重叠字段具有相同的验证。我正在尝试共享验证,但如果满足条件(基于模型的非重叠属性之一),则 运行 不共享代码。
class Book < ApplicationRecord
include SharedValidation
end
class Magazine < ApplicationRecord
include SharedValidation
end
module SharedValidation
extend ActiveSupport::Concern
include ActiveModel::Validations
validates_presence_of :name, :publisher, :author
end
假设 Magazine.is_deleted
是一个仅限杂志的字段,如果 is_deleted 为 false,我们只想 运行 共享验证。关于如何在 Class?
注意:我试图通过执行现场检测和评估来修改模块,但不确定这是否有意义或是否有效:
module SharedValidation
extend ActiveSupport::Concern
include ActiveModel::Validations
included do
proc do |rcd|
has_deleted_field = self.column_names.include?('is_deleted')
if (has_deleted_field && !rcd.is_deleted) || !has_deleted_field
validates_presence_of :name, :publisher, :author
end
end
end
end
看起来您可以将条件添加到验证方法(在 SharedModule 中),而不是有条件地包含模块。
使用您的样本:
class Book < ApplicationRecord
include SharedValidations
end
class Magazine < ApplicationRecord
include SharedValidations
end
module SharedValidations
extend ActiveSupport::Concern
include ActiveModel::Validations
def deleted
return unless self.class.column_names.include?("is_deleted")
is_deleted
end
included do
validates :name, :publisher, presence: true, unless: :deleted
end
end
杂志有 name
、publisher
和 is_deleted
栏。
书只有 name
, publisher
- 没有 is_deleted
.
看起来这个设置有效。
irb> book = Book.new()
=> #<Book id: nil, name: nil, publisher: nil, created_at: nil, updated_at: nil>
irb> book.valid?
=> false
irb> book.errors.full_messages
=> ["Name can't be blank", "Publisher can't be blank"]
irb> magazine = Magazine.new
=> #<Magazine id: nil, name: nil, publisher: nil, is_deleted: nil, created_at: nil, updated_at: nil>
irb> magazine.valid?
=> false
irb> magazine.errors.full_messages
=> ["Name can't be blank", "Publisher can't be blank"]
irb> magazine.is_deleted=true
=> true
irb> magazine.valid?
=> true