I want to strip out embedded separators from a harmonized tariff code before validating it. I thought (naively) that I could do this: class Product < ActiveRecord::Base validates_format_of :hs_class_code, :with => /\A(\d{6}|\d{8}|\d{10})?\Z/ protected def before_validation hs_class_code = hs_class_code.tr(".","").strip if !hs_class_code.nil? end but evidently hs_class_code is always nil. What is the proper syntax to use here? Thanks, -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Try this: class Product < ActiveRecord::Base validates_format_of :hs_class_code, :with => /\A(\d{6}|\d{8}|\d{10})?\Z/ before_validation :clean_tariff_code protected def clean_tariff_code self.hs_class_code.gsub!(".","") unless self.hs_class_code.nil? end It makes it more clear if you name the method. Also, it is a good idea to use self. to be sure that what are intended to be accessor method calls are not interpreted as local variables. Another problem was the use of tr which returns nil if no substitution is made. The was your initial method was written, if hs_class_code did not contain the "." character, the result would be to call strip on nil. Hope this helps -Bill James Byrne wrote:> I want to strip out embedded separators from a harmonized tariff code > before validating it. I thought (naively) that I could do this: > > class Product < ActiveRecord::Base > > validates_format_of :hs_class_code, :with => > /\A(\d{6}|\d{8}|\d{10})?\Z/ > > protected > > def before_validation > hs_class_code = hs_class_code.tr(".","").strip if > !hs_class_code.nil? > end > > but evidently hs_class_code is always nil. What is the proper syntax to > use here? > > Thanks, >--~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
William Pratt wrote:> Try this: > > class Product < ActiveRecord::Base > > validates_format_of :hs_class_code, :with => > /\A(\d{6}|\d{8}|\d{10})?\Z/ > > before_validation :clean_tariff_code > > protected > > def clean_tariff_code > self.hs_class_code.gsub!(".","") unless self.hs_class_code.nil? > end > > It makes it more clear if you name the method. Also, it is a good idea > to use self. to be sure that what are intended to be accessor method > calls are not interpreted as local variables. >Thanks, I am having a deal of difficulty in mentally switching between symbols and such in this context. This makes it very clear what I need to do in similar situation. Yet doubtless I will continue to have problems like this for a while yet.> Another problem was the use of tr which returns nil if no substitution > is made. The was your initial method was written, if hs_class_code did > not contain the "." character, the result would be to call strip on nil. >I believe that .tr returns the original string while it is .tr! that returns nil in this case. (paralleling .sub and .sub!) Thanks for you help. It is greatly appreciated. Jim -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
James Byrne wrote:> William Pratt wrote: >> Try this: >> >> class Product < ActiveRecord::Base >> >> validates_format_of :hs_class_code, :with => >> /\A(\d{6}|\d{8}|\d{10})?\Z/ >> >> before_validation :clean_tariff_code >> >> protected >> >> def clean_tariff_code >> self.hs_class_code.gsub!(".","") unless self.hs_class_code.nil? >> end >>How would one turn this into a generalized case? Given this: before_validation :delouse, :hs_class_code, :with => /\A<regex>\Z/ would this work? protected def delouse(attr,regx) self.(attr).gssub(regx,"") unless self.(attr).nil? end -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Well, I am not sure about :with on before_validation as I don''t see it in the docs or examples anywhere, but I''m not saying it won''t work, I just don''t know. What I can do is show you how I do it and others may chime in with alternatives / better solutions if some exist. First, what I think you are asking is how to generically call your clean method by passing in the attribute and the regex to use. Here are two ways, one more verbose than the other, but it''s more self documenting. before_validation :delouse_hs_class_code before_validation :delouse_another_one protected def delouse_another_one delouse(:another_one,/\"/) end def delouse_hs_class_code delouse(:hs_class_code,/\./) end def delouse(attr,regex) self.send(attr).gsub!(regex,"") unless self.send(attr).nil? end Or you could use Proc''s before_validation Proc.new{|o| o.delouse(:hs_class_code,/\./)} before_validation Proc.new{|o| o.delouse(:another_one,/\"/)} protected def delouse(attr,regex) self.send(attr).gsub!(regex,"") unless self.send(attr).nil? end This should get you going in the right direction. This is just a mock up that I didn''t test exactly and this was also written before my first cup of coffee :) HTH, -Bill James Byrne wrote:> James Byrne wrote: > >> William Pratt wrote: >> >>> Try this: >>> >>> class Product < ActiveRecord::Base >>> >>> validates_format_of :hs_class_code, :with => >>> /\A(\d{6}|\d{8}|\d{10})?\Z/ >>> >>> before_validation :clean_tariff_code >>> >>> protected >>> >>> def clean_tariff_code >>> self.hs_class_code.gsub!(".","") unless self.hs_class_code.nil? >>> end >>> >>> > > How would one turn this into a generalized case? Given this: > > before_validation :delouse, :hs_class_code, :with => > /\A<regex>\Z/ > > would this work? > > protected > > def delouse(attr,regx) > self.(attr).gssub(regx,"") unless self.(attr).nil? > end > >-- Sincerely, William Pratt --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
William Pratt wrote:> This should get you going in the right direction. This is just a mock up > that I didn''t test exactly and this was also written before my first cup > of coffee :) >I will try this approach out later when I get a minute to myself. However, I found this sample in the callback module documentation. class CreditCard < ActiveRecord::Base # Strip everything but digits, so the user can specify "555 234 34" or # "5552-3434" or both will mean "55523434" def before_validation_on_create self.number = number.gsub(/[^0-9]/, "") if attribute_present?("number") end end Which seems a more comprehensive regex to use for the purpose I intend (retain digits only). I suppose something like digits_only is a more descriptive method name than delouse as well. There does not seem to be any way to pass any additional parameters beyond the first to the before_validate call. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
As for the regex, I agree, always use what you want to allow rather than attempting to guess everything you need to take out. In the examples, I was just using what you had in the original method. As far as passing options, you will need to use one of the 2 methods I presented, both of which will allow multiple arguments. -Bill James Byrne wrote:> William Pratt wrote: > > >> This should get you going in the right direction. This is just a mock up >> that I didn''t test exactly and this was also written before my first cup >> of coffee :) >> >> > > I will try this approach out later when I get a minute to myself. > However, I found this sample in the callback module documentation. > > class CreditCard < ActiveRecord::Base > # Strip everything but digits, so the user can specify "555 234 34" > or > # "5552-3434" or both will mean "55523434" > def before_validation_on_create > self.number = number.gsub(/[^0-9]/, "") if > attribute_present?("number") > end > end > > Which seems a more comprehensive regex to use for the purpose I intend > (retain digits only). I suppose something like digits_only is a more > descriptive method name than delouse as well. There does not seem to be > any way to pass any additional parameters beyond the first to the > before_validate call. >-- Sincerely, William Pratt --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
This is what I ended up with. It seems to work. before_validation :digits_only_hs_class_code protected # Strip everything except digits from input string def digits_only(attr) attr.gsub(/[^0-9]/, "") unless attr.nil? end def digits_only_hs_class_code # only do this if not nil self.hs_class_code = digits_only(self.hs_class_code) if self.hs_class_code end -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---