ruby on rails - सुपरक्लस या मिक्सिन द्वारा जोड़ा गया एक ActiveRecord सत्यापन को निकालकर या ओवरराइड कर रहा है




ruby-on-rails validation (6)

मैं निम्नलिखित हैक के साथ समस्या "हल" समाप्त हो गया:

  1. इस पर त्रुटि की खोज करें :email विशेषता प्रकार :taken
  2. जांच लें कि ईमेल इस खाते के लिए अद्वितीय है (जो कि सत्यापन है जो मैं करना चाहता था)
  3. यदि इस खाते के लिए ईमेल अद्वितीय है तो त्रुटि को निकालें

उचित लगता है जब तक आप कोड पढ़ नहीं पाते हैं और मैं एक त्रुटि को कैसे निकालूं? ActiveRecord::Errors में एक बार जोड़ दिए गए त्रुटियों को हटाने का कोई तरीका नहीं है, इसलिए मुझे इसे आंतरिक रूप से पकड़ना होगा और इसे स्वयं करना होगा सुपर डुपर मेगा बदसूरत

यह कोड है:

def validate
  super
  remove_spurious_email_taken_error!(errors)
end

def remove_spurious_email_taken_error!(errors)
  errors.each_error do |attribute, error|
    if error.attribute == :email && error.type == :taken && email_unique_for_account?
      errors_hash = errors.instance_variable_get(:@errors)
      if Array == errors_hash[attribute] && errors_hash[attribute].size > 1
        errors_hash[attribute].delete_at(errors_hash[attribute].index(error))
      else
        errors_hash.delete(attribute)
      end
    end
  end
end

def email_unique_for_account?
  match = account.users.find_by_email(email)
  match.nil? or match == self
end

अगर कोई बेहतर तरीके से जानता है, तो मैं बहुत आभारी रहूंगा।

मैं अपने रेल एप्लिकेशन में प्रमाणीकरण के लिए क्लीयरेंस का उपयोग कर रहा हूं Clearance::User मिक्सिन मेरे User मॉडल के लिए कुछ मान्यताओं को जोड़ता है, लेकिन उनमें से एक है जिसे मैं निकालना या ओवरराइड करना चाहता हूं। ऐसा करने का सबसे अच्छा तरीका क्या है?

सवाल में मान्यता है

validates_uniqueness_of :email, :case_sensitive => false

जो अपने आप में बुरी नहीं है, लेकिन मुझे जोड़ना होगा :scope => :account_id समस्या ये है कि अगर मैं इसे अपने User मॉडल में जोड़ता हूं

validates_uniqueness_of :email, :scope => :account_id

मुझे दोनों मान्यताओं मिलते हैं, और एक क्लीयरेंस जोड़ मेरे से अधिक प्रतिबंधात्मक है, इसलिए मेरा कोई प्रभाव नहीं है। मुझे यह सुनिश्चित करने की आवश्यकता है कि केवल मेरा रन मैं यह कैसे करु?


मुझे हाल ही में यह समस्या थी और Google ने मुझे तुरंत जवाब देने के बाद मुझे इस समस्या का अभी तक एक गैर-आदर्श समाधान पाया है। अब यह आपके मामले में जरूरी काम नहीं करेगा क्योंकि यह आपके पहले से मौजूद सुपर क्लासेस का प्रयोग कर रहा है, लेकिन मेरे लिए यह मेरा अपना कोड था इसलिए मैंने इसका इस्तेमाल किया: यदि सुपर क्लास में टाइप चेक के साथ परम

def SuperClass
  validates_such_and_such_of :attr, :options => :whatever, :if => Proc.new{|obj| !(obj.is_a? SubClass)}
end

def SubClass < SuperClass
  validates_such_and_such_of :attr
end

बहुपक्षीय उप वर्गों के मामले में

def SuperClass
  validates_such_and_such_of :attr, :options => :whatever, :if => Proc.new{|obj| [SubClass1, SubClass2].select{|sub| obj.is_a? sub}.empty?}
