Add regroup method

This commit is contained in:
Danielius 2023-01-14 12:08:46 +02:00
parent 25df7a28fe
commit cfc0144832
No known key found for this signature in database
GPG Key ID: F93C337D167445D9
6 changed files with 74 additions and 3 deletions

View File

@ -1,3 +1,14 @@
* Add `#regroup` query method as a short-hand for `.unscope(:group).group(fields)`
Example:
```ruby
Post.group(:title).regroup(:author)
# SELECT `posts`.`*` FROM `posts` GROUP BY `posts`.`author`
```
*Danielius Visockas*
* PostgreSQL adapter method `enable_extension` now allows parameter to be `[schema_name.]<extension_name>`
if the extension must be installed on another schema.

View File

@ -12,7 +12,7 @@ module ActiveRecord
:create_or_find_by, :create_or_find_by!,
:destroy_all, :delete_all, :update_all, :touch_all, :destroy_by, :delete_by,
:find_each, :find_in_batches, :in_batches,
:select, :reselect, :order, :in_order_of, :reorder, :group, :limit, :offset, :joins, :left_joins, :left_outer_joins,
:select, :reselect, :order, :regroup, :in_order_of, :reorder, :group, :limit, :offset, :joins, :left_joins, :left_outer_joins,
:where, :rewhere, :invert_where, :preload, :extract_associated, :eager_load, :includes, :from, :lock, :readonly,
:and, :or, :annotate, :optimizer_hints, :extending,
:having, :create_with, :distinct, :references, :none, :unscope, :merge, :except, :only,

View File

@ -446,6 +446,27 @@ module ActiveRecord
self
end
# Allows you to change a previously set group statement.
#
# Post.group(:title, :body)
# # SELECT `posts`.`*` FROM `posts` GROUP BY `posts`.`title`, `posts`.`body`
#
# Post.group(:title, :body).regroup(:title)
# # SELECT `posts`.`*` FROM `posts` GROUP BY `posts`.`title`
#
# This is short-hand for <tt>unscope(:group).group(fields)</tt>.
# Note that we're unscoping the entire group statement.
def regroup(*args)
check_if_method_has_arguments!(__callee__, args)
spawn.regroup!(*args)
end
# Same as #regroup but operates on relation in-place instead of copying.
def regroup!(*args) # :nodoc:
self.group_values = args
self
end
# Applies an <code>ORDER BY</code> clause to a query.
#
# #order accepts arguments in one of several formats.

View File

@ -135,6 +135,13 @@ module ActiveRecord
assert relation.skip_preloading_value
end
test "#regroup!" do
@relation = relation.group("foo")
assert relation.regroup!("bar").equal?(relation)
assert_equal ["bar"], relation.group_values
end
private
def relation
@relation ||= Relation.new(FakeKlass)

View File

@ -544,7 +544,7 @@ class RelationTest < ActiveRecord::TestCase
end
%w( references includes preload eager_load group order reorder reselect unscope
joins left_joins left_outer_joins optimizer_hints annotate ).each do |method|
joins left_joins left_outer_joins optimizer_hints annotate regroup ).each do |method|
class_eval <<~RUBY
def test_no_arguments_to_#{method}_raise_errors
error = assert_raises(ArgumentError) { Topic.#{method}() }

View File

@ -117,6 +117,7 @@ The methods are:
* [`references`][]
* [`reorder`][]
* [`reselect`][]
* [`regroup`][]
* [`reverse_order`][]
* [`select`][]
* [`where`][]
@ -155,6 +156,7 @@ The primary operation of `Model.find(options)` can be summarized as:
[`references`]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-references
[`reorder`]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-reorder
[`reselect`]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-reselect
[`regroup`]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-regroup
[`reverse_order`]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-reverse_order
[`select`]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-select
[`where`]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-where
@ -1122,7 +1124,37 @@ the SQL executed would be:
SELECT * FROM books WHERE out_of_print = 1 AND out_of_print = 0
```
[`rewhere`]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-rewhere
[`regroup`]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-regroup
### `regroup`
The [`regroup`][] method overrides an existing, named `group` condition. For example:
```ruby
Book.group(:author).regroup(:id)
```
The SQL that would be executed:
```sql
SELECT * FROM books GROUP BY id
```
If the `regroup` clause is not used, the group clauses are combined together:
```ruby
Book.group(:author).group(:id)
```
the SQL executed would be:
```sql
SELECT * FROM books GROUP BY author, id
```
[`regroup`]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-regroup
Null Relation
-------------