我有一个问题,我有下一个类
class Question < ApplicationRecord
include Mappable
...
end
所以我的问题是在创建一个问题的时候,我需要保留问题验证,但跳过那些来自mapappable
的验证因为现在我用的是question.save(validate: false)
我需要将其更新为question.save(mappable_validate: false)
这样就可以跳过mapable
的验证EDIT
可映射:
module Mappable
extend ActiveSupport::Concern
included do
attr_accessor :skip_map
has_one :map_location, dependent: :destroy
accepts_nested_attributes_for :map_location, allow_destroy: true, reject_if: :all_blank
validate :map_must_be_valid, on: :create, if: :feature_maps?
def map_must_be_valid
return true if skip_map?
unless map_location.try(:available?)
skip_map_error = "Map error"
errors.add(:skip_map, skip_map_error)
end
end
def feature_maps?
Setting["feature.map"].present?
end
def skip_map?
skip_map == "1"
end
end
end
有很多方法可以解决这个问题。但是没有不涉及修改模块的可靠的。
一种方法是简单地使用组合并将验证移动到自己的模块中:
module Mappable
module Validations
extend ActiveSupport::Concern
included do
validate :map_must_be_valid, on: :create, if: :feature_maps?
end
end
end
class Question < ApplicationRecord
include Mappable
end
class Foo < ApplicationRecord
include Mappable
include Mappable::Validations
end
让模块提供的行为可定制的另一种非常常见的方法是不要把所有的代码都塞进不让你传递选项的Module#included
钩子中。
创建一个类方法:
module Mappable
extend ActiveSupport::Concern
def map_must_be_valid
return true if skip_map?
unless map_location.try(:available?)
skip_map_error = "Map error"
errors.add(:skip_map, skip_map_error)
end
end
def feature_maps?
Setting["feature.map"].present?
end
def skip_map?
skip_map == "1"
end
module ClassMethods
def make_mappable(validate: true)
attr_accessor :skip_map
has_one :map_location, dependent: :destroy
accepts_nested_attributes_for :map_location,
allow_destroy: true, reject_if: :all_blank
if validate
validate :map_must_be_valid, on: :create, if: :feature_maps?
end
end
end
end
然后在你想修改的类中调用类方法
class Question < ApplicationRecord
include Mappable
make_mappable(validate: false)
end
这个模式在Rails和Ruby中随处可见,它让你提供的功能更加灵活。
我明白,这似乎不是立即有帮助,因为代码是来自一个宝石。但它可以帮助您了解如何修复gem或评估它是否真正值得/需要。