Module: MetaWhere::Relation
- Defined in:
- lib/meta_where/relation.rb
Class Method Summary collapse
Instance Method Summary collapse
- #attribute_visitor ⇒ Object
- #build_arel ⇒ Object
- #build_custom_joins(joins = [], arel = nil) ⇒ Object
- #build_where(opts, other = []) ⇒ Object
- #construct_limited_ids_condition(relation) ⇒ Object
- #custom_join_sql(*joins) ⇒ 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
- #select(value = Proc.new) ⇒ Object
- #where_values_hash_with_metawhere ⇒ Object
Class Method Details
.included(base) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 |
# File 'lib/meta_where/relation.rb', line 4 def self.included(base) base.class_eval do alias_method_chain :reset, :metawhere alias_method_chain :where_values_hash, :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
121 122 123 124 |
# File 'lib/meta_where/relation.rb', line 121 def attribute_visitor join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_joins) MetaWhere::Visitors::Attribute.new(join_dependency) end |
#build_arel ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/meta_where/relation.rb', line 150 def build_arel arel = table visitor = predicate_visitor arel = build_intelligent_joins(arel, visitor) if @joins_values.present? predicate_wheres = flatten_predicates(@where_values.uniq, visitor) arel = collapse_wheres(arel, (predicate_wheres - ['']).uniq) arel = arel.having(*flatten_predicates(@having_values, visitor).reject {|h| h.blank?}) unless @having_values.empty? arel = arel.take(@limit_value) if @limit_value arel = arel.skip(@offset_value) if @offset_value arel = arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty? arel = build_order(arel, attribute_visitor, @order_values) unless @order_values.empty? arel = build_select(arel, @select_values.uniq) arel = arel.from(@from_value) if @from_value arel = arel.lock(@lock_value) if @lock_value arel end |
#build_custom_joins(joins = [], arel = nil) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/meta_where/relation.rb', line 67 def build_custom_joins(joins = [], arel = nil) arel ||= table joins.each do |join| next if join.blank? @implicit_readonly = true case join when ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation arel = arel.join(join.relation, Arel::Nodes::OuterJoin).on(*join.on) when Hash, Array, Symbol if array_of_strings?(join) join_string = join.join(' ') arel = arel.join(join_string) end else arel = arel.join(join) end end arel end |
#build_where(opts, other = []) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/meta_where/relation.rb', line 46 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
142 143 144 145 146 147 148 |
# File 'lib/meta_where/relation.rb', line 142 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 |
#custom_join_sql(*joins) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/meta_where/relation.rb', line 90 def custom_join_sql(*joins) arel = table joins.each do |join| next if join.blank? @implicit_readonly = true case join when Hash, Array, Symbol if array_of_strings?(join) join_string = join.join(' ') arel = arel.join(join_string) end else arel = arel.join(join) end end arel.joins(arel) 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.
132 133 134 135 136 137 138 139 140 |
# File 'lib/meta_where/relation.rb', line 132 def debug_sql if eager_loading? including = (@eager_load_values + @includes_values).uniq join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, nil) construct_relation_for_association_find(join_dependency).to_sql else arel.to_sql end end |
#merge(r, association_name = nil) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/meta_where/relation.rb', line 16 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.
116 117 118 119 |
# File 'lib/meta_where/relation.rb', line 116 def predicate_visitor join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_joins) MetaWhere::Visitors::Predicate.new(join_dependency) end |
#predicates_without_conflicting_equality ⇒ Object
110 111 112 |
# File 'lib/meta_where/relation.rb', line 110 def predicates_without_conflicting_equality remove_conflicting_equality_predicates(flatten_predicates(@where_values, predicate_visitor)) end |
#reset_with_metawhere ⇒ Object
29 30 31 32 33 |
# File 'lib/meta_where/relation.rb', line 29 def @mw_unique_joins = @mw_association_joins = @mw_non_association_joins = @mw_stashed_association_joins = @mw_custom_joins = nil end |
#select(value = Proc.new) ⇒ Object
178 179 180 181 182 183 184 |
# File 'lib/meta_where/relation.rb', line 178 def select(value = Proc.new) if MetaWhere::Function === value value.table = self.arel_table end super end |
#where_values_hash_with_metawhere ⇒ Object
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/meta_where/relation.rb', line 35 def Hash[flatten_nodes(flatten_predicates(@where_values, predicate_visitor)).find_all { |w| w.respond_to?(:operator) && w.operator == :== && w.left.relation.name == table_name }.map { |where| [ where.left.name, where.right.respond_to?(:value) ? where.right.value : where.right ] }] end |