Hi, I am trying to use the WhitespaceKiller as referenced here: http://wiki.rubyonrails.com/rails/show/HowToStripWhitespaceFromModelFields However, it does not work for attr_accessors such as: attr_accessor :password Here is an inspect snippet of my User object: <User:0x3865798 @password_confirmation="", @password="", @attributes={"name"=>"Tom Davies", "address1"=>"123 No Way", ...}> The WhitespaceKiller only loops through the attributes (which the attr_accessors are not part of) using this code: def before_validation(record) record.attributes.each do | attr, val| if !val.nil? && val.respond_to?(:strip) s = val.strip s.size == 0? record[attr] = nil : record[attr] = s end end end Is there a concise way to modify that method to include the attr_accessors? Thanks, Tom
Tom Davies wrote:> The WhitespaceKiller only loops through the attributes (which the > attr_accessors are not part of) using this code: > > Is there a concise way to modify that method to include the attr_accessors?Something like: def before_validation(record) for var in record.instance_variables.collect {|v| v[1..-1]} - [''attributes'',''new_record''] + record.attribute_names setter_meth = var + ''='' if record.respond_to?(var) && record.respond_to?(setter_meth) val = record.send(var) if !val.nil? && val.respond_to?(:strip) s = val.strip record.send(setter_meth, s.size == 0 ? nil : s) end end end end -- We develop, watch us RoR, in numbers too big to ignore.
Thanks! That seems to do the trick. I just have one question. If I try to test it by replacing the record with an instance of my model User class, it does not pick up the attr_accessors. For example: <% @user = User.new for var in @user.instance_variables.collect {|v| v[1..-1]} - [''attributes'',''new_record''] + @user.attribute_names %> <%= var %> <% end %> Is the record passed to the Observer methods something other than a direct instance of the model class? Thanks again, Tom On 9/14/05, Mark Reginald James <mrj-bzGI/hKkdgQnC9Muvcwxkw@public.gmane.org> wrote:> Tom Davies wrote: > > > The WhitespaceKiller only loops through the attributes (which the > > attr_accessors are not part of) using this code: > > > > Is there a concise way to modify that method to include the attr_accessors? > > Something like: > > def before_validation(record) > for var in record.instance_variables.collect {|v| v[1..-1]} - [''attributes'',''new_record''] + record.attribute_names > setter_meth = var + ''='' > if record.respond_to?(var) && record.respond_to?(setter_meth) > val = record.send(var) > if !val.nil? && val.respond_to?(:strip) > s = val.strip > record.send(setter_meth, s.size == 0 ? nil : s) > end > end > end > end > > -- > We develop, watch us RoR, in numbers too big to ignore. > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Tom Davies wrote:> Thanks! That seems to do the trick. I just have one question. > > If I try to test it by replacing the record with an instance of my > model User class, it does not pick up the attr_accessors. For > example: > > <% @user = User.new > for var in @user.instance_variables.collect {|v| v[1..-1]} - > [''attributes'',''new_record''] + @user.attribute_names %> > <%= var %> > <% end %> > > Is the record passed to the Observer methods something other than a > direct instance of the model class?It''ll only pick up attr_accessors that have been set to some value in the instance. Also, if you want to get a separate list of the accessors, and also to increase efficiency, you could move the respond_to?s out of the loop. e.g. inst_vars = record.instance_variables.collect {|v| v[1..-1]} - [''attributes'',''new_record''] accessors = ivars.delete_if { |iv| !(record.respond_to?(iv) && record.respond_to?(iv+''='')) } for var in accessors + record.attribute_names val = record.send(var) if !val.nil? && val.respond_to?(:strip) s = val.strip record.send(var+''='', s.size == 0 ? nil : s) end end -- We develop, watch us RoR, in numbers too big to ignore.
Thanks Mark. I added your first reply to the WhitespaceKiller wiki page. I am not too concerned with efficiency here... as the number of accessors and attributes is very small for all of my models... but I appreciate your help. Tom On 9/15/05, Mark Reginald James <mrj-bzGI/hKkdgQnC9Muvcwxkw@public.gmane.org> wrote:> Tom Davies wrote: > > Thanks! That seems to do the trick. I just have one question. > > > > If I try to test it by replacing the record with an instance of my > > model User class, it does not pick up the attr_accessors. For > > example: > > > > <% @user = User.new > > for var in @user.instance_variables.collect {|v| v[1..-1]} - > > [''attributes'',''new_record''] + @user.attribute_names %> > > <%= var %> > > <% end %> > > > > Is the record passed to the Observer methods something other than a > > direct instance of the model class? > > It''ll only pick up attr_accessors that have been set to some value > in the instance. > > Also, if you want to get a separate list of the accessors, and also to > increase efficiency, you could move the respond_to?s out of the loop. > > e.g. > > inst_vars = record.instance_variables.collect {|v| v[1..-1]} - [''attributes'',''new_record''] > accessors = ivars.delete_if { |iv| !(record.respond_to?(iv) && record.respond_to?(iv+''='')) } > for var in accessors + record.attribute_names > val = record.send(var) > if !val.nil? && val.respond_to?(:strip) > s = val.strip > record.send(var+''='', s.size == 0 ? nil : s) > end > end > > > > -- > We develop, watch us RoR, in numbers too big to ignore. > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >