Search code examples
ruby-on-railsvalidationruby-on-rails-4virtual-attribute

Raise validation error from virtual attribute in Rails


I got two models: Source and SourceType. Source of course belongs to SourceType.
I want to create new source and assign proper sourcetype object to it. 'Proper' means that one virtual attribute of the source object match some of sourceType objects test regexpression, which becomes source's Type.

I got an attribute writer in source object

class Source < ActiveRecord::Base
   belongs_to :source_type    
   def url=(value)
       SourceType.each do |type|
          # here i match type's regexp to input value and if match, 
          # assign it to the new source object
       end
   end
end

I don't want to build any custom validator for it'll be need to run through SourceTypes twice. How to raise validate error if no sourcetypes is fit to the input so user could see error reasons in a form?


Solution

  • Validation

    If you set the virtual attribute using attr_accessor, you should be able to validate on the model you're sending data to (alternatively using inverse_of if you'd like to validate on the nested model):

    http://api.rubyonrails.org/classes/ActiveModel/Validator.html

    This can now be used in combination with the validates method (see ActiveModel::Validations::ClassMethods.validates for more on this).

    class Person
      include ActiveModel::Validations
      attr_accessor :title
    
      validates :title, presence: true
    end
    

    Code

    I'd do this:

    class Source < ActiveRecord::Base
       belongs_to :source_type, inverse_of: :sources
       attr_accessor :url
    end
    
    class SourceType < ActiveRecord::Base
       has_many :sources, inverse_of: :source_type
       validates :source_type_attr, presence: { if: :url_match? }
    
       def url_match?
          self.sources.url == [your_regex]
       end
    end