activerecord-refined 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/README.md +41 -172
- data/activerecord-refined.gemspec +2 -6
- data/docs/index.md +70 -0
- data/lib/activerecord-refined/version.rb +1 -1
- metadata +2 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 29722b871b0d5cbc7a8a35f201c2930f6e252419c0d4097a0f7476e2e5d57c7e
|
|
4
|
+
data.tar.gz: 24a324dcd539b4d8295c297256a8670bbd2359a7495f5c8506020ce4f681ad47
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 69ece64722eacc0223671ce291696f7d9dd3feb8714673b0b7e2971a52c5a188154f1b821cc626a87b1236565462a4516f1c19b2ccf7bc7c5b849e7340b56fcf
|
|
7
|
+
data.tar.gz: 2ee8961a088d820e546e9cffe98e0ac836e8fb191b8120beebaa15bcc9e5b11ce8b88a1edccdc0580a12448aa0203a1631bd10bba905dc9ccdc066c6b6d24695
|
data/.yardopts
CHANGED
data/README.md
CHANGED
|
@@ -14,42 +14,22 @@ Author.
|
|
|
14
14
|
# WHERE "authors"."age" BETWEEN 20 AND 40 AND "posts"."published" = TRUE
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
Inside a block, symbols denote columns of the receiver's table, and
|
|
18
|
+
`:table[:column]` denotes a qualified column. That holds in every position —
|
|
19
|
+
on the right of a comparison too, so `:age == :retirement_age` compares two
|
|
20
|
+
columns. A value is written as its literal, an enum's as its string; a symbol
|
|
21
|
+
naming no column of the model is refused rather than compared against nothing
|
|
22
|
+
anyone meant.
|
|
23
|
+
|
|
17
24
|
**[Try it in your browser](https://shugo.github.io/activerecord-refined/)** —
|
|
18
25
|
Ruby 4.1, Active Record, SQLite and PostgreSQL run in the page, so the examples
|
|
19
26
|
build real SQL and return real rows without a `ruby-master` build of your own.
|
|
20
27
|
|
|
21
|
-
## History
|
|
22
|
-
|
|
23
|
-
This gem was formerly known as **activerecord-refinements**, created by Akira Matsuda
|
|
24
|
-
to experiment with the initial implementation of Ruby 2.0 Refinements. Because of the
|
|
25
|
-
Refinements' spec change, that implementation stopped working on Ruby 2.0.0 stable, and
|
|
26
|
-
the project was left dormant for a long time.
|
|
27
|
-
|
|
28
|
-
It has now been renamed to **activerecord-refined** and reimplemented on top of
|
|
29
|
-
[`Proc#refined`](https://docs.ruby-lang.org/en/master/Proc.html#method-i-refined),
|
|
30
|
-
which will be introduced in Ruby 4.1. `Proc#refined` returns a new proc that
|
|
31
|
-
is evaluated with the given refinements activated, so a block written by the caller can
|
|
32
|
-
be re-interpreted under the query DSL's refinements:
|
|
33
|
-
|
|
34
|
-
```ruby
|
|
35
|
-
def evaluate_block(&block)
|
|
36
|
-
refined_block = block.refined(ActiveRecord::Refined::BlockSyntax)
|
|
37
|
-
BlockContext.new.instance_exec(&refined_block)
|
|
38
|
-
end
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
This is exactly what the old implementation needed and could not do, so the query syntax
|
|
42
|
-
works again without monkey-patching `Symbol` globally.
|
|
43
|
-
|
|
44
28
|
## Requirements
|
|
45
29
|
|
|
46
30
|
* Ruby 4.1 or later (for `Proc#refined`; not released yet, so a `ruby-master` build is needed for now)
|
|
47
31
|
* Active Record 7.0 or later
|
|
48
32
|
|
|
49
|
-
The [sandbox](https://shugo.github.io/activerecord-refined/) is there to skip
|
|
50
|
-
that build: it carries its own Ruby 4.1. `sandbox/` in this repository is what
|
|
51
|
-
it is made of.
|
|
52
|
-
|
|
53
33
|
## Installation
|
|
54
34
|
|
|
55
35
|
Add this line to your application's Gemfile:
|
|
@@ -66,152 +46,26 @@ Or install it yourself as:
|
|
|
66
46
|
|
|
67
47
|
## Usage
|
|
68
48
|
|
|
69
|
-
|
|
70
|
-
|
|
49
|
+
With Bundler — a Rails application — there is nothing to write: the gem in
|
|
50
|
+
the Gemfile is loaded, and `where`, `select`, `joins`, `left_outer_joins`,
|
|
51
|
+
`having`, `order` and `group` accept a block. Elsewhere, require it:
|
|
71
52
|
|
|
72
53
|
```ruby
|
|
73
54
|
require "activerecord-refined"
|
|
74
55
|
```
|
|
75
56
|
|
|
76
|
-
|
|
77
|
-
denotes a qualified column. That holds in every position — on the right of a
|
|
78
|
-
comparison too, so `:age == :retirement_age` compares two columns. A value is
|
|
79
|
-
written as its literal, an enum's as its string; a symbol naming no column of
|
|
80
|
-
the model is refused rather than compared against nothing anyone meant.
|
|
81
|
-
|
|
82
|
-
The reference — every method a symbol answers to inside a block, every
|
|
83
|
-
function a block can call, and what the relation takes — is on
|
|
84
|
-
[rubydoc.info](https://rubydoc.info/gems/activerecord-refined):
|
|
85
|
-
[`BlockSyntax`](https://rubydoc.info/gems/activerecord-refined/ActiveRecord/Refined/BlockSyntax)
|
|
86
|
-
for the symbol,
|
|
87
|
-
[`BlockContext`](https://rubydoc.info/gems/activerecord-refined/ActiveRecord/Refined/BlockContext)
|
|
88
|
-
for the block, and
|
|
89
|
-
[`QueryMethods`](https://rubydoc.info/gems/activerecord-refined/ActiveRecord/Refined/QueryMethods)
|
|
90
|
-
for the relation. What follows is a tour, a topic at a time; each has a page
|
|
91
|
-
of its own under [docs/](docs/) that says the rest.
|
|
92
|
-
|
|
93
|
-
### Conditions
|
|
94
|
-
|
|
95
|
-
```ruby
|
|
96
|
-
Author.where { :age.between?(20, 40) & :name.like?("A%") }
|
|
97
|
-
Author.where { :country.in?(%w[JP US]) | :country.null? }
|
|
98
|
-
Author.where { !:name.start_with?("A") }
|
|
99
|
-
Author.where { :id.in?(Post.select(:author_id)) } # IN (subquery)
|
|
100
|
-
Author.where { exists?(Post.where { :posts[:author_id] == :authors[:id] }) }
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
`&`, `|` and `!` are AND, OR and NOT. A value on the right is quoted as Active
|
|
104
|
-
Record quotes it, a column compares against a column, a relation is a
|
|
105
|
-
subquery. [docs/conditions.md](docs/conditions.md) has the rest: the
|
|
106
|
-
negations SQL spells for itself, `true?` and NULL, regular expressions,
|
|
107
|
-
`ANY` and `ALL`, PostgreSQL arrays.
|
|
108
|
-
|
|
109
|
-
### Joins
|
|
110
|
-
|
|
111
|
-
```ruby
|
|
112
|
-
Author.joins(:posts) { :posts[:author_id] == :authors[:id] }
|
|
113
|
-
Employee.joins(:employees, as: :managers) { :managers[:id] == :employees[:manager_id] }
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
`joins`, `left_outer_joins`, `right_outer_joins`, `full_outer_joins` and
|
|
117
|
-
`cross_joins` take the `ON` as a block and `as:` for a table alias; a
|
|
118
|
-
relation joins as a subquery, and one marked `lateral` as a `LATERAL` one.
|
|
119
|
-
[docs/joins.md](docs/joins.md).
|
|
120
|
-
|
|
121
|
-
### Aggregates and functions
|
|
122
|
-
|
|
123
|
-
```ruby
|
|
124
|
-
Author.group { :country }.having { count(:*) > 1 }
|
|
125
|
-
Author.select { [count(:*).filter { :age < 50 }.as(:young), avg(:age).as(:average)] }
|
|
126
|
-
Post.group { :author_id }.select { string_agg(:title, ", ").order(:title).as(:titles) }
|
|
127
|
-
Post.where { :created_at > current_timestamp - 7.days }
|
|
128
|
-
Post.select { cast(:price, "decimal(10,2)").as(:price) }
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
The scalar functions are methods — `upper`, `coalesce`, `round` and the rest
|
|
132
|
-
— spelled the adapter's way where the adapters differ, and `fn` reaches any
|
|
133
|
-
other by name. [docs/functions.md](docs/functions.md).
|
|
134
|
-
|
|
135
|
-
### Expressions
|
|
136
|
-
|
|
137
|
-
```ruby
|
|
138
|
-
LineItem.where { :price * :quantity > 1000 }
|
|
139
|
-
Post.where { :flags & 4 > 0 }
|
|
140
|
-
Author.select { :country.when("JP").then("Japan").else("elsewhere").as(:where) }
|
|
141
|
-
Author.select { case_when { :age >= 60 }.then("senior").else("adult").as(:band) }
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
Arithmetic, the bitwise operators and `CASE` are expressions like a column,
|
|
145
|
-
so they compare, alias and aggregate. [docs/expressions.md](docs/expressions.md).
|
|
146
|
-
|
|
147
|
-
### JSON
|
|
148
|
-
|
|
149
|
-
```ruby
|
|
150
|
-
Doc.where { :meta.dig_text(:author, :name) == "alice" }
|
|
151
|
-
Doc.where { :meta.key?(:draft) }
|
|
152
|
-
Doc.update_all { { meta: :meta.bury(:author, :name, "alice") } }
|
|
153
|
-
Post.group { :author_id }.select { json_arrayagg(:title).as(:titles) }
|
|
154
|
-
```
|
|
57
|
+
## Documentation
|
|
155
58
|
|
|
156
|
-
|
|
157
|
-
document by the names Hash uses; `json_object` and `json_arrayagg` build one. The same block
|
|
158
|
-
runs on PostgreSQL's `jsonb`, MySQL's JSON and SQLite's.
|
|
159
|
-
[docs/json.md](docs/json.md).
|
|
59
|
+
https://rubydoc.info/gems/activerecord-refined/
|
|
160
60
|
|
|
161
|
-
|
|
61
|
+
## Adapters
|
|
162
62
|
|
|
163
|
-
|
|
164
|
-
Author.select { [:name, row_number.over.partition(:country).order(:age.desc).as(:rank)] }
|
|
165
|
-
Post.select { sum(:likes).over.order(:created_at).rows(..0).as(:running_total) }
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
`over` on any aggregate or window function, then `partition`, `order`,
|
|
169
|
-
`rows` and `range`. [docs/windows.md](docs/windows.md).
|
|
170
|
-
|
|
171
|
-
### Ordering, aliases and collation
|
|
172
|
-
|
|
173
|
-
```ruby
|
|
174
|
-
Author.order { :country.asc.nulls_last }
|
|
175
|
-
Author.select { upper(:name).as(:author) }
|
|
176
|
-
Author.where { :name.collate(:nocase) == "alice" }
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
[docs/ordering.md](docs/ordering.md).
|
|
180
|
-
|
|
181
|
-
### Grouping, CTEs and DISTINCT ON
|
|
182
|
-
|
|
183
|
-
```ruby
|
|
184
|
-
Sale.group { rollup(:region, :product) }
|
|
185
|
-
Post.distinct_on { :author_id }.order { [:author_id, :likes.desc] } # PostgreSQL
|
|
186
|
-
Node.with_recursive(tree: [Node.where { :id == 1 }, Node.joins(:tree) { :nodes[:parent_id] == :tree[:id] }]).from_cte(:tree)
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
[docs/grouping.md](docs/grouping.md) and [docs/ctes.md](docs/ctes.md).
|
|
190
|
-
|
|
191
|
-
### Writing
|
|
192
|
-
|
|
193
|
-
```ruby
|
|
194
|
-
Post.where { :published == true }.update_all { { likes: :likes + 1 } }
|
|
195
|
-
Tally.upsert_all(rows, unique_by: :page) { { hits: :hits + excluded(:hits) } }
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
[docs/writing.md](docs/writing.md).
|
|
199
|
-
|
|
200
|
-
### Time zones
|
|
201
|
-
|
|
202
|
-
Active Record stores in UTC and a `Time` in a block is quoted the way Active
|
|
203
|
-
Record quotes one, so `where { :created_at > Time.current - 1.day }` is right
|
|
204
|
-
whatever `Time.zone` is; what the database says the time is —
|
|
205
|
-
`current_timestamp`, `extract` — is the session's business.
|
|
206
|
-
[docs/time_zones.md](docs/time_zones.md).
|
|
207
|
-
|
|
208
|
-
## Other adapters
|
|
209
|
-
|
|
210
|
-
SQLite, PostgreSQL, MySQL, MariaDB, Oracle and SQL Server are built in: each
|
|
63
|
+
SQLite, PostgreSQL, MySQL, MariaDB, Oracle and SQL Server are supported: each
|
|
211
64
|
is a `Dialect`, one class per family of spellings, asked for whatever the
|
|
212
|
-
databases write differently
|
|
213
|
-
|
|
214
|
-
fall short, a dialect of
|
|
65
|
+
databases write differently, so that one block builds the right SQL on all
|
|
66
|
+
six. An adapter the gem does not know keeps the standard spellings, which
|
|
67
|
+
reach further than you might expect; where they fall short, a dialect of
|
|
68
|
+
your own says the rest. Subclass
|
|
215
69
|
`ActiveRecord::Refined::Dialect` — or the built-in family the database
|
|
216
70
|
descends from — override only what it spells differently, and register it
|
|
217
71
|
under the adapter's name:
|
|
@@ -278,6 +132,29 @@ once, as normal code is — building query blocks with a string `eval` mints
|
|
|
278
132
|
a fresh instruction sequence per pass, each earning a copy of its own, and
|
|
279
133
|
the memo keeps both alive for the life of the process.
|
|
280
134
|
|
|
135
|
+
## History
|
|
136
|
+
|
|
137
|
+
This gem was formerly known as **activerecord-refinements**, created by Akira Matsuda
|
|
138
|
+
to experiment with the initial implementation of Ruby 2.0 Refinements. Because of the
|
|
139
|
+
Refinements' spec change, that implementation stopped working on Ruby 2.0.0 stable, and
|
|
140
|
+
the project was left dormant for a long time.
|
|
141
|
+
|
|
142
|
+
It has now been renamed to **activerecord-refined** and reimplemented on top of
|
|
143
|
+
[`Proc#refined`](https://docs.ruby-lang.org/en/master/Proc.html#method-i-refined),
|
|
144
|
+
which will be introduced in Ruby 4.1. `Proc#refined` returns a new proc that
|
|
145
|
+
is evaluated with the given refinements activated, so a block written by the caller can
|
|
146
|
+
be re-interpreted under the query DSL's refinements:
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
def evaluate_block(&block)
|
|
150
|
+
refined_block = block.refined(ActiveRecord::Refined::BlockSyntax)
|
|
151
|
+
BlockContext.new.instance_exec(&refined_block)
|
|
152
|
+
end
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
This is exactly what the old implementation needed and could not do, so the query syntax
|
|
156
|
+
works again without monkey-patching `Symbol` globally.
|
|
157
|
+
|
|
281
158
|
## Running the tests
|
|
282
159
|
|
|
283
160
|
The tests only build SQL, but they need a live connection to do it. SQLite is
|
|
@@ -320,11 +197,3 @@ stored anywhere.
|
|
|
320
197
|
bundle exec bump patch --tag # or bump {major,minor} etc.
|
|
321
198
|
git push --follow-tags
|
|
322
199
|
```
|
|
323
|
-
|
|
324
|
-
## Contributing
|
|
325
|
-
|
|
326
|
-
1. Fork it
|
|
327
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
328
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
329
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
|
330
|
-
5. Create new Pull Request
|
|
@@ -42,11 +42,7 @@ Gem::Specification.new do |gem|
|
|
|
42
42
|
gem.add_development_dependency "rubocop-performance", [">= 0"]
|
|
43
43
|
gem.add_development_dependency "rubocop-rails", [">= 0"]
|
|
44
44
|
gem.add_development_dependency "rubocop-md", [">= 0"]
|
|
45
|
-
# What renders the reference: `yard server --reload` serves it locally,
|
|
46
|
-
# rubydoc.info renders the same .yardopts.
|
|
47
|
-
# relative links to docs/*.md -- which GitHub follows as they are -- into
|
|
48
|
-
# links to YARD's file pages; where it is not installed, rubydoc.info among
|
|
49
|
-
# them, YARD says so and leaves the links relative.
|
|
45
|
+
# What renders the reference: `yard server --reload` serves it locally,
|
|
46
|
+
# and rubydoc.info renders the same .yardopts.
|
|
50
47
|
gem.add_development_dependency "yard", [">= 0"]
|
|
51
|
-
gem.add_development_dependency "yard-markdown-relative-links", [">= 0"]
|
|
52
48
|
end
|
data/docs/index.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# ActiveRecord::Refined
|
|
2
|
+
|
|
3
|
+
Adding clean and powerful query syntax on Active Record using refinements.
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
Author.
|
|
7
|
+
joins(:posts) { :posts[:author_id] == :authors[:id] }.
|
|
8
|
+
where { :authors[:age].in?(20..40) & (:posts[:published] == true) }
|
|
9
|
+
# SELECT "authors".* FROM "authors"
|
|
10
|
+
# INNER JOIN "posts" ON "posts"."author_id" = "authors"."id"
|
|
11
|
+
# WHERE "authors"."age" BETWEEN 20 AND 40 AND "posts"."published" = TRUE
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Inside a block, symbols denote columns of the receiver's table, and
|
|
15
|
+
`:table[:column]` denotes a qualified column. That holds in every position —
|
|
16
|
+
on the right of a comparison too, so `:age == :retirement_age` compares two
|
|
17
|
+
columns. A value is written as its literal, an enum's as its string; a symbol
|
|
18
|
+
naming no column of the model is refused rather than compared against nothing
|
|
19
|
+
anyone meant.
|
|
20
|
+
|
|
21
|
+
**[Try it in your browser](https://shugo.github.io/activerecord-refined/)** —
|
|
22
|
+
Ruby 4.1, Active Record, SQLite and PostgreSQL run in the page, so the examples
|
|
23
|
+
build real SQL and return real rows without a `ruby-master` build of your own.
|
|
24
|
+
|
|
25
|
+
## Reference
|
|
26
|
+
|
|
27
|
+
- {ActiveRecord::Refined::BlockSyntax BlockSyntax} — what a symbol answers to
|
|
28
|
+
inside a block: `as`, `asc`, `desc`, `collate`, `[]`, and through it the
|
|
29
|
+
conditions of {ActiveRecord::Refined::AST::Predications Predications} and
|
|
30
|
+
the operators of {ActiveRecord::Refined::AST::Arithmetics Arithmetics}.
|
|
31
|
+
- {ActiveRecord::Refined::BlockContext BlockContext} — what a block can call:
|
|
32
|
+
the aggregates, the scalar and window functions, `CASE`, `sql`, `fn`.
|
|
33
|
+
- {ActiveRecord::Refined::QueryMethods QueryMethods} — what the relation
|
|
34
|
+
takes: the block forms of `where` and the rest, the joins, `from_cte`,
|
|
35
|
+
`distinct_on`, `lateral`.
|
|
36
|
+
- {ActiveRecord::Refined::Writes Writes} — `update_all` and `upsert_all` with
|
|
37
|
+
a block.
|
|
38
|
+
- {ActiveRecord::Refined::Dialect Dialect} — one class per family of SQL
|
|
39
|
+
spellings, and `register` for an adapter of your own.
|
|
40
|
+
|
|
41
|
+
## Guides
|
|
42
|
+
|
|
43
|
+
One topic at a time, each with the SQL it builds and where the adapters
|
|
44
|
+
differ:
|
|
45
|
+
|
|
46
|
+
- {file:docs/conditions.md Conditions} — comparisons, `LIKE`, `IN`, `NULL`,
|
|
47
|
+
`true?`, regular expressions, subqueries, `ANY` and `ALL`, arrays.
|
|
48
|
+
- {file:docs/joins.md Joins} — the `ON` as a block, table aliases, subqueries
|
|
49
|
+
and `LATERAL`.
|
|
50
|
+
- {file:docs/functions.md Aggregates and functions} — `count`, `filter`,
|
|
51
|
+
`string_agg`, the scalar functions, the clock, durations, `extract` and
|
|
52
|
+
`cast`.
|
|
53
|
+
- {file:docs/expressions.md Expressions} — arithmetic, the bitwise operators,
|
|
54
|
+
`CASE`.
|
|
55
|
+
- {file:docs/json.md JSON} — `dig`, `bury`, `except`, `key?`, `keys`, the
|
|
56
|
+
JSON aggregates, and where the adapters' JSON types part.
|
|
57
|
+
- {file:docs/windows.md Window functions} — `over`, `partition`, `order`,
|
|
58
|
+
frames.
|
|
59
|
+
- {file:docs/ordering.md Aliases, ordering and collation}
|
|
60
|
+
- {file:docs/grouping.md Grouping} — `DISTINCT ON`, `GROUPING SETS`,
|
|
61
|
+
`ROLLUP`, `CUBE`.
|
|
62
|
+
- {file:docs/ctes.md Common table expressions} — `with_recursive` and
|
|
63
|
+
`from_cte`.
|
|
64
|
+
- {file:docs/writing.md Writing} — `update_all` and `upsert_all`.
|
|
65
|
+
- {file:docs/time_zones.md Time zones} — what a block converts and what it
|
|
66
|
+
leaves to the session.
|
|
67
|
+
|
|
68
|
+
The repository's README, on
|
|
69
|
+
[GitHub](https://github.com/shugo/activerecord-refined), has the history,
|
|
70
|
+
the requirements, and how the tests and the release are run.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-refined
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.10.
|
|
4
|
+
version: 0.10.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shugo Maeda
|
|
@@ -233,22 +233,6 @@ dependencies:
|
|
|
233
233
|
- ">="
|
|
234
234
|
- !ruby/object:Gem::Version
|
|
235
235
|
version: "0"
|
|
236
|
-
- !ruby/object:Gem::Dependency
|
|
237
|
-
name: yard-markdown-relative-links
|
|
238
|
-
requirement: !ruby/object:Gem::Requirement
|
|
239
|
-
requirements:
|
|
240
|
-
-
|
|
241
|
-
- ">="
|
|
242
|
-
- !ruby/object:Gem::Version
|
|
243
|
-
version: "0"
|
|
244
|
-
type: :development
|
|
245
|
-
prerelease: false
|
|
246
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
247
|
-
requirements:
|
|
248
|
-
-
|
|
249
|
-
- ">="
|
|
250
|
-
- !ruby/object:Gem::Version
|
|
251
|
-
version: "0"
|
|
252
236
|
description: Adding clean and powerful query syntax on Active Record using refinements
|
|
253
237
|
email:
|
|
254
238
|
- shugo@ruby-lang.org
|
|
@@ -265,6 +249,7 @@ files:
|
|
|
265
249
|
- docs/expressions.md
|
|
266
250
|
- docs/functions.md
|
|
267
251
|
- docs/grouping.md
|
|
252
|
+
- docs/index.md
|
|
268
253
|
- docs/joins.md
|
|
269
254
|
- docs/json.md
|
|
270
255
|
- docs/ordering.md
|