Search code examples
ruby-on-railsruby-on-rails-3validationdynamic-data

Rails 3.1 Validations defined in database


is there any way how to execute validation directives saved in database ?

See, i don't have staticaly defined attributes by database columns but are defined as row-type.

Examle:

Have groups and attributes. Every group should have different attributes.

Groups: id, name
Attributes: id, name
GroupAttributes: id, group_id, attribute_id, validation(serialize hash as string, same as rails validations)
Articles: id, group_id, attribute_id, value

Form is dynamicaly created based on which group is defined. Group 1 may have different validation for Attribute 1 than Group 1 for same Attribute.

But big problem are validations. I can't implicit define it in Model. Because i dont know which attributes are want to valide.

I have an idea evaluate string saved in database. But it is critical when there be injected code (which is very unespected).

Do you know any way how to resolve this ?

EDIT:

Principle is: I will write about CMS, it could be more clearer.

CMS have Articles/Posts and Post belongs to Group(Category).

Article should have many Attributes (saved in Attributes db table) like title, content, excerpt, thumbnail image, etc. But these attributes are not fixed in everyone article.

This is because Article belongs to Group. For example: news, posts, properties, reviews, etc.

And there is what i want. When i write some review, it is not neccessary put all fields(attributes) for all groups, only these which are needs.

So my idea is, that is easier to define attributes as "row type" instead "column type". Any time i'm able to add new, remove old for any Group. There could be tens of attributes (and different) for any group.

After neccessary joins all Models i want to define validation for each one attribute (column "validation" on top) and be used only for these attributes which are associated with group (GroupAttributes). Give these attribute validations into the Model, like standard Rails "validates". Without complicated "if" and "unless" conditional statements.

Hope is more detailed than first one.


Solution

  • You can try make custom validator and then loop attributes for group and evaluate their validation parameters on the article. But you will need a proper hash for rails validations.

    GroupAttributes.first.validation => {:presence => true, 
                    :length => {:minimum => 3, :maximum => 254},
                    :uniqueness => true}
    
    #app/models/article.rb
    class Article << ActiveRecord::Base 
      vlidates_with ArticleValidator
    end
    
    #lib/article_validator.rb
    class ArticleValidator << ActiveModel::Validator
      def validate(record)
        record.group.group_attributes.each do |group_attribute|
          record.validates group_attribute.attribute.name, group_attribute.validation
        end
      end
    end
    

    I am not sure if does this works but hope it will be helpfull.

    UPDATE: I was wrong it didn't work because validates is ActiveModel method not ActiveRecord like I thought. The right answer is you have to add before_validation callback and then setup the right validators.

    class Article << ActiveRecord::Base
    
      before_validation :set_validators
      validates :group_id, :presence => true
    
      privat
    
        def set_validators
          self.group.group_attributes.each do |group_attribute|
            Article.validates group_attribute.attribute.name, group_attribute.validation
          end
        end
      end