end

def SubClass1 < SuperClass
  validates_such_and_such_of :attr
end

def SubClass2 < SuperClass
end

मुझे पता है कि मैं खेल में देर कर रहा हूं, लेकिन यह कैसे है:

module Clearance
  module User
    module Validations
      extend ActiveSupport::Concern

      included do
        validates :email,
          email: true,
          presence: true,
          uniqueness: { scope: :account, allow_blank: true },
          unless: :email_optional?

        validates :password, presence: true, unless: :password_optional?
      end
    end
  end
end

एक प्रारंभिक में?


त्रुटियाँ। डीलीट (कुंजी) एक विशेषता के लिए सभी त्रुटियों को निकालती है और मैं केवल एक विशेष प्रकार की त्रुटि को एक विशेषता से निकालना चाहता हूं। यह निम्नलिखित विधि किसी भी मॉडल में जोड़ा जा सकता है।

हटाए जाने पर संदेश लौटाता है, अन्यथा नाइल आंतरिक डेटा संरचनाओं को संशोधित किया जाता है ताकि त्रुटि हटाने के बाद अपेक्षित सभी अन्य तरीकों को काम करना चाहिए।

एमआईटी लाइसेंस के तहत जारी

मान्यताओं के बाद मॉडल से त्रुटि को हटाने का तरीका चलाया गया है।

def remove_error!(attribute, message = :invalid, options = {})
  # -- Same code as private method ActiveModel::Errors.normalize_message(attribute, message, options).
  callbacks_options = [:if, :unless, :on, :allow_nil, :allow_blank, :strict]
  case message
  when Symbol
    message = self.errors.generate_message(attribute, message, options.except(*callbacks_options))
  when Proc
    message = message.call
  else
    message = message
  end
  # -- end block

  # -- Delete message - based on ActiveModel::Errors.added?(attribute, message = :invalid, options = {}).
  message = self.errors[attribute].delete(message) rescue nil
  # -- Delete attribute from errors if message array is empty.
  self.errors.messages.delete(attribute) if !self.errors.messages[attribute].present?
  return message
end

उपयोग:

user.remove_error!(:email, :taken)

विशिष्ट विशेषताओं और संदेशों को छोड़कर वैधता की जांच करने का तरीका।

def valid_except?(except={})
  self.valid?
  # -- Use this to call valid? for superclass if self.valid? is overridden.
  # self.class.superclass.instance_method(:valid?).bind(self).call
  except.each do |attribute, message|
    if message.present?
      remove_error!(attribute, message)
    else
      self.errors.delete(attribute)
    end
  end
  !self.errors.present?
end

उपयोग:

user.valid_except?({email: :blank})
user.valid_except?({email: "can't be blank"})

मुझे स्परी उत्पाद संपत्ति को हटाने की जरूरत है :value मान्यता और ऐसा लगता है कि Klass.class_eval और clear_validators! साथ एक सरल समाधान है clear_validators! AciveRecord::Base

module Spree
  class ProductProperty < Spree::Base

    #spree logic

    validates :property, presence: true
    validates :value, length: { maximum: 255 }

    #spree logic


  end
end

और इसे यहां ओवरराइड करें

Spree::ProductProperty.class_eval do    
  clear_validators!
  validates :property, presence: true
end

मैं मणि काटा और एक साधारण जांच जोड़ूंगा, जिसे तब ओवरराइड किया जा सकता है मेरा उदाहरण एक चिंता का उपयोग करता है

चिंता:

module Slugify

  extend ActiveSupport::Concern

  included do

    validates :slug, uniqueness: true, unless: :skip_uniqueness?
  end

  protected

  def skip_uniqueness?
    false
  end

end

आदर्श:

class Category < ActiveRecord::Base
  include Slugify

  belongs_to :section

  validates :slug, uniqueness: { scope: :section_id }

  protected

  def skip_uniqueness?
    true
  end
end






clearance