I'm trying to figure out how to clean up some form input for a
currency value. I'm using a decimal column to store the value and
have a basic text input box for the data entry.
My question: how can I sanitize this input data?
For instance, say the user enters "$115.25". Currently this is being
stored as "0.00" since ruby detects the dollar sign and strips
everything since it's not a numerical value. Similarly, "15,000.00"
is stored as "15.00" since the comma is detected as a non-numerical
value. It does this as soon as I call "update_attributes" in the
controller, so I don't think I can do much about in the model. By the
time before_validation fires it's already too late. I would assume
the same problem exists for ruby Integers, Floats, etc. So, what's
the "Rails Way" of handling this? Is there a way to clean the
parameters in the model before rails actually sets each attribute or
am I going to have to handle this in the controller?
> I'm trying to figure out how to clean up some form input for a > currency value. I'm using a decimal column to store the value and > have a basic text input box for the data entry.
> My question: how can I sanitize this input data?
> For instance, say the user enters "$115.25". Currently this is being > stored as "0.00" since ruby detects the dollar sign and strips > everything since it's not a numerical value. Similarly, "15,000.00" > is stored as "15.00" since the comma is detected as a non-numerical > value. It does this as soon as I call "update_attributes" in the > controller, so I don't think I can do much about in the model. By the > time before_validation fires it's already too late. I would assume > the same problem exists for ruby Integers, Floats, etc. So, what's > the "Rails Way" of handling this? Is there a way to clean the > parameters in the model before rails actually sets each attribute or > am I going to have to handle this in the controller?
--
Anthony Carlos Vice President Digital Phenom 807 National Press Bldg Washington DC 20045 202.393.0000
> I would use a regex to strip out anything that is not a digit or a
> decimal point:
> input.gsub(/[^0-9.]/, '').to_f
> I'm not sure of the "Rails Way," but it seems like a before filter
> might work well.
> -Anthony
> On Jan 15, 2008, at 12:18 AM, Bryce Thornton wrote:
> > I'm trying to figure out how to clean up some form input for a
> > currency value. I'm using a decimal column to store the value and
> > have a basic text input box for the data entry.
> > My question: how can I sanitize this input data?
> > For instance, say the user enters "$115.25". Currently this is being
> > stored as "0.00" since ruby detects the dollar sign and strips
> > everything since it's not a numerical value. Similarly, "15,000.00"
> > is stored as "15.00" since the comma is detected as a non-numerical
> > value. It does this as soon as I call "update_attributes" in the
> > controller, so I don't think I can do much about in the model. By the
> > time before_validation fires it's already too late. I would assume
> > the same problem exists for ruby Integers, Floats, etc. So, what's
> > the "Rails Way" of handling this? Is there a way to clean the
> > parameters in the model before rails actually sets each attribute or
> > am I going to have to handle this in the controller?
> --
> Anthony Carlos
> Vice President
> Digital Phenom
> 807 National Press Bldg
> Washington DC 20045
> 202.393.0000
> Thanks Anthony. I was aiming to keep the logic in the model. What
> I've done for now is just create a simple method in the model like
> this:
> def update_cleaned_attributes!(attributes)
> if attributes[:salary_amount]
> attributes[:salary_amount].gsub!(/[^0-9.]/, '')
> end
> self.update_attributes!(attributes)
> end
> I then just call this from my controller instead of
> "update_attributes". It works, but feel free to chime in if there's a
> way to do this better.
> Thanks,
> Bryce
> On Jan 15, 12:56 am, Anthony Carlos <anth...@digitalphenom.com> wrote:
> > Hey Bryce,
> > I would use a regex to strip out anything that is not a digit or a
> > decimal point:
> > input.gsub(/[^0-9.]/, '').to_f
> > I'm not sure of the "Rails Way," but it seems like a before filter
> > might work well.
> > -Anthony
> > On Jan 15, 2008, at 12:18 AM, Bryce Thornton wrote:
> > > I'm trying to figure out how to clean up some form input for a
> > > currency value. I'm using a decimal column to store the value and
> > > have a basic text input box for the data entry.
> > > My question: how can I sanitize this input data?
> > > For instance, say the user enters "$115.25". Currently this is being
> > > stored as "0.00" since ruby detects the dollar sign and strips
> > > everything since it's not a numerical value. Similarly, "15,000.00"
> > > is stored as "15.00" since the comma is detected as a non-numerical
> > > value. It does this as soon as I call "update_attributes" in the
> > > controller, so I don't think I can do much about in the model. By the
> > > time before_validation fires it's already too late. I would assume
> > > the same problem exists for ruby Integers, Floats, etc. So, what's
> > > the "Rails Way" of handling this? Is there a way to clean the
> > > parameters in the model before rails actually sets each attribute or
> > > am I going to have to handle this in the controller?
> > --
> > Anthony Carlos
> > Vice President
> > Digital Phenom
> > 807 National Press Bldg
> > Washington DC 20045
> > 202.393.0000
I guess I should not have said before _filter_. I meant a before callback. Perhaps the before_validation callback, which would then allow you to use your validation logic?
class Blah < AR::Base
before_validation :sanitize_money
def sanitize_money salary_amount.gsub!(/[^0-9.]/, '') end
Sorry about the confusion... It's late!
-Anthony
On Jan 15, 2008, at 1:27 AM, Bryce Thornton wrote:
> def attributes=(attributes, guard_protected_attributes = true) > if attributes[:salary_amount] > attributes[:salary_amount].gsub!(/[^0-9.]/, '') > end
> super(attributes, guard_protected_attributes) > end
> It works without changing the way I typically add/update records.
> On Jan 15, 1:12 am, Bryce Thornton <brycethorn...@gmail.com> wrote: >> Thanks Anthony. I was aiming to keep the logic in the model. What >> I've done for now is just create a simple method in the model like >> this:
>> def update_cleaned_attributes!(attributes) >> if attributes[:salary_amount] >> attributes[:salary_amount].gsub!(/[^0-9.]/, '') >> end
>> self.update_attributes!(attributes) >> end
>> I then just call this from my controller instead of >> "update_attributes". It works, but feel free to chime in if >> there's a >> way to do this better.
>> Thanks, >> Bryce
>> On Jan 15, 12:56 am, Anthony Carlos <anth...@digitalphenom.com> >> wrote:
>>> Hey Bryce,
>>> I would use a regex to strip out anything that is not a digit or a >>> decimal point:
>>> input.gsub(/[^0-9.]/, '').to_f
>>> I'm not sure of the "Rails Way," but it seems like a before filter >>> might work well.
>>> -Anthony
>>> On Jan 15, 2008, at 12:18 AM, Bryce Thornton wrote:
>>>> I'm trying to figure out how to clean up some form input for a >>>> currency value. I'm using a decimal column to store the value and >>>> have a basic text input box for the data entry.
>>>> My question: how can I sanitize this input data?
>>>> For instance, say the user enters "$115.25". Currently this is >>>> being >>>> stored as "0.00" since ruby detects the dollar sign and strips >>>> everything since it's not a numerical value. Similarly, >>>> "15,000.00" >>>> is stored as "15.00" since the comma is detected as a non-numerical >>>> value. It does this as soon as I call "update_attributes" in the >>>> controller, so I don't think I can do much about in the model. >>>> By the >>>> time before_validation fires it's already too late. I would assume >>>> the same problem exists for ruby Integers, Floats, etc. So, what's >>>> the "Rails Way" of handling this? Is there a way to clean the >>>> parameters in the model before rails actually sets each >>>> attribute or >>>> am I going to have to handle this in the controller?
>>> --
>>> Anthony Carlos >>> Vice President >>> Digital Phenom >>> 807 National Press Bldg >>> Washington DC 20045 >>> 202.393.0000
--
Anthony Carlos Vice President Digital Phenom 807 National Press Bldg Washington DC 20045 202.393.0000
I create 'getters' or 'setters' and then just use read_attribute, write_attribute when necessary.
Here is one example. I want to take any of the following string for gender: M, m, Male, Female, f, F .... etc..
So I take care of the logic before I store it. I also want to take the chance to store it in a consistent way (translating M to Male).
# # Custom writer to make sure we store the # gender information consistently. We # store: 'Male', 'Female', or 'Unknown' # def gender=(gender_string) case gender_string when /^[M|m](ale)*$/: write_attribute(:gender, 'Male') when /^[F|f](emale)*$/: write_attribute(:gender, 'Female') when /^[U|u](nknown)*$/: write_attribute(:gender, 'Unknown') # Let the validations catch anything else. else write_attribute(:gender, gender_string) end end
:gender is the field name in the database. This provides a hook if you will that gives you access to the element before it's stored. Validations will pick up _after_ this is run. Therefore, I allow validations to kick in for the 'else' clause. I've combined this with the following validator:
validates_inclusion_of :gender, :in => %w{ Male Female Unknown }
Hope this helps.
-Joe
On Jan 15, 2008, at 2:03 AM, Anthony Carlos wrote:
> I guess I should not have said before _filter_. I meant a before > callback. Perhaps the before_validation callback, which would then > allow you to use your validation logic?
> class Blah < AR::Base
> before_validation :sanitize_money
> def sanitize_money > salary_amount.gsub!(/[^0-9.]/, '') > end
> Sorry about the confusion... It's late!
> -Anthony
> On Jan 15, 2008, at 1:27 AM, Bryce Thornton wrote:
>> Update.. I think this is a better solution:
>> def attributes=(attributes, guard_protected_attributes = true) >> if attributes[:salary_amount] >> attributes[:salary_amount].gsub!(/[^0-9.]/, '') >> end
>> super(attributes, guard_protected_attributes) >> end
>> It works without changing the way I typically add/update records.
>> On Jan 15, 1:12 am, Bryce Thornton <brycethorn...@gmail.com> wrote: >>> Thanks Anthony. I was aiming to keep the logic in the model. What >>> I've done for now is just create a simple method in the model like >>> this:
>>> def update_cleaned_attributes!(attributes) >>> if attributes[:salary_amount] >>> attributes[:salary_amount].gsub!(/[^0-9.]/, '') >>> end
>>> self.update_attributes!(attributes) >>> end
>>> I then just call this from my controller instead of >>> "update_attributes". It works, but feel free to chime in if >>> there's a >>> way to do this better.
>>> Thanks, >>> Bryce
>>> On Jan 15, 12:56 am, Anthony Carlos <anth...@digitalphenom.com> >>> wrote:
>>>> Hey Bryce,
>>>> I would use a regex to strip out anything that is not a digit or a >>>> decimal point:
>>>> input.gsub(/[^0-9.]/, '').to_f
>>>> I'm not sure of the "Rails Way," but it seems like a before filter >>>> might work well.
>>>> -Anthony
>>>> On Jan 15, 2008, at 12:18 AM, Bryce Thornton wrote:
>>>>> I'm trying to figure out how to clean up some form input for a >>>>> currency value. I'm using a decimal column to store the value and >>>>> have a basic text input box for the data entry.
>>>>> My question: how can I sanitize this input data?
>>>>> For instance, say the user enters "$115.25". Currently this is >>>>> being >>>>> stored as "0.00" since ruby detects the dollar sign and strips >>>>> everything since it's not a numerical value. Similarly, >>>>> "15,000.00" >>>>> is stored as "15.00" since the comma is detected as a non- >>>>> numerical >>>>> value. It does this as soon as I call "update_attributes" in the >>>>> controller, so I don't think I can do much about in the model. >>>>> By the >>>>> time before_validation fires it's already too late. I would >>>>> assume >>>>> the same problem exists for ruby Integers, Floats, etc. So, >>>>> what's >>>>> the "Rails Way" of handling this? Is there a way to clean the >>>>> parameters in the model before rails actually sets each >>>>> attribute or >>>>> am I going to have to handle this in the controller?
>>>> --
>>>> Anthony Carlos >>>> Vice President >>>> Digital Phenom >>>> 807 National Press Bldg >>>> Washington DC 20045 >>>> 202.393.0000
> --
> Anthony Carlos > Vice President > Digital Phenom > 807 National Press Bldg > Washington DC 20045 > 202.393.0000
-Joe _______________ Joe O'Brien, artisan EdgeCase theedgecase.com
> I create 'getters' or 'setters' and then just use read_attribute, > write_attribute when necessary.
> Here is one example. I want to take any of the following string for > gender: M, m, Male, Female, f, F .... etc..
> So I take care of the logic before I store it. I also want to take > the chance to store it in a consistent way (translating M to Male).
> # > # Custom writer to make sure we store the > # gender information consistently. We > # store: 'Male', 'Female', or 'Unknown' > # > def gender=(gender_string) > case gender_string > when /^[M|m](ale)*$/: write_attribute(:gender, 'Male') > when /^[F|f](emale)*$/: write_attribute(:gender, 'Female') > when /^[U|u](nknown)*$/: write_attribute(:gender, 'Unknown') > # Let the validations catch anything else. > else write_attribute(:gender, gender_string) > end > end
> :gender is the field name in the database. This provides a hook if > you will that gives you access to the element before it's stored. > Validations will pick up _after_ this is run. Therefore, I allow > validations to kick in for the 'else' clause. I've combined this with > the following validator:
> validates_inclusion_of :gender, :in => %w{ Male Female Unknown }
> Hope this helps.
> -Joe
> On Jan 15, 2008, at 2:03 AM, Anthony Carlos wrote:
> > Bryce:
> > I guess I should not have said before _filter_. I meant a before > > callback. Perhaps the before_validation callback, which would then > > allow you to use your validation logic?
> > On Jan 15, 2008, at 1:27 AM, Bryce Thornton wrote:
> >> Update.. I think this is a better solution:
> >> def attributes=(attributes, guard_protected_attributes = true) > >> if attributes[:salary_amount] > >> attributes[:salary_amount].gsub!(/[^0-9.]/, '') > >> end
> >> super(attributes, guard_protected_attributes) > >> end
> >> It works without changing the way I typically add/update records.
> >> On Jan 15, 1:12 am, Bryce Thornton <brycethorn...@gmail.com> wrote: > >>> Thanks Anthony. I was aiming to keep the logic in the model. What > >>> I've done for now is just create a simple method in the model like > >>> this:
> >>> def update_cleaned_attributes!(attributes) > >>> if attributes[:salary_amount] > >>> attributes[:salary_amount].gsub!(/[^0-9.]/, '') > >>> end
> >>> self.update_attributes!(attributes) > >>> end
> >>> I then just call this from my controller instead of > >>> "update_attributes". It works, but feel free to chime in if > >>> there's a > >>> way to do this better.
> >>> Thanks, > >>> Bryce
> >>> On Jan 15, 12:56 am, Anthony Carlos <anth...@digitalphenom.com> > >>> wrote:
> >>>> Hey Bryce,
> >>>> I would use a regex to strip out anything that is not a digit or a > >>>> decimal point:
> >>>> input.gsub(/[^0-9.]/, '').to_f
> >>>> I'm not sure of the "Rails Way," but it seems like a before filter > >>>> might work well.
> >>>> -Anthony
> >>>> On Jan 15, 2008, at 12:18 AM, Bryce Thornton wrote:
> >>>>> I'm trying to figure out how to clean up some form input for a > >>>>> currency value. I'm using a decimal column to store the value and > >>>>> have a basic text input box for the data entry.
> >>>>> My question: how can I sanitize this input data?
> >>>>> For instance, say the user enters "$115.25". Currently this is > >>>>> being > >>>>> stored as "0.00" since ruby detects the dollar sign and strips > >>>>> everything since it's not a numerical value. Similarly, > >>>>> "15,000.00" > >>>>> is stored as "15.00" since the comma is detected as a non- > >>>>> numerical > >>>>> value. It does this as soon as I call "update_attributes" in the > >>>>> controller, so I don't think I can do much about in the model. > >>>>> By the > >>>>> time before_validation fires it's already too late. I would > >>>>> assume > >>>>> the same problem exists for ruby Integers, Floats, etc. So, > >>>>> what's > >>>>> the "Rails Way" of handling this? Is there a way to clean the > >>>>> parameters in the model before rails actually sets each > >>>>> attribute or > >>>>> am I going to have to handle this in the controller?
> >>>> --
> >>>> Anthony Carlos > >>>> Vice President > >>>> Digital Phenom > >>>> 807 National Press Bldg > >>>> Washington DC 20045 > >>>> 202.393.0000
> > --
> > Anthony Carlos > > Vice President > > Digital Phenom > > 807 National Press Bldg > > Washington DC 20045 > > 202.393.0000