简体   繁体   中英

Validating polymorphic association type in Rails

I am developing a controller that creates a model with a polymorphic belongs_to association. What I do now to find the model it belongs to is as follows:

 def find_polymorphic_model(classes)
   classes_names = classes.map { |c| c.name.underscore + '_id' }

   params.select { |k, v| classes_names.include?(k) }.each do |name, value|
     if name =~ /(.+)_id$/
       return $1.classify.constantize.find(value)
     end
   end

  raise InvalidPolymorphicType
end

Where classes is an array of valid types for the association.

The problem with this approach is that I have to remember in the controller which types are allowed for the model I am creating.

Is there a way to find which types are allowed for a certain polymorphic belongs_to association? Or maybe I am doing this wrong and I should not let a polymorphic controller be exposed without nesting it in the polymorphic resource (in the router)?

I also think there may be problems with the fact that Rails lazy loads classes, so to be able to find out this thing I would have to explicitly load all models at initialization time.

For your validation you don't have to get all the possible polymorphic types. All you need is to check if the specified type (say, the value of taggable_type attribute) is suitable. You can do it this way:

# put it in the only_polymorphic_validator.rb. I guess under app/validators/. But it's up to you.
class OnlyPolymorphicValidator < ActiveModel::EachValidator
    def validate_each(record, attribute, value)
        polymorphic_type = attribute.to_s.sub('_type', '').to_sym
        specified_class = value.constantize rescue nil
        this_association = record.class.to_s.underscore.pluralize.to_sym

        unless(specified_class.reflect_on_association(this_association).options[:as] == polymorphic_type rescue false)
            record.errors[attribute] << (options[:message] || "isn't polymorphic type")
        end
    end
end

And then use:

validates :taggable_type, only_polymorphic: true

to check whether :taggable_type contains a valid class.

Answered too soon and didn't get that you are looking at polymorphic associations.

For associations in general, use reflect_on_all_associations .

However, for some polymorphic associations, there is no way to know all the classes which can implement the association. For some others, you need to look at the type field.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM