El 16/10/2007, a las 6:50, Steve <[EMAIL PROTECTED]> escribió:

> Is anyone out there writing specs to check attr_accessible fields?  
> I had
> originally written my spec to check for allowing the desired  
> fields, and
> then none of the other regular db fields. Unfortunately this isn't
> satisfactory, because attr_protected could have been used instead,  
> which
> of course wouldn't prevent mass assignment to any whatever=(val)  
> method.
>
> I'm thinking of maybe some internal Rails variable that holds an  
> array of
> accessible fields maybe? Does anyone know if such a thing exists?  
> Just to
> make it clear, I don't want to test Rails, I want to check that the
> accessible fields have been set properly. Would it be possible to  
> mock or
> some such to check for a call to attr_accessible?

Yes, I spec this kind of thing.

   describe User, 'accessible attributes' do
     it 'should allow mass-assignment to the login name' do
       lambda { new_user.update_attributes(:login_name =>  
String.random) }.should_not raise_error
     end
     # many other examples here, one for each accessible attribute  
that I care about
   end

   describe User, 'protected attributes' do
     it 'should deny mass-assignment to the passphrase hash' do
       lambda { new_user.update_attributes(:passphrase_hash =>  
String.random) }.should raise_error
     end
     # many other examples here, one for each protected attribute  
that I care about
   end

I do it this way because:

1. I am most interested in the *behaviour*; does this let me mass- 
assign to this attribute (or not)?

2. I don't want my specs to depend on internal knowledge of the Rails  
attribute protection/access implementation.

The style of spec shown above seems the best way to me of both  
documenting the desired behaviour and confirming that it exists; I  
don't view these as tests of Rails' internals, but as tests that I've  
used attr_accessible and attr_protected correctly. I tried other ways  
in the past, but this is the one I like best.

Another thing to note that helps the readability of the specs: the  
new_user and String.random methods are provided by FixtureReplacement  
(<http://replacefixtures.rubyforge.org/>). Note that by default  
FixtureReplacement used mass-assignment under the covers, so it can't  
be used with protected attributes, but I've sent a patch in to the  
maintainer which changes that:

Index: lib/fixture_replacement/fixture_replacement.rb
===================================================================
--- lib/fixture_replacement/fixture_replacement.rb      (revision 31)
+++ lib/fixture_replacement/fixture_replacement.rb      (working copy)
@@ -70,7 +70,9 @@
            hash_given = args[0] || Hash.new
            merged_hash = self.send(attributes_method).merge(hash_given)
            evaluated_hash = Generator.merge_unevaluated_method 
(self, :create, merged_hash)
-          obj = class_name.create!(evaluated_hash)
+          obj = class_name.new
+          evaluated_hash.each { |k, v| obj.send("#{k}=", v) }
+          obj.save!
            obj
          end
        end
@@ -86,7 +88,9 @@
            hash_given = args[0] || Hash.new
            merged_hash = self.send(attributes_method).merge(hash_given)
            evaluated_hash = Generator.merge_unevaluated_method 
(self, :create, merged_hash)
-          class_name.new(evaluated_hash)
+          obj = class_name.new
+          evaluated_hash.each { |k, v| obj.send("#{k}=", v) }
+          obj
          end
        end
      end

Hopefully this will be included soon.

One more thing to note: the documentation for FixtureReplacement is  
pretty thin at this stage, so I threw together this cheatsheet:

<http://wincent.com/knowledge-base/FixtureReplacement_cheatsheet>

This is a bit easier than consulting the (excellent) screencast  
provided by the author:

<http://http://replacefixtures.rubyforge.org/>

Cheers,
Wincent



_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to