I have seen that Active Record is making a full update (with all
columns) if I change the position of an item in a has_many,
acts_as_list configuration. e.g.:
UPDATE pages SET "name" = 'asdasdasd', "content" = NULL, "position" =
1, "article_id" = 1 WHERE id = 10
I know Hibernate O/R mapper. There is an option called "dynamic-
update". The O/R mapper keeps track of changed properties in the
entity objects and generates the following update statement:
UPDATE pages SET "position" = 1 WHERE id = 10
The mapper does not change the complete row. Only the columns changed.
Is something like this possible in Rails? Is something like this
planned for Active Record?
update(id, attributes)
update_all(updates, conditions
Another problem I had was with update_attribute. I thought
ActiveRecord will generate a simple UPDATE SQL statement for this
column only. I have seen in the log that update_attribute generates an
UPDATE statement with all columns.
What do you think?
Do you have use case where UPDATE requires DELETE of dependent
records ?
>
> Another problem I had was with update_attribute. I thought
> ActiveRecord will generate a simple UPDATE SQL statement for this
> column only. I have seen in the log that update_attribute generates an
> UPDATE statement with all columns.
>
You can make a plugin with smth like :
module ActiveRecord
class Base
# page = Page.find(10)
# page.update_only( 'position' => 5)
# will result in SQL:
# UPDATE pages SET position = 5 WHERE id = 10
# notes:
# 1.created/updated_on/at fields aren't handled
# 2.returns true if update succeed, false otherwise
def update_only( new_attrs )
return true if new_attrs.empty?
pkey = quote_value(id) # to allow changing primary key
altogether :)
new_attrs.each { |column, value| write_attribute(column,
value) }
if valid?
update_list = new_attrs.keys.map do |name|
self.class.connection.quote_column_name(name) + "=" +
quote_value(read_attribute(name),column_for_attribute(name) )
end.join(' , ')
connection.update(
"UPDATE #{self.class.table_name} SET #{update_list} WHERE
#{self.class.primary_key} = #{pkey}",
"#{self.class.name} Update" )
true
else
false
end
end
end
end
> You can make a plugin with smth like :
> module ActiveRecord
> class Base
> [...]
Ok. Something like that can fix the update_attribute issue. But if I
use acts_as_list with move_higher I have to change the move_higher
functionality (override?)...
Thank you for your post - very interesting :)
This is the problem I currently have with ActiveRecord - you want to
implement your program the "easy" Rails way - and then you get some
pitfalls - and your code getting more and ugly. I think it would be
nice to get ActiveRecord more flexible/powerful for such cases.
I have another post for this topic in "Ruby on Rails: Core" list:
http://groups.google.com/group/rubyonrails-core/browse_thread/thread/dc2d301dd9c8e5c9
see attached diff for possible changes
> This is the problem I currently have with ActiveRecord - you want to
> implement your program the "easy" Rails way - and then you get some
> pitfalls - and your code getting more and ugly. I think it would be
> nice to get ActiveRecord more flexible/powerful for such cases.
>
Rails is flexible, providing basic functionality that is good enough
for majority of cases, and easy way to extend it to your needs,
http://agilewebdevelopment.com/plugins/category/2
> Rails is flexible, providing basic functionality that is good enough
> for majority of cases, and easy way to extend it to your needs,http://agilewebdevelopment.com/plugins/category/2
I think my case is such a major case and ActiveRecord can be more
flexible. I know that I can extend it with a plugin, etc. but I think
it makes no sense to update all columns all the time. What do you
think about this default behaviour?
Update all columns all the time is not a problem, unless there are
blobs which aren't touched, so occasionally people ask why update
statement doesn't include only changed attributes, and have to resort
to update_all.
Besides, model can have callbacks (timestamps, locking, versioning
etc) on update, so this aspect also should be considered.
>Besides, model can have callbacks (timestamps, locking, versioning
>etc) on update, so this aspect also should be considered.
Ok. I see...
At present time there is no solution to track model changes in Rails,
probably, due to low demand for most users, see:
http://dev.rubyonrails.org/ticket/1423
http://dev.rubyonrails.org/ticket/3238
http://dev.rubyonrails.org/ticket/5961
update_attribute
update_attributes
update_attributes!
Also, I was able to find ticket, #5961, that had patch in regards to this issue:
http://dev.rubyonrails.org/ticket/5961
Thus, I would recommend opening/creating a ticket so that this issue
gets resolved in future releases:
Good luck,
-Conrad
~h
On Mar 2, 3:38 pm, "Oliver Paulus" <oli...@code-project.org> wrote:
> > Update all columns all the time is not a problem, [...]
>
> Ok, but why should the persistence layer update more columns than
> necessary? I think there is a reason for this functionality in the
> "enterprise" (no I don´t want to start a flamewar "enterprise"
> discussion) O/R MapperHibernate. If the persistence layer keeps track
I've had the same thoughts myself. Which is why I started the
DataMapper project (source available in the repo on RubyForge, gem
release sometime next week: http://rubyforge.org/projects/datamapper).
To put it simply, I'm striving for a better ActiveRecord. To keep
compatibility with ActiveRecord for a majority of interfaces and use-
cases, though the underlying implementation is much closer to more
traditional O/R Mappers such as Hibernate, the Scott Ambler examples,
and Martin Fowler's description.
This specific case for example is handled easily since the DataMapper
employs a UnitOfWork pattern to track changes.