Because it's intended to be used in scenarios where you're not
interested in dealing with validation errors. Such as automatic
functions that update a flag or increment a counter at billing. These
functions should not fail just because the object is invalid for
whatever reason.
If you want the same functionality with validation, you can use
update_attributes :attribute => value.
If this is confusion, please do add a documentation patch explaining
it fully.
Confusion probably arises because both methods have such similar
names. Perhaps update and update_without_validation, both taking a
hash of attributes, would make a clearer API? I appreciate that the
way rails is written, implementing this could be more complicated than
a simple rename method, but if it makes ActiveRecord easier to use it
could be worth it.
Tom
I think things should be swapped around, the API should be designed
for the common case which is that you want validation. If you don't
want validation, then do
object.attribute = value
object.save(false)
Of course, this is ultimately a matter of taste and of priorities, but
I think in this case data integrity and the principle of least
surprise should be prioritized.
I'm curious as to whether anyone currently depends on
update_attribute's lack of validation and, if so, how should we phase
it into a validating method? One possible way to do it is that if
validation fails, issue a warning stating that the implementation has
changed and that if you want to update without validation to use
attributes= and save(false). The problem with this, of course, is that
people who expect update_attribute to validate will be receiving
spurious warnings. Other suggestions?
-bd
I do understand that the naming can be confusing, but it's pretty
late in the game to be changing it. It's used as a way to skip
validations even inside Rails itself, and changing the behavior of
that method would have very far-reaching implications.
- Jamis
> --~--~---------~--~----~------------~-------~--~----~
> 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 rubyonra...@googlegroups.com
> To unsubscribe from this group, send email to rubyonrails-core-
> unsub...@googlegroups.com
> For more options, visit this group at http://groups.google.com/
> group/rubyonrails-core?hl=en
> -~----------~----~----~----~------~----~------~--~---
>
Jamis Buck:
> Lots of people are depending on the current behavior. [...]
> I do understand that the naming can be confusing, but it's pretty late
> in the game to be changing it.
Those new to the game continue to arrive, though. Suggestion: introduce
a method with the same behaviour as update_attribute and a better name.
Leave the old method unchanged, but deprecate it.
--Anthony.
I really don't think deprecating update_attribute is justified,
rewording the documentation to indicate you probably don't want to use
it would be much easier for all concerned.
--
Cheers
Koz
Cheers,
Jamie van Dyke
Fear of Fish
ja...@fearoffish.co.uk
+44 (0)7816 519649
Yeah, I understand that changing at this point can be problematic, but
maybe it's still worthwhile in the long run. To me, the clearest
syntax would be something like
object.update_attribute(:attribute, value, :validate => false)
Either way, I think I understand now the use case that this method
comes from now, and I've actually had it myself. In my case it was a
scheduled procedure that needed to update a single flag or date
column. What I ended up doing was hand writing my own method called
update_column which only updated that single column. The reason I
didn't use update_attribute was that it updates *all* columns which
lead to locking/concurrency issues. As far as I can tell, the ideal
implementation of this use case is a method that updates only the
column that you are interested in, but that *does* in fact trigger
validation but only validation for that particular column.
I have yet to come across a use case where I need to set a column to a
value that by itself is invalid (i.e. setting a date to something that
is not a date, setting a string that can only have an enumeration of
values to something else etc.). It's a different issue that the set of
values for all attributes should be allowed to be invalid which I
think is what DHH and Jamis are referring to.
I appreciate your passion for having a clear API, but you might not
want to use PoLS as a way of supporting your argument. Among other
people, Matz has distanced himself from this saying as it holds an
assumption of universality that is rarely, if ever, present.
The current behavior conforms with PoLS for me. It doesn't for you.
Thus, there is no single PoLS for the issue, making the argument moot.
Again, I do appreciate caring about the details. And it's great to see
enthusiasm for improving Rails on all fronts. But I think we can get
higher yields elsewhere after grabbing the low-hanging fruit of
updating the documentation.
I think there is general agreement that the naming of update_attribute
is unfortunate since it doesn't in any way suggest why it isn't
validating when the plural form of the method is. I haven't been
following the discussions on the PoLS, but I think it's pretty obvious
that it has always been a guiding principle in API design, even before
the term was coined, and always will be. I think both Ruby and Rails
make a great job following PoLS and that's one of the main reasons
they are such a joy to use. An API that surprises you again and again
will just be too frustrating and hard to use. It's common sense.
I'm not the only one who has been surprised. Dave Thomas didn't know
update_attribute is non-validating, which is why it's not in the book,
and his spontaneous reaction when I told him about it was that it's
probably a bug. I think that's what gave me the courage to bring up
the issue here.
I'm not on a one man crusade here to change the API. I accept the API
won't change at this point, and no API will ever be perfect to
everybody, and that's ok.
I sincerely appreciate all the time you have put into clearifying
things to me. This discussion has definitely given me some new
insights. Thanks guys!
If attr_protected is in use for the attribute in question,
`update_attributes :attr => val` won't function just as if we used the
singular update_attribute.
Obviously this is not a huge issue as we could just do something like
`model.attr = val \ model.save`, but that's a bit chunky.
It would be nice to have a way to use `update_attribute` WITH
validations. I wouldn't propose, nor agree with, changing the default
behavior of `update_attribute` at this stage. I'm just saying it would
be nice to have validations as an option for that method, or at least
another method that could update a single protected attribute with
validations.
Thanks for listening.
> It would be nice to have a way to use `update_attribute` WITH
> validations. I wouldn't propose, nor agree with, changing the default
> behavior of `update_attribute` at this stage. I'm just saying it would
> be nice to have validations as an option for that method, or at least
> another method that could update a single protected attribute with
> validations.
update_attribute_without_validation_skipping
The original update_attribute does perform validations. It is
overriden with alias_method_chain by validations.rb to skip 'em. The
original method is then preserved with the above name.
--
Chris Wanstrath
http://errtheblog.com
On Apr 6, 1:36 pm, "Chris Wanstrath" <c...@ozmm.org> wrote:
Just use update_attributes(name => value)
Kind regards,
Thijs
--
Fingertips - http://www.fngtps.com
He's updating an attribute that's either not allowed by
attr_accessible, or it's protected by attr_protected, so a mass
assignment won't work.
What about update_attribute name, value, true ?
--
Rick Olson
http://lighthouseapp.com
http://weblog.techno-weenie.net
http://mephistoblog.com
Regardless of whether or not validation should be called the current
behavior adversely impacts save situations that involve concurrency
and isn't of any added value for save situations that don't. Perhaps
I'm missing legitimate reasons for this behavior? I too am facing the
same situation as Peter. Wishing to update a flag that isn't user
editable in a table that contains other user editable data. I'm going
to write the same custom method as Peter has but again looking at the
name "update_attribute" and knowing what it does in practice feels a
little disingenuous :-)
Best regards,
-Michael
http://javathehutt.blogspot.com
You've given example use cases in which you need a record in the
database to be 'invalid', temporarily. Is it possible that your
validations not covering a particular (exceptional) case? For example,
suppose a field is required EXCEPT in a certain condition. One case
that comes to mind is when the record represents a document that a user
can save in an incomplete state, returning later to complete it. It
might be allowable for some fields to be nil when the document is
incomplete.
Using update_attribute to accommodate this seems, to me, to discourage a
full elaboration of validations. This is particularly troubling to me
for two reasons:
1) Rails takes a dim view of database constraints, so model probably
bears more responsibility for overall system integrity than it would in
other frameworks.
2) Rails (rightly) insists on MVC, yet methods like update_attribute
diminish one of the best things about the 'M' - the domain-driven
approach in which 'model' really means 'a model of the business/domain'.
I would prefer to see an option on Rails, perhaps
config.strict_validation, that could be used by those of us who want to
be able to rely on the model classes in this way.
So, if config.strict_validation == true, we could run the following on
startup:
# Adds update_attribute!, which incurs validation, and
# issue warnings for use of methods that either bypass or
# don't throw exceptions on validation failure.
module ActiveRecord
class Base
# Incurs validation.
def update_attribute!(name, value)
send(name.to_s + '=', value)
save!
end
def update_attribute_with_warning(name, value)
ActiveRecord::Base.validation_warning(:update_attribute)
update_attribute_without_warning(name, value)
end
alias_method_chain :update_attribute, :warning
private
# Produce a warning encourage update_attribute! use
# and listing the line from which it was called.
def self.validation_warning(method_name)
# Don't warn about calls from this file or active_record...
unless caller[1] =~ /activerecord/
msg=<<EOM
warning: The method '#{method_name}' bypasses validation. Consider
'#{method_name}!'.
#{method_name} was called from #{caller[1]}
EOM
warn msg
end
end
end
end
In my own project, I also warn on save, update_attributes and create.
Thanks,
Brian Hartin
brian.hartin@(The free email system by Google).com
--
Posted via http://www.ruby-forum.com/.