diff options
Diffstat (limited to 'activerecord/lib/active_record/relation')
3 files changed, 33 insertions, 13 deletions
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 7eeb3dde70..3c8e0f2052 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -191,7 +191,7 @@ module ActiveRecord join_dependency = construct_join_dependency_for_association_find relation = construct_relation_for_association_find(join_dependency) - relation = relation.except(:select).select("1").limit(1) + relation = relation.except(:select, :order).select("1").limit(1) case id when Array, Hash diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index 7e8ddd1b5d..af167dc59b 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -22,21 +22,23 @@ module ActiveRecord value = value.select(value.klass.arel_table[value.klass.primary_key]) if value.select_values.empty? attribute.in(value.arel.ast) when Array, ActiveRecord::Associations::CollectionProxy - values = value.to_a.map { |x| - x.is_a?(ActiveRecord::Base) ? x.id : x - } + values = value.to_a.map {|x| x.is_a?(ActiveRecord::Base) ? x.id : x} + ranges, values = values.partition {|value| value.is_a?(Range) || value.is_a?(Arel::Relation)} + + array_predicates = ranges.map {|range| attribute.in(range)} if values.include?(nil) values = values.compact if values.empty? - attribute.eq nil + array_predicates << attribute.eq(nil) else - attribute.in(values.compact).or attribute.eq(nil) + array_predicates << attribute.in(values.compact).or(attribute.eq(nil)) end else - attribute.in(values) + array_predicates << attribute.in(values) end + array_predicates.inject {|composite, predicate| composite.or(predicate)} when Range, Arel::Relation attribute.in(value) when ActiveRecord::Base diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 670ba0987d..c281bead0d 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -9,7 +9,8 @@ module ActiveRecord :select_values, :group_values, :order_values, :joins_values, :where_values, :having_values, :bind_values, :limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value, - :from_value, :reorder_value, :reverse_order_value + :from_value, :reorder_value, :reverse_order_value, + :uniq_value def includes(*args) args.reject! {|a| a.blank? } @@ -38,7 +39,7 @@ module ActiveRecord end # Works in two unique ways. - # + # # First: takes a block so it can be used just like Array#select. # # Model.scoped.select { |m| m.field == value } @@ -176,9 +177,25 @@ module ActiveRecord relation end + # Specifies whether the records should be unique or not. For example: + # + # User.select(:name) + # # => Might return two records with the same name + # + # User.select(:name).uniq + # # => Returns 1 record per unique name + # + # User.select(:name).uniq.uniq(false) + # # => You can also remove the uniqueness + def uniq(value = true) + relation = clone + relation.uniq_value = value + relation + end + # Used to extend a scope with additional methods, either through - # a module or through a block provided. - # + # a module or through a block provided. + # # The object returned is a relation, which can be further extended. # # === Using a module @@ -200,7 +217,7 @@ module ActiveRecord # # scope = Model.scoped.extending do # def page(number) - # # pagination code goes here + # # pagination code goes here # end # end # scope.page(params[:page]) @@ -209,7 +226,7 @@ module ActiveRecord # # scope = Model.scoped.extending(Pagination) do # def per_page(number) - # # pagination code goes here + # # pagination code goes here # end # end def extending(*modules) @@ -252,6 +269,7 @@ module ActiveRecord build_select(arel, @select_values.uniq) + arel.distinct(@uniq_value) arel.from(@from_value) if @from_value arel.lock(@lock_value) if @lock_value |