You are currently browsing the tag archive for the ‘ActiveRecord’ tag.
When fetching all associations with includes they are not cached, but could be, since they are still the same records(unlike with :select/:conditions etc)
user = User.first
user.comments.length # hits db
user.comments.length # cached
user = User.first
user.commens.all(:include=>:comenter).length # hits db
user.commens.all(:include=>:comenter).length # hits db
user.comments.length # hits db
Cached find all with includes
This can save requests when performing repetitive calls to the same record.
user = User.first
user.comments.load_target_with_includes([:commenter, :tags]).length # hits db
user.comments.load_target_with_includes([:commenter, :tags]).length # cached
user.comments.length # cached
Code
# do not load an association twice, when all we need are includes
# all(:include=>xxx) would always reload the target
class ActiveRecord::Associations::AssociationCollection
def load_target_with_includes(includes)
raise if @owner.new_record?
if loaded?
@target
else
@loaded = true
@target = all(:include => includes)
end
end
end
Sometimes big updates that affect millions of rows kill our database (all queries hang/are blocked).
Therefore we built a simple solution:
class ActiveRecord::Base
def self.slow_update_all(set, where, options={})
ids_to_update = find_values(:select => :id, :conditions => where)
ids_to_update.each_slice(10_000) do |slice|
update_all(set, :id => slice)
sleep options[:sleep] if options[:sleep]
end
ids_to_update.size
end
end
This needs ActiveRecord find_values extension
A simple and readable alternative to update_all({:x=>y}, :id=>id)
Usage
User.update_one(id, :name=>'Pete')
Code
clas ActiveRecord::Base
def self.update_one(id, attributes)
update_all(attributes, :id => id)
end
end
ActiveRecord`s validate_uniqueness_of produces evil SQL that will not use your existing index!
Before:
SELECT `users`.id FROM `users` WHERE `users`.`email` = BINARY ‘my@email.com’ AND `users`.id 1234) LIMIT 1; –> 0.80s
After:
SELECT `users`.id FROM `users` WHERE `users`.`email` = ‘my@email.com’ AND `users`.id 1234) LIMIT 1; –> 0.00s
Hack to make AR use faster queries on the cost that no case-sensitive queries can be made anymore.
# validates_uniqueness_of produces "column = BINARY 'text'" queries
# which will not use existing indices, so we add this
# EVIL HACK to make
# ALL validates_uniqueness_of in-case-sensitive
class ActiveRecord::ConnectionAdapters::MysqlAdapter
def case_sensitive_equality_operator
"="
end
end
When updating to 2.3.4 I noticed that touch is
no longer a simple ‘update :updated_at’, but a save!,
which caused some code to break
(e.g. touch`ing in after_save == loop)
Usage
User.first.touch_without_callbacks User.touch_without_callbacks([User.first.id, User.last.id])
Install
Paste somewhere…
# Provide .touch as it was in 2.3.2, simply update the :updated_at field.
class ActiveRecord::Base
def touch_without_callbacks
now = Time.now.utc
self.class.touch(id, now)
self.updated_at = now
end
def self.touch_without_callbacks(ids, time=Time.now.utc)
update_all({:updated_at=>time}, :id=>ids)
end
end
