Hi all wonderfull core-developers. Rails is an amazing framework. I have a model (named Order) with an underlying DB field that is boolean. My migration file looks like this: t.boolean :balloon, :null => false, :default => true In my AR model I dutyfully have a line like this: validates_inclusion_of :balloon, :in => [true, false] In my test like the line below I expect an error, but I get none: order.balloon = ''some text'' assert !order.valid? I get no error because the value ''some text'' is converted (via type_cast) to false. Hence I get no error. In general I find it confusing that my validation takes place after the column_specific type cast. I would rather have a validation message when my boolean field is set to "some arbitraty text" instead of letting it be swallowed by some fall_back value in ActiveRecord::ConnectionAdapters::Column::value_to_boolean. In general I find it confusing and not clearly documented that validations occur after the type_cast mechanism (is that true for all types? also times/dates?) Jarl -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Michael Koziarski
2010-May-29 05:12 UTC
Re: confusing behaviour of validates_inclussion_of
> In general I find it confusing that my validation takes place after > the column_specific type cast. I would rather have a validation > message when my boolean field is set to "some arbitraty text" instead > of letting it be swallowed by some fall_back value in > ActiveRecord::ConnectionAdapters::Column::value_to_boolean. > > In general I find it confusing and not clearly documented that > validations occur after the type_cast mechanism (is that true for > all types? also times/dates?)Yeah, it happens for all types otherwise you couldn''t do something like this: validates_inclusion_of :price, :in=>0..500 Form submission values are all strings and "30" wouldn''t pass that validation if it were done before typecasting. Similarly your validation wouldn''t work with check_box_tag. -- Cheers Koz -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Jarl Friis
2010-May-31 09:08 UTC
Suggested validation for boolean does not work (WAS: confusing behaviour of validates_inclussion_of)
Hi Michael. Thanks for replying. Michael Koziarski <michael@koziarski.com> writes:>> In general I find it confusing that my validation takes place after >> the column_specific type cast. I would rather have a validation >> message when my boolean field is set to "some arbitraty text" instead >> of letting it be swallowed by some fall_back value in >> ActiveRecord::ConnectionAdapters::Column::value_to_boolean. >> >> In general I find it confusing and not clearly documented that >> validations occur after the type_cast mechanism (is that true for >> all types? also times/dates?) > > Yeah, it happens for all types otherwise you couldn''t do something like this: > > validates_inclusion_of :price, :in=>0..500I see. However it is unclear which validates_* macros that validates the raw value and which that validates the type_casted value.> Form submission values are all strings and "30" wouldn''t pass that > validation if it were done before typecasting. Similarly your > validation wouldn''t work with check_box_tag.Well, this is exactly my problem, the current implementation does not work with the suggested validation for booleans: The current suggested way to validate booleans is validates_inclusion_of :balloon, :in => [true, false] But that does NOT work, providing "something else" as parameter to :balloon passes the validation, becauase it is converted to false before the validates_inclusion_of So for all boolean fields I must write sometning like this: validates_each(:balloon) do |record,attr_name,value| raw_value = record.send("#{attr_name}_before_type_cast") unless ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.union(ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES).member? raw_value record.errors.add(attr_name, :inclusion, :default => "is not a boolean value", :value => raw_value) end end I am quite surprised that I am the only/first one having this problem, boolean values can''t be that rare. I didn''t do anything special, just introduced a boolean field, and added some tests like (using shoulda): should_allow_values_for :balloon, true, false should_not_allow_values_for :balloon, nil, '''', ''any ohter value'' And then the problem showed up. Jarl -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
matthewrudyjacobs@gmail.com
2010-Jun-01 03:46 UTC
Re: Suggested validation for boolean does not work (WAS: confusing behaviour of validates_inclussion_of)
Jarl, I''m wondering in what context you end up with user input that outputs a boolean? Is it from a web form, or XML, or JSON or console app? My feeling is that you''re only going to end up with a true/false if you are calling from a method inside your application, eg. something.make_order(params, :balloon => true) in which case "validation" may be the wrong use case. If you''re trying to guard against your own input then perhaps what you want to invent something like guard_field :balloon, :values => [true, false] where saying order.balloon = "purple" would instead raise an ArgumentError On May 31, 5:08 pm, Jarl Friis <j...@gavia.dk> wrote:> Hi Michael. > > Thanks for replying. > > Michael Koziarski <mich...@koziarski.com> writes: > >> In general I find it confusing that my validation takes place after > >> the column_specific type cast. I would rather have a validation > >> message when my boolean field is set to "some arbitraty text" instead > >> of letting it be swallowed by some fall_back value in > >> ActiveRecord::ConnectionAdapters::Column::value_to_boolean. > > >> In general I find it confusing and not clearly documented that > >> validations occur after the type_cast mechanism (is that true for > >> all types? also times/dates?) > > > Yeah, it happens for all types otherwise you couldn''t do something like this: > > > validates_inclusion_of :price, :in=>0..500 > > I see. However it is unclear which validates_* macros that validates the raw > value and which that validates the type_casted value. > > > Form submission values are all strings and "30" wouldn''t pass that > > validation if it were done before typecasting. Similarly your > > validation wouldn''t work with check_box_tag. > > Well, this is exactly my problem, the current implementation does not > work with the suggested validation for booleans: > > The current suggested way to validate booleans is > validates_inclusion_of :balloon, :in => [true, false] > > But that does NOT work, providing "something else" as parameter to > :balloon passes the validation, becauase it is converted to false > before the validates_inclusion_of > > So for all boolean fields I must write sometning like this: > validates_each(:balloon) do |record,attr_name,value| > raw_value = record.send("#{attr_name}_before_type_cast") > unless ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.union(ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES).member? raw_value > record.errors.add(attr_name, :inclusion, :default => "is not a boolean value", :value => raw_value) > end > end > > I am quite surprised that I am the only/first one having this problem, > boolean values can''t be that rare. I didn''t do anything special, just > introduced a boolean field, and added some tests like (using shoulda): > > should_allow_values_for :balloon, true, false > should_not_allow_values_for :balloon, nil, '''', ''any ohter value'' > > And then the problem showed up. > > Jarl-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
"matthewrudyjacobs@gmail.com" <matthewrudyjacobs@gmail.com> writes:> Jarl, > I''m wondering in what context you end up with user input that outputs > a boolean? > > Is it from a web form, > or XML, > or JSON > or console app?Integration with an external system making REST calls to our app.> My feeling is that you''re only going to end up with a true/false if > you are calling from a method inside your application, > eg. > > something.make_order(params, :balloon => true) > > in which case "validation" may be the wrong use case.Yes, but as in most other rails application, the input comes from a http POST or PUT method, hence the input is unreliable and validation is wanted.> If you''re trying to guard against your own input > then perhaps what you want to invent something like > > guard_field :balloon, :values => [true, false]I am trying to inform what-ever-have provided-the-input that the value is not acceptable. Here is an example A generic web-form, where all input fields are of type text (in the HTML form), but of course some fields (like :balloon) are typed, and therefore only certain values are accepted. The value "sand" (which means ''true'' in danish) is not an acceptable boolean value, hence I would like a validation message. Currently this would silently be converted to false, which semantically means the complete opposite of what the user expected. Jarl -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Jarl, I''ve been listening in on this conversation and it brings to mind a discussion a while back on the use of presenters and reverse presenters. Since the dawn of time, ActiveRecord (and perhaps even ActiveModel) has been tightly wedded to the concept of unreliable human input (= HTML forms). Gradually there has been some decoupling, but nothing comprehensive. The idea of a "Presenter/Reverse Presenter" is needed to insulate the persisted (and canonical) model from various presentation/view layer technologies -you can perhaps find some more background by googling those terms. Consider using something other than validations -matthewrudyjacobs "guard" macro seems like a reasonable step. You might still need to disable validations in various and sundry circumstances -bummer. -Chris On Jun 1, 5:15 am, Jarl Friis <j...@gavia.dk> wrote:> "matthewrudyjac...@gmail.com" <matthewrudyjac...@gmail.com> writes: > > Jarl, > > I''m wondering in what context you end up with user input that outputs > > a boolean? > > > Is it from a web form, > > or XML, > > or JSON > > or console app? > > Integration with an external system making REST calls to our app. > > > My feeling is that you''re only going to end up with a true/false if > > you are calling from a method inside your application, > > eg. > > > something.make_order(params, :balloon => true) > > > in which case "validation" may be the wrong use case. > > Yes, but as in most other rails application, the input comes from a > http POST or PUT method, hence the input is unreliable and validation > is wanted. > > > If you''re trying to guard against your own input > > then perhaps what you want to invent something like > > > guard_field :balloon, :values => [true, false] > > I am trying to inform what-ever-have provided-the-input that the value > is not acceptable. > > Here is an example A generic web-form, where all input fields are of > type text (in the HTML form), but of course some fields (like > :balloon) are typed, and therefore only certain values are > accepted. The value "sand" (which means ''true'' in danish) is not an > acceptable boolean value, hence I would like a validation > message. Currently this would silently be converted to false, which > semantically means the complete opposite of what the user expected. > > Jarl-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.