Hello. In one of my ActiveRecord models I provide an after initialization callback after_initialize :foobar In that callback I check some attribute def foobar if my_attr.blank? ..... end Sometimes when I check the validation of an instance of that model my_model.valid? this foobar method (together with all my other after_initialize methods) are called (why that? ... the instance already exist.). The main problem is that this leads to "missing attribute" errors. It seems that the valid? method fetches and initializes objects from the database without loading all attributes ... is that true? How to avoid those missing attribute errors? Simply ignore them? Regards, Kai -- 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 5 December 2010 15:35, Kai Schlamp <kai.schlamp-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote:> Hello. > > In one of my ActiveRecord models I provide an after initialization > callback > after_initialize :foobar > > In that callback I check some attribute > def foobar > if my_attr.blank? ..... > end > > Sometimes when I check the validation of an instance of that model > my_model.valid? > this foobar method (together with all my other after_initialize > methods) are called (why that? ... the instance already exist.). The > main problem is that this leads to "missing attribute" errors. > It seems that the valid? method fetches and initializes objects from > the database without loading all attributes ... is that true? How to > avoid those missing attribute errors? Simply ignore them?That seems very strange. Are you absolutely sure that this what is happening? valid? cannot be fetching the object from the db as it must exist before you call valid? Or are you talking about fetching associated objects that are checked within valid? Do you have a repeatable situation where you see it? If so what happens for example if you use ruby-debug to break in just before the call of valid? and then inspect the object and call valid? from the console. Colin Colin -- 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Sorry for the late answer ... I had to simplyfy my model somehow to really test that is not an other interaction that causes that problem.> That seems very strange. Are you absolutely sure that this what is happening? > valid? cannot be fetching the object from the db as it must exist > before you call valid? Or are you talking about fetching associated > objects that are checked within valid? > Do you have a repeatable situation where you see it?Yes, I guess so. My Model: class MyModel < ActiveRecord::Base after_initialize :init_token validates :token, :uniqueness => true def init_token puts "init token" if self.token.blank? self.token = ActiveSupport::SecureRandom.hex(10) end end end And a simple case where it happens: m1 = MyModel.create m1.token.should_not be_empty m2 = MyModel.new m2.token.should_not be_empty m2.token = m1.token m2.valid? # where the exception is thrown (also "init token" is called) Full trace below.> If so what happens for example if you use ruby-debug to break in just > before the call of valid? and then inspect the object and call valid? > from the console.I never used the debugger yet, but I will try to. But maybe you already know of the above info what is going on here? Kai Error trace: ActiveModel::MissingAttributeError: missing attribute: token from /home/zeus/projects/myproject/app/models/my_model.rb:9:in `init_token'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activesupport-3.0.3/lib/active_support/callbacks.rb:415:in `_run_initialize_callbacks'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/base.rb:1453:in `init_with'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/base.rb:909:in `instantiate'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/base.rb:467:in `find_by_sql'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/base.rb:467:in `collect!'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/base.rb:467:in `find_by_sql'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/relation.rb:64:in `to_a'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/relation/finder_methods.rb:333:in `find_first'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/relation/finder_methods.rb:122:in `first'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/relation/finder_methods.rb:180:in `exists?'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/validations/uniqueness.rb:39:in `validate_each'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activemodel-3.0.3/lib/active_model/validator.rb:154:in `validate'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activemodel-3.0.3/lib/active_model/validator.rb:151:in `each'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activemodel-3.0.3/lib/active_model/validator.rb:151:in `validate'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activesupport-3.0.3/lib/active_support/callbacks.rb:314:in `send'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activesupport-3.0.3/lib/active_support/callbacks.rb:314:in `_callback_before_1265'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activesupport-3.0.3/lib/active_support/callbacks.rb:414:in `_run_validate_callbacks'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activemodel-3.0.3/lib/active_model/validations.rb:212:in `run_validations!'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activemodel-3.0.3/lib/active_model/validations/callbacks.rb:67:in `run_validations!'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activesupport-3.0.3/lib/active_support/callbacks.rb:413:in `_run_validation_callbacks'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activemodel-3.0.3/lib/active_model/validations/callbacks.rb:67:in `run_validations!'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activemodel-3.0.3/lib/active_model/validations.rb:179:in `valid?'' from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ activerecord-3.0.3/lib/active_record/validations.rb:55:in `valid?'' from (irb):103 -- 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 7 December 2010 19:24, Kai Schlamp <kai.schlamp-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote:> Sorry for the late answer ... I had to simplyfy my model somehow to > really test that is not an other interaction that causes that problem. > >> That seems very strange. Are you absolutely sure that this what is happening? >> valid? cannot be fetching the object from the db as it must exist >> before you call valid? Or are you talking about fetching associated >> objects that are checked within valid? >> Do you have a repeatable situation where you see it? > > Yes, I guess so. > > My Model: > > class MyModel < ActiveRecord::Base > > after_initialize :init_token > > validates :token, :uniqueness => true > > def init_token > puts "init token" > if self.token.blank? > self.token = ActiveSupport::SecureRandom.hex(10) > end > end > end > > And a simple case where it happens: > m1 = MyModel.create > m1.token.should_not be_empty > m2 = MyModel.new > m2.token.should_not be_empty > m2.token = m1.token > m2.valid? # where the exception is thrown (also "init token" is > called) > > Full trace below. > >> If so what happens for example if you use ruby-debug to break in just >> before the call of valid? and then inspect the object and call valid? >> from the console. > > I never used the debugger yet, but I will try to. But maybe you > already know of the above info what is going on here? > > Kai > > Error trace: > ActiveModel::MissingAttributeError: missing attribute: token > from /home/zeus/projects/myproject/app/models/my_model.rb:9:in > `init_token'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activesupport-3.0.3/lib/active_support/callbacks.rb:415:in > `_run_initialize_callbacks'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/base.rb:1453:in `init_with'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/base.rb:909:in `instantiate'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/base.rb:467:in `find_by_sql'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/base.rb:467:in `collect!'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/base.rb:467:in `find_by_sql'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/relation.rb:64:in `to_a'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/relation/finder_methods.rb:333:in > `find_first'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/relation/finder_methods.rb:122:in > `first'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/relation/finder_methods.rb:180:in > `exists?'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/validations/uniqueness.rb:39:in > `validate_each'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activemodel-3.0.3/lib/active_model/validator.rb:154:in `validate'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activemodel-3.0.3/lib/active_model/validator.rb:151:in `each'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activemodel-3.0.3/lib/active_model/validator.rb:151:in `validate'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activesupport-3.0.3/lib/active_support/callbacks.rb:314:in `send'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activesupport-3.0.3/lib/active_support/callbacks.rb:314:in > `_callback_before_1265'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activesupport-3.0.3/lib/active_support/callbacks.rb:414:in > `_run_validate_callbacks'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activemodel-3.0.3/lib/active_model/validations.rb:212:in > `run_validations!'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activemodel-3.0.3/lib/active_model/validations/callbacks.rb:67:in > `run_validations!'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activesupport-3.0.3/lib/active_support/callbacks.rb:413:in > `_run_validation_callbacks'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activemodel-3.0.3/lib/active_model/validations/callbacks.rb:67:in > `run_validations!'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activemodel-3.0.3/lib/active_model/validations.rb:179:in `valid?'' > from /home/zeus/.rvm/gems/ruby-1.8.7-p302@rails/gems/ > activerecord-3.0.3/lib/active_record/validations.rb:55:in `valid?'' > from (irb):103I am not fully confident, but here is a suggestion. The call of valid? must check for the uniqueness of token. To do that I think it may be doing a find with a condition of the token value of the object being validated, so that is the find_by_sql in the stack. Since the token is not unique this does actually find a record. Possibly then the found record is being instantiated, hence the call to init_token. But why it should fail I do not know. I presume the table has got a field called token? As I said I am not convinced. You may learn more by studying the log to see what the query being run is. Also try the debugger and you can find out what is being instantiated. Is it only in tests that you have the problem or is the test throwing up a real error in your app (such as the missing field in the table for example). Colin -- 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
> I am not fully confident, but here is a suggestion. The call of valid? > must check for the uniqueness of token. To do that I think it may be > doing a find with a condition of the token value of the object being > validated, so that is the find_by_sql in the stack. Since the token > is not unique this does actually find a record. Possibly then the > found record is being instantiated, hence the call to init_token.Yes, that is what I also guessed and the debugger seems to bring up. But in my opinion it is not good behavior to instantiate a record in that case. I wonder why that can''t be avoided by simply checking the data without creating the record (but I am no Rails pro).> But why it should fail I do not know.The last SQL statement is: SELECT `grids`.`id` FROM `grids` WHERE (`grids`.`token` = BINARY ''mkp8ae2qbq'') LIMIT 1 And thats the cause of the problem as token is not selected here. I am not sure if this is good behavior, that why opened a ticket to discuss it further: https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/6127-after_initialize-may-lead-to-missing-attribute-when-used-with-uniqueness-validation Kai -- 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 7 December 2010 22:19, Kai Schlamp <kai.schlamp-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote:> >> I am not fully confident, but here is a suggestion. The call of valid? >> must check for the uniqueness of token. To do that I think it may be >> doing a find with a condition of the token value of the object being >> validated, so that is the find_by_sql in the stack. Since the token >> is not unique this does actually find a record. Possibly then the >> found record is being instantiated, hence the call to init_token. > > Yes, that is what I also guessed and the debugger seems to bring up. > But in my opinion it is not good behavior to instantiate a record in > that case. > I wonder why that can''t be avoided by simply checking the data without > creating the record (but I am no Rails pro). > >> But why it should fail I do not know. > > The last SQL statement is: > SELECT `grids`.`id` FROM `grids` WHERE (`grids`.`token` = BINARY > ''mkp8ae2qbq'') LIMIT 1 > > And thats the cause of the problem as token is not selected here. > I am not sure if this is good behavior, that why opened a ticket to > discuss it further: > https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/6127-after_initialize-may-lead-to-missing-attribute-when-used-with-uniqueness-validationThere is nothing wrong with rails running that query to check for an existing token. It must do something similar. Note that it is only picking up grids.id (not sure why it is grids as that does not seem to bear any relationship to your model names but presumably you understand that). The question is whether it goes on to attempt to instantiate an object from that, which the query does not prove. You could go a bit further by debugging into the failing method and seeing what is there and how it got there. I don''t think you answered my question as to whether the failure is only in the tests and whether the app itself basically works. Colin -- 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
I''m experiencing this error and it is happening during normal site operation, not just in tests. Haven''t debugged it yet to see if it''s attempting to instantiate an object. Will try... -- 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
In fact, it appears that activerecord/lib/active_record/base.rb (rails 2.3.8) is calling after_initialize on line 1687 on a record that only has an id set. -- 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.