edge_rider is Power tools for ActiveRecord relations (scopes). Please note that some of the functions edge_rider provides have native implementations in newer rails versions.
Useful in applications
Relation#traverse_association(*names)
Edge Rider gives your relations a method #traverse_association
which returns a new relation by "pivoting" around a named association. You can traverse multiple associations in a single call. E.g. to turn a relation of posts into a relation of all posts of their authors:
posts = Post.where(:archived => false)
posts_by_same_authors = posts.traverse_association(:author, :posts)
Model.preload_associations(object, associations)
Edge Rider gives your model classes a method .preload_associations. The method can be used to preload associations for loaded objects like this:
@user = User.find(params[:id])
User.preload_associations [@user], { :threads => { :posts => :author }, :messages => :sender }
Useful in libraries
These utilities are mostly useful in libraries that need to support multiple versions of Rails. They offer a unified interface across Rails versions.
Relation#collect_ids
You should not use relation.collect(&:id) for this because a call like that will instantiate a potentially large number of ActiveRecord objects only to collect its ID.
Edge Rider has a better way. Your relations gain a method #collect_ids that will fetch all IDs in a single query without instantiating a single ActiveRecord object:
posts = Post.where(:archived => false)
post_ids = posts.collect_ids
Implemenation note: In Rails 3.2+, #collect_ids
delegates to #pluck
, which can be used for the same purpose.
Relation#collect_column(name, options)
You should not use relation.collect(&:column) for this because a call like that will instantiate a potentially large number of ActiveRecord objects only to collect its column value.
Edge Rider has a better way. Your relations gain a method #collect_column that will fetch all column values in a single query without instantiating a single ActiveRecord object. If you only care about unique values, use the :distinct => true option:
posts = Post.where(:archived => false)
distinct_subjects = posts.collect_column(:subject, :distinct => true)
Implementation note: In Rails 3.2+, #collect_column
delegates to #pluck
, which can be used for the same effect.
Relation#to_sql
# Rails 2 scope
Post.scoped(:conditions => { :id => [1, 2] }).to_sql
# => "SELECT `posts`.* FROM `posts` WHERE `posts.id` IN (1, 2)"
^
# Rails 3 relation
Post.where(:id => [1, 2]).to_sql
# => "SELECT `posts`.* FROM `posts` WHERE `posts.id` IN (1, 2)"
Implementation note: Rails 3+ implements #to_sql
.
Relation#to_id_query
Site.joins(:user).where(:users => { :name => 'Bruce' }).to_id_query
to_id_query
will immediately run an SQL query where it collects all the IDs that match your relation:
SELECT sites.id FROM sites INNER JOIN users WHERE sites.user_id = sites.id AND users.name = 'Bruce'
It now uses these IDs to return a new relation that has no joins and a single condition on the id column:
SELECT * FROM sites WHERE sites.user_id IN (3, 17, 103)
Relation#origin_class
Edge Rider gives your relations a method #origin_class that returns the class the relation is based on. This is useful e.g. to perform unscoped record look-up.
Post.recent.origin_class
# => Post
Model.scoped
Edge Rider ports Model.scoped forward to Rails 4+ (taken from activerecord-deprecated_finders).
User.scoped # just calls User.all in Rails 4
User.active.scoped(conditions: { admin: true })