Module: MetaWhere::Relation
- Defined in:
- lib/meta_where/relation.rb
Constant Summary collapse
- JoinAssociation =
::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation
- JoinDependency =
::ActiveRecord::Associations::ClassMethods::JoinDependency
Instance Attribute Summary collapse
- #join_dependency ⇒ Object readonly
Class Method Summary collapse
Instance Method Summary collapse
- #attribute_visitor ⇒ Object
- #build_arel ⇒ Object
- #build_where(opts, other = []) ⇒ Object
- #construct_limited_ids_condition(relation) ⇒ Object
-
#debug_sql ⇒ Object
Simulate the logic that occurs in ActiveRecord::Relation.to_a.
- #merge(r, association_name = nil) ⇒ Object
-
#predicate_visitor ⇒ Object
Very occasionally, we need to get a visitor for another relation, so it makes sense to factor these out into a public method despite only being two lines long.
- #predicates_without_conflicting_equality ⇒ Object
- #reset_with_metawhere ⇒ Object
- #scope_for_create_with_metawhere ⇒ Object
- #select(value = Proc.new) ⇒ Object
Instance Attribute Details
#join_dependency ⇒ Object
22 23 24 |
# File 'lib/meta_where/relation.rb', line 22 def join_dependency @join_dependency ||= (build_join_dependency(table.from(table), @joins_values) && @join_dependency) end |
Class Method Details
.included(base) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/meta_where/relation.rb', line 10 def self.included(base) base.class_eval do alias_method_chain :reset, :metawhere alias_method_chain :scope_for_create, :metawhere end # We have to do this on the singleton to work with Ruby 1.8.7. Not sure why. base.instance_eval do alias_method :&, :merge end end |
Instance Method Details
#attribute_visitor ⇒ Object
92 93 94 95 96 97 98 |
# File 'lib/meta_where/relation.rb', line 92 def attribute_visitor @attribute_visitor ||= begin visitor = MetaWhere::Visitors::Attribute.new visitor.join_dependency = join_dependency visitor end end |
#build_arel ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/meta_where/relation.rb', line 124 def build_arel arel = table.from table build_join_dependency(arel, @joins_values) unless @joins_values.empty? visitor = predicate_visitor predicate_wheres = flatten_predicates(@where_values.uniq, visitor) collapse_wheres(arel, (predicate_wheres - ['']).uniq) arel.having(*flatten_predicates(@having_values, visitor).reject {|h| h.blank?}) unless @having_values.empty? arel.take(@limit_value) if @limit_value arel.skip(@offset_value) if @offset_value arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty? build_order(arel, attribute_visitor, @order_values) unless @order_values.empty? build_select(arel, @select_values.uniq) arel.from(@from_value) if @from_value arel.lock(@lock_value) if @lock_value arel end |
#build_where(opts, other = []) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/meta_where/relation.rb', line 57 def build_where(opts, other = []) if opts.is_a?(String) [@klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))] else predicates = [] [opts, *other].each do |arg| predicates += Array.wrap( case arg when Array @klass.send(:sanitize_sql, arg) when Hash @klass.send(:expand_hash_conditions_for_aggregates, arg) else arg end ) end predicates end end |
#construct_limited_ids_condition(relation) ⇒ Object
116 117 118 119 120 121 122 |
# File 'lib/meta_where/relation.rb', line 116 def construct_limited_ids_condition(relation) visitor = relation.attribute_visitor relation.order_values.map! {|o| visitor.can_accept?(o) ? visitor.accept(o).to_sql : o} super end |
#debug_sql ⇒ Object
Simulate the logic that occurs in ActiveRecord::Relation.to_a
This will let us get a dump of the SQL that will be run against the DB for debug purposes without actually running the query.
106 107 108 109 110 111 112 113 114 |
# File 'lib/meta_where/relation.rb', line 106 def debug_sql if eager_loading? including = (@eager_load_values + @includes_values).uniq join_dependency = JoinDependency.new(@klass, including, []) construct_relation_for_association_find(join_dependency).to_sql else arel.to_sql end end |
#merge(r, association_name = nil) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/meta_where/relation.rb', line 26 def merge(r, association_name = nil) if (r && (association_name || base_class.name != r.klass.base_class.name)) # Merging relations with different base. association_name ||= (default_association = reflect_on_all_associations.detect {|a| a.class_name == r.klass.name}) ? default_association.name : r.table_name.to_sym r = r.clone r.where_values.map! {|w| MetaWhere::Visitors::Predicate.visitables.include?(w.class) ? {association_name => w} : w} r.joins_values.map! {|j| [Symbol, Hash, MetaWhere::JoinType].include?(j.class) ? {association_name => j} : j} self.joins_values += [association_name] if reflect_on_association(association_name) end super(r) end |
#predicate_visitor ⇒ Object
Very occasionally, we need to get a visitor for another relation, so it makes sense to factor these out into a public method despite only being two lines long.
84 85 86 87 88 89 90 |
# File 'lib/meta_where/relation.rb', line 84 def predicate_visitor @predicate_visitor ||= begin visitor = MetaWhere::Visitors::Predicate.new visitor.join_dependency = join_dependency visitor end end |
#predicates_without_conflicting_equality ⇒ Object
78 79 80 |
# File 'lib/meta_where/relation.rb', line 78 def predicates_without_conflicting_equality remove_conflicting_equality_predicates(flatten_predicates(@where_values, predicate_visitor)) end |
#reset_with_metawhere ⇒ Object
39 40 41 42 43 |
# File 'lib/meta_where/relation.rb', line 39 def @mw_unique_joins = @mw_association_joins = @mw_non_association_joins = @mw_stashed_association_joins = @mw_custom_joins = nil end |
#scope_for_create_with_metawhere ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/meta_where/relation.rb', line 45 def @scope_for_create ||= begin @create_with_value || predicates_without_conflicting_equality.inject({}) do |hash, where| if is_equality_predicate?(where) hash[where.left.name] = where.right.respond_to?(:value) ? where.right.value : where.right end hash end end end |
#select(value = Proc.new) ⇒ Object
152 153 154 155 156 157 158 |
# File 'lib/meta_where/relation.rb', line 152 def select(value = Proc.new) if MetaWhere::Function === value value.table = self.arel_table end super end |