class Ransack::Adapters::ActiveRecord::Context
Constants
- JoinBase
- JoinDependency
Because the AR::Associations namespace is insane
- JoinPart
Public Class Methods
new(object, options = {})
click to toggle source
Redefine a few things for ActiveRecord 3.0.
Calls superclass method
Ransack::Context.new
# File lib/ransack/adapters/active_record/3.0/context.rb, line 16 def initialize(object, options = {}) super @arel_visitor = Arel::Visitors.visitor_for @engine end
Public Instance Methods
alias_tracker()
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 87 def alias_tracker raise NotImplementedError, "ActiveRecord 3.0 does not have an alias tracker" end
attribute_method?(str, klass = @klass)
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 40 def attribute_method?(str, klass = @klass) exists = false if ransackable_attribute?(str, klass) exists = true elsif (segments = str.split(/_/)).size > 1 remainder = [] found_assoc = nil while !found_assoc && remainder.unshift(segments.pop) && segments.size > 0 do assoc, poly_class = unpolymorphize_association( segments.join(Constants::UNDERSCORE) ) if found_assoc = get_association(assoc, klass) exists = attribute_method?( remainder.join(Constants::UNDERSCORE), poly_class || found_assoc.klass ) end end end exists end
evaluate(search, opts = {})
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 25 def evaluate(search, opts = {}) viz = Visitor.new relation = @object.where(viz.accept(search.base)) if search.sorts.any? relation = relation.except(:order) .reorder(viz.accept(search.sorts)) end if opts[:distinct] relation.select(Constants::DISTINCT + @klass.quoted_table_name + Constants::DOT_ASTERIX) else relation end end
join_associations()
click to toggle source
All dependent JoinAssociation items used in the search query
# File lib/ransack/adapters/active_record/3.0/context.rb, line 78 def join_associations @join_dependency.join_associations end
join_sources()
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 82 def join_sources raise NotImplementedError, "ActiveRecord 3.0 does not use join_sources or support joining relations with Arel::Join nodes. Use join_associations." end
klassify(obj)
click to toggle source
# File lib/ransack/adapters/active_record/context.rb, line 70 def klassify(obj) if Class === obj && ::ActiveRecord::Base > obj obj elsif obj.respond_to? :klass obj.klass elsif obj.respond_to? :base_klass obj.base_klass else raise ArgumentError, "Don't know how to klassify #{obj}" end end
relation_for(object)
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 21 def relation_for(object) object.scoped end
table_for(parent)
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 65 def table_for(parent) parent.table end
type_for(attr)
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 69 def type_for(attr) return nil unless attr && attr.valid? klassify(attr.parent) .columns_hash[attr.arel_attribute.name.to_s] .type end
Private Instance Methods
associations(assoc, parent)
click to toggle source
# File lib/ransack/adapters/active_record/context.rb, line 266 def associations(assoc, parent) @associations_pot ||= {} @associations_pot[assoc] = parent end
build_join_dependency(relation)
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 134 def build_join_dependency(relation) buckets = relation.joins_values.group_by do |join| case join when String Constants::STRING_JOIN when Hash, Symbol, Array Constants::ASSOCIATION_JOIN when ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation Constants::STASHED_JOIN when Arel::Nodes::Join Constants::JOIN_NODE else raise 'unknown class: %s' % join.class.name end end association_joins = buckets[Constants::ASSOCIATION_JOIN] || [] stashed_association_joins = buckets[Constants::STASHED_JOIN] || [] join_nodes = buckets[Constants::JOIN_NODE] || [] string_joins = (buckets[Constants::STRING_JOIN] || []).map(&:strip).uniq join_list = relation.send :custom_join_sql, (string_joins + join_nodes) join_dependency = JoinDependency.new( relation.klass, association_joins, join_list ) join_nodes.each do |join| join_dependency.table_aliases[join.left.name.downcase] = 1 end join_dependency.graft(*stashed_association_joins) end
build_joins(relation)
click to toggle source
Checkout active_record/relation/query_methods.rb build_joins
for reference. Lots of duplicated code maybe we can avoid it
# File lib/ransack/adapters/active_record/context.rb, line 180 def build_joins(relation) buckets = relation.joins_values.group_by do |join| case join when String :string_join when Hash, Symbol, Array :association_join when Polyamorous::JoinDependency, Polyamorous::JoinAssociation :stashed_join when Arel::Nodes::Join :join_node else raise 'unknown class: %s' % join.class.name end end buckets.default = [] association_joins = buckets[:association_join] stashed_association_joins = buckets[:stashed_join] join_nodes = buckets[:join_node].uniq string_joins = buckets[:string_join].map(&:strip).uniq join_list = if ::ActiveRecord::VERSION::MAJOR >= 5 join_nodes + convert_join_strings_to_ast(relation.table, string_joins) else relation.send :custom_join_ast, relation.table.from(relation.table), string_joins end join_dependency = JoinDependency.new( relation.klass, association_joins, join_list ) join_nodes.each do |join| join_dependency.alias_tracker.aliases[join.left.name.downcase] = 1 end if ::ActiveRecord::VERSION::STRING >= Constants::RAILS_4_1 join_dependency else join_dependency.graft(*stashed_association_joins) end end
build_or_find_association(name, parent = @base, klass = nil)
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 173 def build_or_find_association(name, parent = @base, klass = nil) found_association = @join_dependency.join_associations .detect do |assoc| assoc.reflection.name == name && assoc.parent == parent && (!klass || assoc.reflection.klass == klass) end unless found_association @join_dependency.send( :build, Polyamorous::Join.new(name, @join_type, klass), parent ) found_association = @join_dependency.join_associations.last default_conditions = found_association.active_record.scoped.arel.constraints if default_conditions.any? and_default_conditions = "AND #{default_conditions.reduce(&:and).to_sql}" end # Leverage the stashed association functionality in AR @object = @object.joins(found_association).joins(and_default_conditions) end found_association end
convert_join_strings_to_ast(table, joins)
click to toggle source
# File lib/ransack/adapters/active_record/context.rb, line 225 def convert_join_strings_to_ast(table, joins) joins .flatten .reject(&:blank?) .map { |join| table.create_string_join(Arel.sql(join)) } end
get_association(str, parent = @base)
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 120 def get_association(str, parent = @base) klass = klassify parent ransackable_association?(str, klass) && klass.reflect_on_all_associations.detect { |a| a.name.to_s == str } end
get_parent_and_attribute_name(str, parent = @base)
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 94 def get_parent_and_attribute_name(str, parent = @base) attr_name = nil if ransackable_attribute?(str, klassify(parent)) attr_name = str elsif (segments = str.split(/_/)).size > 1 remainder = [] found_assoc = nil while remainder.unshift(segments.pop) && segments.size > 0 && !found_assoc do assoc, klass = unpolymorphize_association( segments.join(Constants::UNDERSCORE) ) if found_assoc = get_association(assoc, parent) join = build_or_find_association( found_assoc.name, parent, klass ) parent, attr_name = get_parent_and_attribute_name( remainder.join(Constants::UNDERSCORE), join ) end end end [parent, attr_name] end
join_dependency(relation)
click to toggle source
# File lib/ransack/adapters/active_record/3.0/context.rb, line 126 def join_dependency(relation) if relation.respond_to?(:join_dependency) # Squeel will enable this relation.join_dependency else build_join_dependency(relation) end end