Class: ActsAsRecursiveTree::Builders::RelationBuilder
- Inherits:
-
Object
- Object
- ActsAsRecursiveTree::Builders::RelationBuilder
- Defined in:
- lib/acts_as_recursive_tree/builders/relation_builder.rb
Overview
Constructs the Arel necessary for recursion.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#ids ⇒ Object
readonly
Returns the value of attribute ids.
-
#klass ⇒ Object
readonly
Returns the value of attribute klass.
-
#recursive_temp_table ⇒ Object
readonly
Returns the value of attribute recursive_temp_table.
-
#travers_loc_table ⇒ Object
readonly
Returns the value of attribute travers_loc_table.
-
#without_ids ⇒ Object
readonly
Returns the value of attribute without_ids.
Class Method Summary collapse
Instance Method Summary collapse
- #apply_depth(select_manager) ⇒ Object
- #apply_except_id(relation) ⇒ Object
- #apply_parent_type_column(arel_condition) ⇒ Object
- #apply_query_opts_condition(relation) ⇒ Object
- #base_table ⇒ Object
- #build ⇒ Object
- #build_base_join_select(select_manager) ⇒ Object
- #build_base_select ⇒ Object
- #build_cte_table ⇒ Object
- #build_union_select ⇒ Object
- #create_select_manger(column = nil) ⇒ Object
-
#get_query_options(proc) ⇒ ActsAsRecursiveTree::Options::QueryOptions
Constructs a new QueryOptions and yield it to the proc if one is present.
-
#initialize(klass, ids, exclude_ids: false, &block) ⇒ RelationBuilder
constructor
A new instance of RelationBuilder.
Constructor Details
#initialize(klass, ids, exclude_ids: false, &block) ⇒ RelationBuilder
Returns a new instance of RelationBuilder.
21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 21 def initialize(klass, ids, exclude_ids: false, &block) @klass = klass @config = klass._recursive_tree_config @ids = ActsAsRecursiveTree::Options::Values.create(ids, @config) @without_ids = exclude_ids @query_opts = (block) rand_int = random.rand(1_000_000) @recursive_temp_table = Arel::Table.new("recursive_#{klass.table_name}_#{rand_int}_temp") @travers_loc_table = Arel::Table.new("traverse_#{rand_int}_loc") end |
Instance Attribute Details
#ids ⇒ Object (readonly)
Returns the value of attribute ids.
14 15 16 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 14 def ids @ids end |
#klass ⇒ Object (readonly)
Returns the value of attribute klass.
14 15 16 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 14 def klass @klass end |
#recursive_temp_table ⇒ Object (readonly)
Returns the value of attribute recursive_temp_table.
14 15 16 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 14 def recursive_temp_table @recursive_temp_table end |
#travers_loc_table ⇒ Object (readonly)
Returns the value of attribute travers_loc_table.
14 15 16 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 14 def travers_loc_table @travers_loc_table end |
#without_ids ⇒ Object (readonly)
Returns the value of attribute without_ids.
14 15 16 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 14 def without_ids @without_ids end |
Class Method Details
.build(klass, ids, exclude_ids: false, &block) ⇒ Object
8 9 10 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 8 def self.build(klass, ids, exclude_ids: false, &block) new(klass, ids, exclude_ids: exclude_ids, &block).build end |
Instance Method Details
#apply_depth(select_manager) ⇒ Object
65 66 67 68 69 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 65 def apply_depth(select_manager) return select_manager unless depth_present? select_manager.where(depth.apply_to(travers_loc_table[depth_column])) end |
#apply_except_id(relation) ⇒ Object
60 61 62 63 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 60 def apply_except_id(relation) return relation unless without_ids relation.where(ids.apply_negated_to(base_table[primary_key])) end |
#apply_parent_type_column(arel_condition) ⇒ Object
116 117 118 119 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 116 def apply_parent_type_column(arel_condition) return arel_condition unless parent_type_column.present? arel_condition.and(base_table[parent_type_column].eq(klass.base_class)) end |
#apply_query_opts_condition(relation) ⇒ Object
131 132 133 134 135 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 131 def apply_query_opts_condition(relation) # check with nil? and not #present?/#blank? which will execute the query return relation if condition.nil? relation.merge(condition) end |
#base_table ⇒ Object
49 50 51 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 49 def base_table klass.arel_table end |
#build ⇒ Object
53 54 55 56 57 58 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 53 def build relation = Strategy.(@query_opts).build(self) relation = apply_except_id(relation) relation end |
#build_base_join_select(select_manager) ⇒ Object
121 122 123 124 125 126 127 128 129 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 121 def build_base_join_select(select_manager) klass.select( base_table[primary_key], base_table[parent_key], Arel.sql( (travers_loc_table[depth_column] + 1).to_sql ).as(depth_column.to_s) ).unscope(where: :type).joins(select_manager.join_sources) end |
#build_base_select ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 90 def build_base_select id_node = base_table[primary_key] base_table.where( ids.apply_to(id_node) ).project( id_node, base_table[parent_key], Arel.sql('0').as(depth_column.to_s) ) end |
#build_cte_table ⇒ Object
83 84 85 86 87 88 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 83 def build_cte_table Arel::Nodes::As.new( travers_loc_table, build_base_select.union(build_union_select) ) end |
#build_union_select ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 102 def build_union_select join_condition = apply_parent_type_column( traversal_strategy.build(self) ) select_manager = base_table.join(travers_loc_table).on(join_condition) # need to use ActiveRecord here for merging relation relation = build_base_join_select(select_manager) relation = apply_query_opts_condition(relation) relation.arel end |
#create_select_manger(column = nil) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 71 def create_select_manger(column = nil) projections = if column travers_loc_table[column] else Arel.star end select_mgr = travers_loc_table.project(projections).with(:recursive, build_cte_table) apply_depth(select_mgr) end |
#get_query_options(proc) ⇒ ActsAsRecursiveTree::Options::QueryOptions
Constructs a new QueryOptions and yield it to the proc if one is present. Subclasses may override this method to provide sane defaults.
41 42 43 44 45 46 47 |
# File 'lib/acts_as_recursive_tree/builders/relation_builder.rb', line 41 def (proc) opts = ActsAsRecursiveTree::Options::QueryOptions.new proc.call(opts) if proc opts end |