ActiveRecord validation reflection.

In my model class I have:
  class X < ActiveRecord:Base
    validates_length_of :login, :within => 3..40
  end

In my view file I do:
    <label for="login">Login (3..40 characters)

Is there a way to query this length information?
Hence, having hard-coded "3..40" in the view is NOT good, as the length
limit may change from model definition. I rather do something like:
    <label for="login">Login (<%= find_the_frigging_length_from_model_X
%> characters)

thx,
Ray

You could set the minumum and/or maximum via a class attribute. Like I just did in the console.

>> class Joe
>> @@val = {:pass_length => {:min => 3, :max => 40}}
>> cattr_accessor :val
>> end
=> [:val]
>> Joe.val
=> {:pass_length=>{:min=>3, :max=>40}}
>> Joe.val[:pass_length][:min]
=> 3
>>

Then do your validations also using the class attribute
validates_length_of :login, :within => val[:login][:min]..val[:login][:max]

Voila!
Jason

rexaler wrote:

Hi

To cope with similar issues some time ago I released this project

http://simpledesc.rubyforge.org/

Maybe you can find it of some help.
It provides a facility to store and query extra data about your classes / models

The current release is working but the code is not brilliant. In
subversion there's already a newer version which I may release as a
gem in the next few weeks.

Paolo

You could set the minumum and/or maximum via a class attribute. Like I
just did in the console.

>> class Joe
>> @@val = {:pass_length => {:min => 3, :max => 40}}
>> cattr_accessor :val
>> end
=> [:val]
>> Joe.val
=> {:pass_length=>{:min=>3, :max=>40}}
>> Joe.val[:pass_length][:min]
=> 3
>>

Then do your validations also using the class attribute
validates_length_of :login, :within =>
val[:login][:min]..val[:login][:max]

Voila!
Jason

rexaler wrote:

> In my model class I have:
> class X < ActiveRecord:Base
> validates_length_of :login, :within => 3..40
> end

> In my view file I do:
> <label for="login">Login (3..40 characters)

> Is there a way to query this length information?
> Hence, having hard-coded "3..40" in the view is NOT good, as the length
> limit may change from model definition. I rather do something like:
> <label for="login">Login (<%= find_the_frigging_length_from_model_X
> %> characters)

Class attribute is one option, class constant is another..

class X < ActiveRecord::Base
  MIN_PASS = 3
  MAX_PASS = 40
  validates_length_of :login, :within => MIN_PASS..MAX_PASS
end

and in the view

<label for="login">Login (<%= "#{X::MIN_PASS}-#{X::MAX_PASS}" %>
characters)</label>

-r

http://www.agilewebdevelopment.com/plugins/validation_reflection

See also

http://schuerig.de/michael/blog/?p=8

HTH,
Michael

Thanks guys. It's really helpful to see different ways of resolving
this problem. For now I'm doing this (based on the
validation_reflection plugin from Michael's post):

    refls = X.reflect_on_validations_for("login")
    ref = refls.collect{ |ref| ref.macro == :validates_length_of ? ref
: nil }.compact.first
    ref.options[:within].to_s

Not sure if this is the best way (other suggestions?), but gets what I
need. I will try to take the next step to make this a method call for
any given ActiveRecord class, attribute, validation type and option.

thx,
Ray

And this is what I have now:
  def get_validation_option(clazz, method_name, validation, option)
    refls = clazz.reflect_on_validations_for(method_name)
    ref = refls.collect{ |ref| ref.macro == validation ? ref : nil
}.compact.first
    ref.options[option].to_s
  end

Tested in a controller (or view):
   logger.debug(get_validation_option(Person, "login",
:validates_length_of, :within))

Ray

Consider this alternative

  def get_validation_option(clazz, method_name, validation,
      option, default = nil)
    refl = clazz.reflect_on_validations_for(method_name).find { |r|
      r.macro == validation
    }
    if refl
      (refl.options[option] || default).to_s
    else
      default
    end
  end

Michael