Module: ActiveRecord::Refined::QueryMethods
- Defined in:
- lib/active_record/refined.rb
Instance Method Summary collapse
-
#distinct_on(*columns, &block) ⇒ Object
DISTINCT ON (...), which keeps the first row of each group the order brings up.
- #distinct_on!(*columns, &block) ⇒ Object
-
#distinct_on_values ⇒ Object
ActiveRecord generates these for the values it knows about; this one is ours, and lives in the same place so that it survives a spawn.
- #distinct_on_values=(columns) ⇒ Object
-
#from(value, subquery_name = nil, as: nil) ⇒ Object
A symbol names a table, which ActiveRecord's own from only takes as a string.
-
#from_cte(name) ⇒ Object
Selects a CTE in place of the model's own table.
- #from_cte_value ⇒ Object
- #from_cte_value=(name) ⇒ Object
- #group(*args, &block) ⇒ Object
- #having(opts = nil, *rest, &block) ⇒ Object
-
#joins(*args, as: nil, lateral: false, &block) ⇒ Object
asnames the table within the query, which is what makes a self join expressible: joins(:employees, as: :managers) { ... }. - #left_outer_joins(*args, as: nil, lateral: false, &block) ⇒ Object
- #order(*args, &block) ⇒ Object
- #select(*fields, &block) ⇒ Object
- #where(opts = nil, *rest, &block) ⇒ Object
Instance Method Details
#distinct_on(*columns, &block) ⇒ Object
DISTINCT ON (...), which keeps the first row of each group the order brings up. PostgreSQL has it and the others do not; Arel carries the node and refuses to write it elsewhere, the way it does a regexp, so there is nothing for this to check:
Post.distinct_on { :author }.order { [:author, :likes.desc] }
The portable shape is a row_number window in a subquery, which the README shows.
422 423 424 |
# File 'lib/active_record/refined.rb', line 422 def distinct_on(*columns, &block) spawn.distinct_on!(*columns, &block) end |
#distinct_on!(*columns, &block) ⇒ Object
426 427 428 429 430 431 432 433 |
# File 'lib/active_record/refined.rb', line 426 def distinct_on!(*columns, &block) columns = Array(evaluate_block(&block)) if block if columns.empty? raise ArgumentError, "distinct_on needs a column or an expression" end self.distinct_on_values += columns self end |
#distinct_on_values ⇒ Object
ActiveRecord generates these for the values it knows about; this one is ours, and lives in the same place so that it survives a spawn.
437 438 439 |
# File 'lib/active_record/refined.rb', line 437 def distinct_on_values @values.fetch(:distinct_on, ActiveRecord::QueryMethods::FROZEN_EMPTY_ARRAY) end |
#distinct_on_values=(columns) ⇒ Object
441 442 443 444 |
# File 'lib/active_record/refined.rb', line 441 def distinct_on_values=(columns) assert_modifiable! @values[:distinct_on] = columns end |
#from(value, subquery_name = nil, as: nil) ⇒ Object
A symbol names a table, which ActiveRecord's own from only takes as a
string. With as it is selected under another name; when that name
is the model's own, from_cte says the same thing without repeating it.
373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/active_record/refined.rb', line 373 def from(value, subquery_name = nil, as: nil) unless value.is_a?(Symbol) if as raise ArgumentError, "as: needs the table named as a symbol" end return super(value, subquery_name) end arel_table = Arel::Table.new(value) arel_table = arel_table.alias(as) if as super(arel_table, subquery_name) end |
#from_cte(name) ⇒ Object
Selects a CTE in place of the model's own table. The alias is not a choice -- ActiveRecord keeps qualifying columns with the table name, so the model's is the only name that works -- which is why it is taken from the model rather than asked for: with_recursive(tree: [...]).from_cte(:tree)
The name is checked against what with declares, so that a typo is
not a query against a table nobody has. Checked when the SQL is
built, since the CTE may be declared after this in the chain, or by a
scope merged into it.
395 396 397 398 399 400 401 402 |
# File 'lib/active_record/refined.rb', line 395 def from_cte(name) unless name.is_a?(Symbol) raise ArgumentError, "from_cte takes the CTE's name as a symbol" end relation = from(name, as: klass.table_name) relation.from_cte_value = name relation end |
#from_cte_value ⇒ Object
404 405 406 |
# File 'lib/active_record/refined.rb', line 404 def from_cte_value @values[:from_cte] end |
#from_cte_value=(name) ⇒ Object
408 409 410 411 |
# File 'lib/active_record/refined.rb', line 408 def from_cte_value=(name) assert_modifiable! @values[:from_cte] = name end |
#group(*args, &block) ⇒ Object
360 361 362 363 364 365 366 367 368 |
# File 'lib/active_record/refined.rb', line 360 def group(*args, &block) if block result = evaluate_block(&block) arel = Array(result).map {|node| to_arel_field(node) } super(*arel, &nil) else super end end |
#having(opts = nil, *rest, &block) ⇒ Object
342 343 344 345 346 347 348 |
# File 'lib/active_record/refined.rb', line 342 def having(opts = nil, *rest, &block) if block super(evaluate_block(&block).to_arel(table, klass)) else super end end |
#joins(*args, as: nil, lateral: false, &block) ⇒ Object
as names the table within the query, which is what makes a self
join expressible: joins(:employees, as: :managers) { ... }.
lateral joins a relation instead of a table, and lets it see the row
being joined to -- the top few rows of each group, and the like.
451 452 453 454 455 456 457 458 459 460 |
# File 'lib/active_record/refined.rb', line 451 def joins(*args, as: nil, lateral: false, &block) if lateral super(build_lateral_join(args.first, Arel::Nodes::InnerJoin, as, &block)) elsif block super(build_join_node(args.first, Arel::Nodes::InnerJoin, as, &block)) else reject_join_alias(as) super(*args, &block) end end |
#left_outer_joins(*args, as: nil, lateral: false, &block) ⇒ Object
462 463 464 465 466 467 468 469 470 471 |
# File 'lib/active_record/refined.rb', line 462 def left_outer_joins(*args, as: nil, lateral: false, &block) if lateral joins(build_lateral_join(args.first, Arel::Nodes::OuterJoin, as, &block)) elsif block joins(build_join_node(args.first, Arel::Nodes::OuterJoin, as, &block)) else reject_join_alias(as) super(*args, &block) end end |
#order(*args, &block) ⇒ Object
350 351 352 353 354 355 356 357 358 |
# File 'lib/active_record/refined.rb', line 350 def order(*args, &block) if block result = evaluate_block(&block) arel = Array(result).map {|node| to_arel_field(node) } super(*arel, &nil) else super end end |
#select(*fields, &block) ⇒ Object
332 333 334 335 336 337 338 339 340 |
# File 'lib/active_record/refined.rb', line 332 def select(*fields, &block) if block result = evaluate_block(&block) arel = Array(result).map {|node| to_arel_field(node) } super(*arel, &nil) else super end end |
#where(opts = nil, *rest, &block) ⇒ Object
324 325 326 327 328 329 330 |
# File 'lib/active_record/refined.rb', line 324 def where(opts = nil, *rest, &block) if block super(evaluate_block(&block).to_arel(table, klass)) else super end end |