Iain E. Davis
2010-Nov-02 00:36 UTC
[rspec-users] Testing attr_accessible (and/or attr_protected)
I''ve been puzzling over how to test that attr_accessible has been set for the correct columns; but the tests I''ve come up with so far seem to fail to fail when I expect. I came across this old message from this list: http://www.mail-archive.com/rspec-users at rubyforge.org/msg01570.html Which seemed like a plausible example, but my attempt (modeled on the example) doesn''t work: describe Article, ''protected attributes'' do it ''should deny mass-assignment to the user_id'' do lambda { article.update_attributes(:person_id => @person.id) }.should raise_error end end The lambda doesn''t raise an error, even though the attr_accessible doesn''t include person_id. Where am I stumbling here? Is it my beginner''s knowledge of rails, or beginner''s knowledge of Ruby? Thanks, Iain
Alexey Ilyichev
2010-Nov-02 06:33 UTC
[rspec-users] Testing attr_accessible (and/or attr_protected)
An attempt to assign protected attributes leads to the warning in your log and not doing actual assignment. You can test it like this: describe Article, ''protected attributes'' do it ''should deny mass-assignment to the user_id'' do RAILS_DEFAULT_LOGGER.should_receive(:warn) # I ain''t sure if it is actually a warning, and I would just skip this check article.update_attributes(:person_id => @person.id) article.person_id.should == nil # or whatever it is before update call end end On Tue, Nov 2, 2010 at 3:36 AM, Iain E. Davis <iain at somethingelectronic.com>wrote:> I''ve been puzzling over how to test that attr_accessible has been set > for the correct columns; but the tests I''ve come up with so far seem > to fail to fail when I expect. I came across this old message from > this list: > > http://www.mail-archive.com/rspec-users at rubyforge.org/msg01570.html > > Which seemed like a plausible example, but my attempt (modeled on the > example) doesn''t work: > > describe Article, ''protected attributes'' do > it ''should deny mass-assignment to the user_id'' do > lambda { article.update_attributes(:person_id => @person.id) > }.should raise_error > end > end > > The lambda doesn''t raise an error, even though the attr_accessible > doesn''t include person_id. > > Where am I stumbling here? Is it my beginner''s knowledge of rails, or > beginner''s knowledge of Ruby? > > Thanks, > > Iain > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20101102/0e32cd8d/attachment.html>
Evgeniy Dolzhenko
2010-Nov-02 07:13 UTC
[rspec-users] Testing attr_accessible (and/or attr_protected)
update_attributes [1] doesn''t raise any exception when you try to assign the attribute which is protected with `attr_accessible/attr_protected` machinery (only warning in log is printed). So your options are: 1. perform update_attributes for an attribute and then assert that the attribute didn''t change 2. go a bit "meta" and implement something like Shoulda allow_mass_assignment_of matcher [2] [1] http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-i-attributes%3D [2] http://github.com/thoughtbot/shoulda/blob/master/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb On Tue, Nov 2, 2010 at 3:36 AM, Iain E. Davis <iain at somethingelectronic.com> wrote:> I''ve been puzzling over how to test that attr_accessible has been set > for the correct columns; but the tests I''ve come up with so far seem > to fail to fail when I expect. I came across this old message from > this list: > > http://www.mail-archive.com/rspec-users at rubyforge.org/msg01570.html > > Which seemed like a plausible example, but my attempt (modeled on the > example) doesn''t work: > > describe Article, ''protected attributes'' do > ? ? it ''should deny mass-assignment to the user_id'' do > ? ? ? lambda { article.update_attributes(:person_id => ?@person.id) > }.should raise_error > ? ? end > end > > The lambda doesn''t raise an error, even though the attr_accessible > doesn''t include person_id. > > Where am I stumbling here? Is it my beginner''s knowledge of rails, or > beginner''s knowledge of Ruby? > > Thanks, > > Iain > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Wincent Colaiuta
2010-Nov-02 07:20 UTC
[rspec-users] Testing attr_accessible (and/or attr_protected)
On 02/11/2010, at 01:36, Iain E. Davis wrote:> I''ve been puzzling over how to test that attr_accessible has been set > for the correct columns; but the tests I''ve come up with so far seem > to fail to fail when I expect. I came across this old message from > this list: > > http://www.mail-archive.com/rspec-users at rubyforge.org/msg01570.html > > Which seemed like a plausible example, but my attempt (modeled on the > example) doesn''t work: > > describe Article, ''protected attributes'' do > it ''should deny mass-assignment to the user_id'' do > lambda { article.update_attributes(:person_id => @person.id) > }.should raise_error > end > end > > The lambda doesn''t raise an error, even though the attr_accessible > doesn''t include person_id. > > Where am I stumbling here? Is it my beginner''s knowledge of rails, or > beginner''s knowledge of Ruby?I''m the author of that message you linked to from three years ago. Things have changed quite a bit since then. Right now, I check for this stuff using a custom matcher: http://gist.github.com/659344 Which can be used like this: article.should_not allow_mass_assignment_of(:person_id => @person.id) Or: article.should allow_mass_assignment_of(:person_id => @person.id) I''m not the only one to have written custom matchers like this though; if you Google (for "rspec custom matcher rails" or "rspec macro rails") you''ll probably find a bunch for doing this, and for other stuff (like testing validations, associations etc). Cheers, Wincent
Iain E. Davis
2010-Nov-02 14:39 UTC
[rspec-users] Testing attr_accessible (and/or attr_protected)
I failed to mention I''m using Rails 2.3.8 and Rspec-1.3.x. I should have said that right away. On Tue, Nov 2, 2010 at 01:33, Alexey Ilyichev <bluesman.alex at gmail.com> wrote:> An attempt to assign protected attributes leads to the warning in your logHmm... Maybe I should actually look at the log once in a while...> ??? article.update_attributes(:person_id => ?@person.id) > ??? article.person_id.should == nil # or whatever it is before update callOn Tue, Nov 2, 2010 at 02:13, Evgeniy Dolzhenko <dolzenko at gmail.com> wrote:> 1. perform update_attributes for an attribute and then assert that the attribute didn''t changeBuh. I wish I had thought of that. Seems rather obvious now...I confess I was expecting something esoteric and thus didn''t stop to think if there was a simple solution. :) To me, checking whether the attribute changed is more straight-forward than implementing a custom matcher, at least at my current level of experience (novice) with rails and rspec. I suppose I need to be careful that the attribute change was rejected for some other reason (bad data, for example). But that''s true of any example/test. On Tue, Nov 2, 2010 at 02:20, Wincent Colaiuta <win at wincent.com> wrote:> I''m the author of that message you linked to from three years ago. Things have changed quite > a bit since then.I suspected so! I guess I should have clued in when I didn''t find anything about raising an error in the docs for update_attribute. Oh! In the same vein, when looking at the docs/source for update_attribute, I formed the expectation that update_attribute(s) would return false if it failed. My new guess is that it returns false if it fails to save the model...irregardless of whether the attribute changes? Thank you Alexey, Evgeniy, and Wincent! Iain
Rick DeNatale
2010-Nov-02 15:31 UTC
[rspec-users] Testing attr_accessible (and/or attr_protected)
On Tue, Nov 2, 2010 at 10:39 AM, Iain E. Davis <iain at somethingelectronic.com> wrote:> I failed to mention I''m using Rails 2.3.8 and Rspec-1.3.x. I should > have said that right away. > > On Tue, Nov 2, 2010 at 01:33, Alexey Ilyichev <bluesman.alex at gmail.com> wrote: >> An attempt to assign protected attributes leads to the warning in your log > Hmm... Maybe I should actually look at the log once in a while... > >> ??? article.update_attributes(:person_id => ?@person.id) >> ??? article.person_id.should == nil # or whatever it is before update call > > On Tue, Nov 2, 2010 at 02:13, Evgeniy Dolzhenko <dolzenko at gmail.com> wrote: >> 1. perform update_attributes for an attribute and then assert that the attribute didn''t change > > Buh. I wish I had thought of that. Seems rather obvious now...I > confess I was expecting something esoteric and thus didn''t stop to > think if there was a simple solution. :) > > To me, checking whether the attribute changed is more straight-forward > than implementing a custom matcher, at least at my current level of > experience (novice) with rails and rspec. > > I suppose I need to be careful that the attribute change was rejected > for some other reason (bad data, for example). But that''s true of any > example/test.Note that Evgeniy''s two suggestions: 1. perform update_attributes for an attribute and then assert that the attribute didn''t change 2. go a bit "meta" and implement something like Shoulda allow_mass_assignment_of matcher Represent two different philosophies. The first, feels to me more like you are specifying/testing the behavior of ActiveRecord rather than your own code. It indirectly tests whether or not attr_accessible/attr_protected is in effect by observing the effect on one of the methods which are effected by those ''declarative'' methods. In general I prefer to concentrate on specifying/testing the code I write. The second approach is more compatible with that philosophy. I trust that ActiveRecord correctly implements protected attributes, what I want to prove is that my code is using them. This is independent of whether or not a custom matcher is used. For example Wincent''s implementation of the matcher takes the first approach, while the shoulda macro instead examines whether or not the model has an attribute set as accessible directly. Now the shoulda approach is dependent a bit on the implementation in activerecord, which is a reason to look for such plugins before trying to write them yourself, an open-source plugin has more eyes on it and will probably adapt to any changes before you run into them yourself. And as Wincent points out, you don''t usually need to do such plumbing yourself, there are lots of RSpec compatible matchers (including the Shoulda matchers) freely available. -- Rick DeNatale Help fund my talk at Ruby Conf 2010:http://pledgie.com/campaigns/13677 Blog: http://talklikeaduck.denhaven2.com/ Github: http://github.com/rubyredrick Twitter: @RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale
Evgeniy Dolzhenko
2010-Nov-02 15:49 UTC
[rspec-users] Testing attr_accessible (and/or attr_protected)
> I suppose I need to be careful that the attribute change was rejected > for some other reason (bad data, for example). But that''s true of any > example/test.Good catch, that''s why I think the Shoulda approach makes sense (since otherwise you''re duplicating the Rails test suite which is supposed to specify/exercise that functionality already)
Iain E. Davis
2010-Nov-02 16:55 UTC
[rspec-users] Testing attr_accessible (and/or attr_protected)
> To me, checking whether the attribute changed is more straight-forward > than implementing a custom matcher, at least at my current level of > experience (novice) with rails and rspec.Okay, so that didn''t last very long. Suddenly, I was swimming in very repetitive code in my _spec files...I could feel my eyes closing from the ennui... In light of that experience and the excellent points that Rick made, I think I''ll go hunt down a custom matcher that checks that I actually set the planned attr_accessible, rather than doing it the way I just did it! I''ll start by looking at the link to Shoulda''s matcher, kindly provided by Evgeniy earlier. It works the other way, but the repetition was driving me crazy, and as Rick says:> It indirectly tests whether or not attr_accessible/attr_protected is in effect by observing the effect on > one of the methods which are effected by those ''declarative'' methods.I agree...I was at some level sort of aware of that but didn''t know enough (yet) to overcome it. :)>?The second approach is more compatible with that philosophy. I trust that ActiveRecord correctly > implements protected attributes, what I want to prove is that my code is using them.Exactly. The way I''ve begun to think is "...if I add a line[1] of code to do X, will my test flag a failure if that line is not there?". That way I''m writing tests that insure that the code _I''ve_ (or my team has) written is correct, and not testing Rails/Authlogic/Rspec/etc. themselves. :) Thanks again! Iain [1] "Line" is a bit misleading, since I could leave off a _portion_ of a line in the case of attr_accessible and similar pieces.