What about the current behaviour is causing you problems? Reducing
the number of columns updated is extremely dangerous without using
locking of some sort as there's no way for the models to enforce the
validations.
What about the current behaviour is causing you problems? Reducing
the number of columns updated is extremely dangerous without using
locking of some sort as there's no way for the models to enforce the
validations.
The problem is the following: If I want to have an Attachment (Upload)
entity with the acts_as_list (position) column - ActiveRecord makes a
full update (with the blob content) on each position change (with
move_higher). Now I had to use a has_one relation (and added another
entity for the content, etc.) and using native SQL for doing the
listing - because I do not have the attachment name in entity A and
the blob entity (DRY principle).
Another problem: If I have an Entity with a "published" flag and on
another page I have the "edit entity" functionality. If I click on
publish this entity (page A) ActiveRecord is making a full update -
instead of updating only the flag (or datetime column). Another user
can be on edit page to change content on page B. In this case - in the
ActiveRecord case the last update wins - and the changes before get
lost.
Reducing the number of columns updated is extremely dangerous without using
locking of some sort as there's no way for the models to enforce the
validations.
The model can be validated too - the complete record is available -
only the generated update can be smaller.
And a locking feature is OK - if I want to have it. Hibernate e.g.
provides locking too (see
Page Redirection,
Page Redirection).
The main problem is that ActiveRecord is very nice and easy to use -
in the first view. I love Rails and started the "easy" way to
implement my things. Then I saw some problems - described above. Using
SQL is annoying me because the code is not so portable and more
complicated. I had to add another entity to decouple the
"acts_as_list" entity from the blob entity. This makes my program more
complicated and I cannot use the simplest way. The other principles in
Rails are in this way "do it simple" - but some ActiveRecord things
can become a pitfall if you are using it in this way. I think it would
be nice to have an O/R Mapper (persistence layer) that is more
flexible - to keep in ActiveRecord more often - and avoid native SQL
(more often). Another problem in my point of view is that a full
update on all columns can be a performance issue too - on entities
with a lot of properties.
Another issue is the following: I thought the "update_attribute" do
only the update on the one attribute - but it makes a full update.
That was a little bit confusing to me.
Perhaps acts_as_list can be changed that only the position column will
be updated on position change - e.g. with move_higher.
Another problem: If I have an Entity with a "published" flag and on
another page I have the "edit entity" functionality. If I click on
publish this entity (page A) ActiveRecord is making a full update -
instead of updating only the flag (or datetime column). Another user
can be on edit page to change content on page B. In this case - in the
ActiveRecord case the last update wins - and the changes before get
lost.
What you've outlined here is precisely the risk for partial updates.
Your model validations will ensure that each of the individual models
are internally consistent, then proceed to write only their changes to
the database. The resulting record may, or may not, be valid, and
that's too risky.
The model can be validated too - the complete record is available -
only the generated update can be smaller.
No it doesn't as I've mentioned above.
And a locking feature is OK - if I want to have it.Hibernate e.g.
provides locking too (see
Page Redirection,
Page Redirection).
Rails supports both pessimistic and optimistic locking, just like
hibernate does.
Perhaps acts_as_list can be changed that only the position column will
be updated on position change - e.g. with move_higher.
If the only case where this makes a difference is entities with blobs,
then I don't think it justifies the significant risk implied by
partial updates.
I think it would be nice to have an option to choose if I want partial
updates or not. The default should be the full update. Then every
developer can choose. e.g. In the case of acts_as_list with no extra
relation to the blob I would choose the partial update option. In the
other cases I do not need to change the default. For performance
tuning the developers can test it with the option and without - to
decide if it is needed to have the model "full validated" - means the
validation of different fields in combination, because in the simple
case all fields are present and can be validated against "simple"
rules. If you have 2 or more fields which must be validated in
combination - you should choose the full update option (the default).
What do you think about this?
I think partial updates are so rarely desirable, and so rarely give a
significant speed increase, that it is better to force the developer
to use raw SQL in that situation.
I agree. Perhaps a plugin might be nice though, with syntax like:
class RecordWithBlob < ActiveRecord::Base
update_only_when_changed :blob_attribute
end
I don't have the need for such a plugin myself, but if someone did
want to put in the work, here's one way to do it:
* intercept write_attribute to record which attributes are being changed
* intercept attributes_with_quotes to remove the marked attribute if
it hasn't changed (and the record isn't new)
When I say intecept, I mean use alias_method_chain to wrap around the
original implementations.
I think partial updates are so rarely desirable, and so rarely give a
significant speed increase, that it is better to force the developer
to use raw SQL in that situation.
In case of acts_as_list and the move_higher method (e.g.) you have to
change your model design - I think an option like :dynamic_update =>
true would be fine for this case.
I love the Rails way of developing apps easily. If you use native SQL
your code gets more ugly. Why not add an :dynamic_update => true to
save, etc?
In case of acts_as_list and the move_higher method (e.g.) you have to
change your model design - I think an option like :dynamic_update =>
true would be fine for this case.
I love the Rails way of developing apps easily. If you use native SQL
your code gets more ugly. Why not add an :dynamic_update => true to
save, etc?
The best option here is for someone who's really passionate about this
problem, i.e. yourself, to release a plugin which implements that
functionality. Should it prove popular, we can investigate adding it
to rails itself.