active_windows 0.1.3 → 0.1.5
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/README.md +13 -0
- data/docs/REVIEW_AND_PLAN.md +2 -0
- data/lib/active_windows/active_record_extensions.rb +29 -6
- data/lib/active_windows/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 03e84e2dfa5e33f68986b9d63c7875e490ceaaab2f8e1a50a9974c42f883d1b5
|
|
4
|
+
data.tar.gz: e2565adc58e0a2ccc236970baa804ede27522ce6d3688131bc5a23554cde71e1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 375915ceb4ff9845df08d952bf6e6e48f9e46e07ae4a7857dbca78ea698b7f5025ee634254fd5d8d03c7a7810df4c5ece16406864b4feba8604d7ce98b336770
|
|
7
|
+
data.tar.gz: 0c4df8c117ab1f49b08bb16f3e7573d2600339ff26bc64bea6f2d42aa3ae5e419ebd4c33e8c833f8e057d919f10ebaf6f0f1713e0077603fb40d5e6cb6b5da93
|
data/README.md
CHANGED
|
@@ -84,6 +84,19 @@ Available options:
|
|
|
84
84
|
| `:frame` | `String` | Raw SQL frame clause (e.g. `"ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING"`) |
|
|
85
85
|
| `:value` | `Symbol`, `String`, `Array` | Expression(s) passed as function arguments |
|
|
86
86
|
|
|
87
|
+
### Association Names
|
|
88
|
+
|
|
89
|
+
You can use `belongs_to` association names instead of foreign key columns. ActiveWindows automatically resolves them:
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
# These are equivalent:
|
|
93
|
+
Order.row_number.partition_by(:user).window_order(:amount).as(:rn)
|
|
94
|
+
Order.row_number.partition_by(:user_id).window_order(:amount).as(:rn)
|
|
95
|
+
|
|
96
|
+
# Works in the hash API too:
|
|
97
|
+
Order.window(row_number: { partition: :user, order: :amount, as: :rn })
|
|
98
|
+
```
|
|
99
|
+
|
|
87
100
|
### Chaining with ActiveRecord
|
|
88
101
|
|
|
89
102
|
Window functions integrate naturally with standard ActiveRecord methods:
|
data/docs/REVIEW_AND_PLAN.md
CHANGED
|
@@ -34,6 +34,8 @@ The gem provides a fluent DSL for SQL window functions in ActiveRecord. Core fun
|
|
|
34
34
|
- ~~**PostgreSQL CI**~~ — Added. GitHub Actions workflow tests against PostgreSQL 17 with service container.
|
|
35
35
|
- ~~**MySQL CI**~~ — Added. GitHub Actions workflow tests against MySQL 8.0 with service container.
|
|
36
36
|
- ~~**MySQL compatibility**~~ — Fixed. Aliases now use `klass.connection.quote_column_name` to properly quote reserved words (e.g., `rank`) with backticks on MySQL and double quotes on PostgreSQL/SQLite. Test assertions use adapter-agnostic `q()` and `col()` helpers.
|
|
37
|
+
- ~~**WindowChain `order` naming collision**~~ — Fixed. Renamed to `window_order` to avoid conflict with ActiveRecord's `.order()`. WindowChain now delegates `.order()` to the relation for query-level ordering. Uses `method_missing` for full relation method coverage.
|
|
38
|
+
- ~~**Association name resolution**~~ — Added. `partition_by(:user)` automatically resolves to `user_id` via `belongs_to` reflection. Works in both fluent and hash APIs. 74 tests, 355 assertions.
|
|
37
39
|
|
|
38
40
|
---
|
|
39
41
|
|
|
@@ -44,11 +44,24 @@ module ActiveWindows
|
|
|
44
44
|
@relation.window(to_window_hash)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
# Delegate
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
# Delegate to the materialized relation so the chain is transparent.
|
|
48
|
+
# Explicit delegates for Ruby protocol methods that must be defined eagerly.
|
|
49
|
+
delegate :to_sql, :to_a, :to_ary, :inspect, to: :to_relation
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def method_missing(method, ...)
|
|
54
|
+
relation = to_relation
|
|
55
|
+
if relation.respond_to?(method)
|
|
56
|
+
relation.public_send(method, ...)
|
|
57
|
+
else
|
|
58
|
+
super
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def respond_to_missing?(method, include_private = false)
|
|
63
|
+
to_relation.respond_to?(method, include_private) || super
|
|
64
|
+
end
|
|
52
65
|
end
|
|
53
66
|
|
|
54
67
|
module QueryMethods
|
|
@@ -204,10 +217,20 @@ module ActiveWindows
|
|
|
204
217
|
if name.is_a?(Arel::Nodes::Node) || name.is_a?(Arel::Nodes::SqlLiteral)
|
|
205
218
|
name
|
|
206
219
|
else
|
|
207
|
-
klass.arel_table[name
|
|
220
|
+
klass.arel_table[resolve_column_name(name)]
|
|
208
221
|
end
|
|
209
222
|
end
|
|
210
223
|
|
|
224
|
+
def resolve_column_name(name)
|
|
225
|
+
name_sym = name.to_sym
|
|
226
|
+
return name_sym if klass.column_names.include?(name.to_s)
|
|
227
|
+
|
|
228
|
+
reflection = klass.reflect_on_association(name_sym)
|
|
229
|
+
return reflection.foreign_key.to_sym if reflection&.macro == :belongs_to
|
|
230
|
+
|
|
231
|
+
name_sym
|
|
232
|
+
end
|
|
233
|
+
|
|
211
234
|
def arel_order(expr)
|
|
212
235
|
case expr
|
|
213
236
|
when Arel::Nodes::Node, Arel::Nodes::SqlLiteral
|