On Jan 9, 1:22 pm, sharad <[email protected]> wrote:
>
> > Have you seen that validations take :if and :unless options ?
>
> I need to use coustom validation, for them I did not see any :if,
> :unless option

I think you can still do

validate :something, :if => :something+else?

>
> But as I got it working I have lot of question in all stages
> that I want to put else I will never able to know what is happening.
>

[snip
>     ruby>
>     ruby>   class Person
>     ruby>   cvalidation :zen do
>     ruby>       puts "Yes"
>     ruby>     end
>     ruby>   end
>            => #<Proc:0x95e73fc@(irb):8 (lambda)>
>     ruby> x = Person.newq
>           NoMethodError: undefined method `newq' for Person:Class

Not sure what this is showing - you haven't attempted to define newq
anywhere

>
> So this is not working now in test 2,  I now test only attr_accessor
>
> test 2:
>
>     ruby>   def k(name)
>     ruby>    attr_accessor name
>     ruby>   end
>             => nil
>     ruby>  class Personq
>     ruby>   k :test
>     ruby>   end
>            => nil
>     ruby>  x = Personq.new
>            => #<Personq:0x917a4e0>
>     ruby>  x.test
>            NoMethodError: private method `test' called for #<Personq:
> 0x917a4e0>
>
I ran this in irb and this worked fine.

> test 4:
>     ruby>   def cvalidation(name, &block)
>     ruby>       class_eval do
>     ruby>             attr_accessor name
>     ruby>           define_method "svalidator_#{name}" do |*arg|
>     ruby>                 if name
>     ruby>                   yield *arg
>     ruby>                 end
>     ruby>             end
>     ruby>         end
>     ruby>     end
>               => nil
>     ruby>
>     ruby> class Work
>     ruby>   cvalidation :done do
>     ruby>       puts "Yes"
>     ruby>     end
>     ruby>   end
>             => #<Proc:0xa337638@(irb):64 (lambda)>
>     ruby> x = Work.new
>            => #<Work:0xa32d200>
>     ruby> x.svalidator_done
>           Yes
>            => nil
>     ruby> x.done
>           => nil
>
> Here define_method is working but it is not using argument `name' in
> if condition, it uses some other name method, than provided argument
> `name'
>
> Q2: Why it is like that and what `name' method or variable it is
>     actually using in both lines ?

blocks are closures, so it sees the same local variables as those that
were existent when define_method were called, so it picks up the name
that was first argument to cvalidation. self is special though - self
will be the value of the object the method is called on.

>     ruby>           define_method "svalidator_#{name}" do |*arg|
>     ruby>                 if name
>
> test 5:
>     ruby>   def cvalidation(name, &block)
>     ruby>       class_eval do
>     ruby>             attr_accessor name
>     ruby>           define_method "svalidator_#{name}" do |*arg|
>     ruby>                 if send "#{name}"
>     ruby>                   yield *arg
>     ruby>                 end
>     ruby>             end
>     ruby>         end
>     ruby>     end
>               => nil
>     ruby>
>     ruby>   class QQ
>     ruby>     cvalidation :xx do
>     ruby>       puts "Yes"
>     ruby>     end
>     ruby>   end
>             => #<Proc:0xa0aaf28@(irb):105 (lambda)>
>     ruby> x = QQ.new
>           => #<QQ:0xa0a09ec>
>     ruby> x.svalidator_xx
>           => nil
>     ruby> x.xx
>           => nil
>     ruby> x.xx = "sfddsaf"
>           => "sfddsaf"
>     ruby> x.svalidator_xx
>           Yes
>           => nil
>     ruby> x.xx = nil
>           => nil
>     ruby> x.svalidator_xx
>           => nil
>     ruby> class NN
>     ruby>   cvalidation :ww do |w|
>     ruby>       puts w, " Hi"
>     ruby>     end
>     ruby>   end
>             => #<Proc:0x9fbe830@(irb):105 (lambda)>
>     ruby> x = NN.new
>           => #<NN:0x9fabb40>
>     ruby> x.ww
>           => nil
>     ruby> x.svalidator_ww
>           => nil
>     ruby> x.ww = "Sharad"
>           => "Sharad"
>     ruby> x.svalidator_ww
>
>           Hi
>           => nil
>     ruby> x.svalidator_ww "Sharad"
>           Sharad
>           Hi
>           => nil
>     ruby> puts "Sharad", "Hi"
>           Sharad
>           Hi
>           => nil
>     ruby>
>
> Here I guess as I see all is working, but
> I really like to know about `name' used in
>
>     ruby>                 if send "#{name}"
>
> in test 5, uses the `name' arguemnt provided.
>
> But
>     ruby>                 if name
> in test 4 it do not able to use same `name' argument
>

When you just write name, it picks up the local variable from the
closure (it's ambiguous whether you mean the local variable or the
method, and in these cases ruby picks the local variable), but by
using send you're forcing it to call the accessor method. You could
also have disambiguated by writing self.name or name()

Fred
> Why ?
>
> --
> Regards,
> -sharad
>
> On Jan 9, 3:37 am, Frederick Cheung <[email protected]>
> wrote:
>
>
>
> > On Jan 8, 10:18 pm, Sharad Pratap <[email protected]> wrote:
>
> > > Class Person < ActibeRecord::Base
> > >  valid_with_cond :test do
> > >      if self.addresses > 3
> > >         errors[:base] << "Can not have more than 3 addresses".
> > >    end
> > >  end
> > > end
>
> > > But when I check it on console
>
> > > Person.test
>
> > > it throw me error test is private method.
>
> > > Anybody could let me know how to correct it.
>
> > Your call to attr_accessor will create instance methods called test
> > and test=, but you tried to call test on the class (and so you end up
> > falling through to Kernel#test).
> > Have you seen that validations take :if and :unless options ?
>
> > Fred

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to