Class: Flounder::Query::Select
- Includes:
- Enumerable
- Defined in:
- lib/flounder/query/select.rb
Overview
A query obtained by calling any of the chain methods on an entity.
Instance Attribute Summary collapse
-
#default_projection ⇒ Object
readonly
All projected fields if no custom projection is made.
-
#has_projection ⇒ Object
readonly
Set to true once #project is used.
-
#join_entity ⇒ Object
readonly
Returns the value of attribute join_entity.
-
#last_join ⇒ Object
readonly
Returns the value of attribute last_join.
-
#manager ⇒ Object
readonly
Arel SqlManager that accumulates this query.
-
#projection_prefixes ⇒ Object
readonly
Each projection has a unique prefix mapping to the entity that uses this prefix during this query.
-
#relation_entity_map ⇒ Object
readonly
maps relations that were included in this select to their entities.
Attributes inherited from Base
#bind_values, #domain, #engine, #entity
Instance Method Summary collapse
- #_join(join_node, entity) ⇒ Object
- #add_fields_to_default(entity) ⇒ Object
- #anchor ⇒ Object
-
#connect(*connect_spec) ⇒ Object
Follows relationships on the currently anchored entity.
- #each(&block) ⇒ Object
- #first ⇒ Object
- #group_by(*field_list) ⇒ Object
- #having(*conditions) ⇒ Object
- #hoist ⇒ Object
-
#initialize(domain, from_entity) ⇒ Select
constructor
A new instance of Select.
- #inner_join(*args) ⇒ Object (also: #join)
- #limit(n) ⇒ Object
- #offset(n) ⇒ Object
- #on(join_conditions) ⇒ Object
-
#order_by(*field_list) ⇒ Object
Orders by a list of field references.
- #outer_join(*args) ⇒ Object
-
#project(*field_list) ⇒ Object
Adds a field to the projection clause of the SQL statement (the part between SELECT and FROM).
-
#size ⇒ Object
Executes a ‘select count(*)` query on the database and returns the result.
Methods inherited from Base
#kick, #measure, #parse_conditions, #to_sql, #where, #with
Methods included from Helpers::Entity
#convert_to_entity, #entity_like?
Constructor Details
#initialize(domain, from_entity) ⇒ Select
Returns a new instance of Select.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/flounder/query/select.rb', line 30 def initialize domain, from_entity super domain, Arel::SelectManager, from_entity @has_projection = false @projection_prefixes = Hash.new @default_projection = [] # by default, joins are made to the entity that you start the query with @join_entity = entity @relation_entity_map = {} add_fields_to_default from_entity manager.from from_entity.table end |
Instance Attribute Details
#default_projection ⇒ Object (readonly)
All projected fields if no custom projection is made. Fields are encoded so that they can be traced back to the entity that contributed them.
14 15 16 |
# File 'lib/flounder/query/select.rb', line 14 def default_projection @default_projection end |
#has_projection ⇒ Object (readonly)
Set to true once #project is used. From that point on, no fields can be added through default projections.
19 20 21 |
# File 'lib/flounder/query/select.rb', line 19 def has_projection @has_projection end |
#join_entity ⇒ Object (readonly)
Returns the value of attribute join_entity.
25 26 27 |
# File 'lib/flounder/query/select.rb', line 25 def join_entity @join_entity end |
#last_join ⇒ Object (readonly)
Returns the value of attribute last_join.
25 26 27 |
# File 'lib/flounder/query/select.rb', line 25 def last_join @last_join end |
#manager ⇒ Object (readonly)
Arel SqlManager that accumulates this query.
10 11 12 |
# File 'lib/flounder/query/select.rb', line 10 def manager @manager end |
#projection_prefixes ⇒ Object (readonly)
Each projection has a unique prefix mapping to the entity that uses this prefix during this query.
23 24 25 |
# File 'lib/flounder/query/select.rb', line 23 def projection_prefixes @projection_prefixes end |
#relation_entity_map ⇒ Object (readonly)
maps relations that were included in this select to their entities.
28 29 30 |
# File 'lib/flounder/query/select.rb', line 28 def relation_entity_map @relation_entity_map end |
Instance Method Details
#_join(join_node, entity) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/flounder/query/select.rb', line 48 def _join join_node, entity entity = convert_to_entity(entity) @last_join = entity table = entity.table manager.join(table, join_node) add_fields_to_default(entity) self end |
#add_fields_to_default(entity) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/flounder/query/select.rb', line 60 def add_fields_to_default entity # Don't add fields through the default method if #project was already # used. return if has_projection prefix = entity.name.to_s table = entity.table warn "Table alias #{prefix} already used in select; field aliasing will occur!" \ if projection_prefixes.has_key? prefix projection_prefixes[prefix] = entity entity.column_names.each do |name| default_projection << table[name].as("_#{prefix}_#{name}") end end |
#anchor ⇒ Object
94 95 96 97 |
# File 'lib/flounder/query/select.rb', line 94 def anchor @join_entity = last_join self end |
#connect(*connect_spec) ⇒ Object
Follows relationships on the currently anchored entity. This is like an explicit join, but allows to eliminate repetition.
Example:
users.
connect(:posts => {:comments => :author}).
where(:author, id: 2)
# roughly aequivalent to
= users.as(:authors, :author)
users.
join(:posts).on(:id => :user_id).anchor.
join(:comments).on(:id => :post_id).anchor.
join().on(:author_id => :id).
where(, id: 2)
185 186 187 188 189 |
# File 'lib/flounder/query/select.rb', line 185 def connect *connect_spec follow_relation_spec(join_entity, connect_spec) self end |
#each(&block) ⇒ Object
147 148 149 |
# File 'lib/flounder/query/select.rb', line 147 def each &block all.each(&block) end |
#first ⇒ Object
152 153 154 155 156 |
# File 'lib/flounder/query/select.rb', line 152 def first manager.take(1) all.first end |
#group_by(*field_list) ⇒ Object
115 116 117 118 |
# File 'lib/flounder/query/select.rb', line 115 def group_by *field_list manager.group *map_to_arel(field_list) self end |
#having(*conditions) ⇒ Object
119 120 121 |
# File 'lib/flounder/query/select.rb', line 119 def having *conditions parse_conditions(*conditions) { |bit| manager.having(bit) } end |
#hoist ⇒ Object
98 99 100 101 |
# File 'lib/flounder/query/select.rb', line 98 def hoist @join_entity = entity self end |
#inner_join(*args) ⇒ Object Also known as: join
78 79 80 |
# File 'lib/flounder/query/select.rb', line 78 def inner_join *args _join(Arel::Nodes::InnerJoin, *args) end |
#limit(n) ⇒ Object
136 137 138 139 |
# File 'lib/flounder/query/select.rb', line 136 def limit n manager.take n self end |
#offset(n) ⇒ Object
140 141 142 143 |
# File 'lib/flounder/query/select.rb', line 140 def offset n manager.skip n self end |
#on(join_conditions) ⇒ Object
87 88 89 90 91 92 |
# File 'lib/flounder/query/select.rb', line 87 def on join_conditions manager.on( *join_conditions.map { |(k, v)| transform_tuple( join_entity, k, join_field(v)) }) self end |
#order_by(*field_list) ⇒ Object
Orders by a list of field references.
Note: Replaces previous order_by.
127 128 129 130 131 132 133 134 |
# File 'lib/flounder/query/select.rb', line 127 def order_by *field_list manager.orders.clear field_list.each do |field| field = transform field manager.order field end self end |
#outer_join(*args) ⇒ Object
83 84 85 |
# File 'lib/flounder/query/select.rb', line 83 def outer_join *args _join(Arel::Nodes::OuterJoin, *args) end |
#project(*field_list) ⇒ Object
Adds a field to the projection clause of the SQL statement (the part between SELECT and FROM). Projection of ‘*’ is the default, so you can omit this call entirely if you want that.
107 108 109 110 111 112 113 |
# File 'lib/flounder/query/select.rb', line 107 def project *field_list @has_projection = true @default_projection = [] manager.project *map_to_arel(field_list) self end |
#size ⇒ Object
Executes a ‘select count(*)` query on the database and returns the result. If you want to avoid modifying your query (!) using this, dup it or execute it first and then call #size on the resulting array.
162 163 164 165 166 167 |
# File 'lib/flounder/query/select.rb', line 162 def size manager.projections = [] project 'count(*)::int as count' all.first.count end |