Hi Jeremy,
Yes, the Sequel is doing a good job for that edge case.

So in AR `super` makes method_missing to define the `ghost` attribute
method `name` in order to reduce the method lookup next time.
After it gets defined it also calls that method - at that time it
should only return "bob". After it gets called in method_missing,
shouldn't it just return back into our User#name scope?
Since the second time we call User#name we get the expected result, we
can assume that method_missing defined the `ghost` attribute
correctly.
Right?
But it is still not very clear to me why the 'Hi' gets capitalized. I
would expect 'bob' to be repeated twice if we have the case of doubled
method call. # Smth. like this: 'hi Bob bob'

BTW, I found this investigation interesting and I'd like to summarize
it into a small article (I've started it here: https://gist.github.com/930514).
Would you like to participate?

--
Thanks

On Apr 27, 9:09 am, Jeremy Evans <[email protected]> wrote:
> On Tue, Apr 26, 2011 at 4:44 PM, ivanpoval <[email protected]> wrote:
> > Hi, here is the example of the wrong usage of the `super` keyword
> > trying to override the attribute method.
>
> > class User < ActiveRecord::Base
> >  def name
> >    super.to_s.capitalize
> >  end
> > end
>
> > The result of this code looks 'pseudo'-correct and some people assume
> > it's fine to use that like if it were self[:name].to_s.capitalize
> > If we take a look at the code below - the results are different:
>
> > class User < ActiveRecord::Base
> >  def name
> >    'hi ' + super.to_s.capitalize
> >  end
> > end
>
> > u = User.first
> > p u.name # => 'hi Hi bob'
> > p u.name # => 'hi Bob'
> > p u.name # => 'hi Bob'
>
> > My question is why the first call to u.name produces that result.
> > I'm looking at
> > if self.class.generated_methods.include?(method_name)
> >  return self.send(method_id, *args, &block)
> > end
>
> > in
> > module ActiveRecord
> >  module AttributeMethods
> >    def method_missing
>
> > but need some help to figure the things out.
> > Simply want to know what is actually happening...
>
> The first time you call name, your super call actually calls
> method_missing, since the name method doesn't exist higher in the
> method chain.  method_missing doesn't think the attribute methods have
> been defined yet, so it calls a method to define them in an anonymous
> module included in the class, then calls the method again.  Basically,
> the first time you call it:
>
> User#name -> ActiveRecord::AttributeMethods#method_missing ->
> User#name -> generated_methods_module#name
>
> Future calls don't hit method_missing because
> generated_methods_module#name already exists:
>
> User#name -> generated_methods_module#name
>
> Your example works fine in Sequel, BTW, because Sequel sets up the
> attribute methods in an anonymous module included in the class at
> class definition time, instead of when the attribute method is first
> called.  I wouldn't be surprised if the ActiveRecord way of defining
> attribute methods is subject to a race condition in threaded code, in
> addition to the problem you are experiencing.
>
> Jeremy

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" 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-core?hl=en.

Reply via email to