coatepec 0.5.0 → 0.5.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/CHANGELOG.md +17 -0
- data/README.md +25 -0
- data/lib/coatepec/introspection/model.rb +41 -2
- data/lib/coatepec/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 161aafede82c7279701f75a51cc7976a6ef7bbbadff7bc22a7bc04dc050e1780
|
|
4
|
+
data.tar.gz: 2b867df0d495bb573e1e00ad9a94f9aca800fa7045bbf6965fb0825acfc2683f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d93777d12dac89c55450377259fc7d206bd6ef077766395f1397045372a58a7203bf986bbb9a525fc89b8510159a7fd9d0c3a057c321219edd95d6f23caa7acf
|
|
7
|
+
data.tar.gz: 3e580288a7c4ef9b0e707909967c28293ce8bc8b749e8c11d03903faef69ef80587c4a8307e13e769633d521b6245a05f806859d124a40346a9a0120b56e3e9b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.1
|
|
4
|
+
|
|
5
|
+
- Fix `rails_model` crashing outright for a model with a `has_one`/
|
|
6
|
+
`has_many :through` association that goes through a polymorphic
|
|
7
|
+
`belongs_to` (e.g. `has_one :x, through: :notable, source: :y` where
|
|
8
|
+
`belongs_to :notable, polymorphic: true`). `foreign_key` on that
|
|
9
|
+
reflection needs a single fixed class to resolve, which a polymorphic
|
|
10
|
+
association can't provide, and that was previously an unrescued
|
|
11
|
+
`ArgumentError` that took down the whole response. That specific case now
|
|
12
|
+
reports `foreign_key: nil`/`class_name: nil` for the affected association,
|
|
13
|
+
the same way an already-handled plain polymorphic `belongs_to` does.
|
|
14
|
+
- Add a general safety net around each association's metadata: if a single
|
|
15
|
+
association still fails for some other, not-yet-anticipated
|
|
16
|
+
`ActiveRecord` reflection quirk, only that association's entry degrades
|
|
17
|
+
(gaining an `error` field describing what went wrong) instead of the
|
|
18
|
+
entire `rails_model` call crashing for the whole model.
|
|
19
|
+
|
|
3
20
|
## 0.5.0
|
|
4
21
|
|
|
5
22
|
- **Breaking:** `mcp` is no longer a runtime dependency of the `coatepec`
|
data/README.md
CHANGED
|
@@ -130,6 +130,31 @@ a no-op.
|
|
|
130
130
|
| `rails_routes` | `query?`, `limit?` (1..200, default 50), `offset?` | Case-insensitive filter across name/verb/path/controller/action |
|
|
131
131
|
| `rails_model` | `name` (constant path, e.g. `Widget` or `Admin::Widget`) | ActiveRecord models only; columns, associations, validators, enums -- no row data |
|
|
132
132
|
|
|
133
|
+
### Example queries
|
|
134
|
+
|
|
135
|
+
`rails_routes`:
|
|
136
|
+
|
|
137
|
+
- "What are all the routes in this app?" -- `rails_routes()`
|
|
138
|
+
- "What's the URL for widgets?" -- `rails_routes(query: "widget")`. `query` is a
|
|
139
|
+
case-insensitive substring match across name, verb, path, controller, *and*
|
|
140
|
+
action -- not just the path -- so a resource name alone typically returns
|
|
141
|
+
every route for that resource (index/create/new/...); narrow further with
|
|
142
|
+
something like `query: "new_widget"` to hit one route by name.
|
|
143
|
+
- "Which routes accept POST?" -- `rails_routes(query: "POST")`, the same
|
|
144
|
+
substring match applied to the verb column.
|
|
145
|
+
|
|
146
|
+
`rails_model`:
|
|
147
|
+
|
|
148
|
+
- "What columns does Widget have, and which are nullable?" --
|
|
149
|
+
`rails_model(name: "Widget")` -- see `columns[].null`, `columns[].sql_type`,
|
|
150
|
+
`columns[].default`.
|
|
151
|
+
- "What validations and associations does Widget enforce?" -- same call --
|
|
152
|
+
see `validators` and `associations`.
|
|
153
|
+
- "What happens if I ask about a non-model class, like a controller?" --
|
|
154
|
+
`rails_model(name: "ApplicationController")` raises `not_active_record_model`
|
|
155
|
+
rather than introspecting it (a nonexistent constant raises `model_not_found`
|
|
156
|
+
instead) -- the tool only ever reflects on `ActiveRecord::Base` descendants.
|
|
157
|
+
|
|
133
158
|
The warm test worker forces Rails' reload-checking on for its own boot,
|
|
134
159
|
regardless of the target app's own `test.rb` setting (which disables it by
|
|
135
160
|
default) -- so editing a model file takes effect on the next tool call
|
|
@@ -93,7 +93,32 @@ module Coatepec
|
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
def associations_for(klass)
|
|
96
|
-
klass.reflect_on_all_associations.first(MAX_ITEMS).map { |assoc|
|
|
96
|
+
klass.reflect_on_all_associations.first(MAX_ITEMS).map { |assoc| safe_association_data(assoc) }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# build_association_data's own field-level rescues (association_class_name,
|
|
100
|
+
# association_foreign_key) cover every failure mode seen in practice so
|
|
101
|
+
# far, but ActiveRecord's reflection internals are large enough that
|
|
102
|
+
# betting the whole rails_model call on having anticipated all of them
|
|
103
|
+
# is optimistic -- a has_one/has_many :through a polymorphic belongs_to
|
|
104
|
+
# is exactly the kind of case that wasn't anticipated until it crashed
|
|
105
|
+
# this method outright (see association_foreign_key). This is the
|
|
106
|
+
# boundary of last resort: one association's introspection failing
|
|
107
|
+
# degrades just that entry instead of the whole model. It deliberately
|
|
108
|
+
# does not rescue StandardError -- a NoMethodError here is a genuine
|
|
109
|
+
# Coatepec bug (e.g. a typo), and letting that crash loudly beats
|
|
110
|
+
# silently reporting it as "this association is fine, no data".
|
|
111
|
+
def safe_association_data(assoc)
|
|
112
|
+
build_association_data(assoc)
|
|
113
|
+
rescue NameError, ArgumentError, ::ActiveRecord::ActiveRecordError => e
|
|
114
|
+
degraded_association_data(assoc, e)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def degraded_association_data(assoc, error)
|
|
118
|
+
{
|
|
119
|
+
name: assoc.name.to_s, macro: assoc.macro.to_s, class_name: nil, foreign_key: nil, through: nil,
|
|
120
|
+
polymorphic: nil, error: "#{error.class}: #{error.message}"
|
|
121
|
+
}
|
|
97
122
|
end
|
|
98
123
|
|
|
99
124
|
def build_association_data(assoc)
|
|
@@ -101,7 +126,7 @@ module Coatepec
|
|
|
101
126
|
name: assoc.name.to_s,
|
|
102
127
|
macro: assoc.macro.to_s,
|
|
103
128
|
class_name: association_class_name(assoc),
|
|
104
|
-
foreign_key: assoc
|
|
129
|
+
foreign_key: association_foreign_key(assoc),
|
|
105
130
|
through: assoc.through_reflection&.name&.to_s,
|
|
106
131
|
polymorphic: assoc.polymorphic? || false
|
|
107
132
|
}
|
|
@@ -120,6 +145,20 @@ module Coatepec
|
|
|
120
145
|
nil
|
|
121
146
|
end
|
|
122
147
|
|
|
148
|
+
# A has_one/has_many :through reflection whose `through:` target is
|
|
149
|
+
# itself a polymorphic belongs_to has no single fixed class either --
|
|
150
|
+
# ThroughReflection#foreign_key needs through_reflection.klass to find
|
|
151
|
+
# the source reflection, and .klass on a polymorphic reflection always
|
|
152
|
+
# raises ArgumentError (see association_class_name above). A dangling
|
|
153
|
+
# class_name on the reflection itself still raises NameError the same
|
|
154
|
+
# way. Report foreign_key: nil rather than letting either crash the
|
|
155
|
+
# call.
|
|
156
|
+
def association_foreign_key(assoc)
|
|
157
|
+
assoc.foreign_key.to_s
|
|
158
|
+
rescue NameError, ArgumentError
|
|
159
|
+
nil
|
|
160
|
+
end
|
|
161
|
+
|
|
123
162
|
def validators_for(klass)
|
|
124
163
|
klass.validators.first(MAX_ITEMS).map do |validator|
|
|
125
164
|
{
|
data/lib/coatepec/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: coatepec
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Enrique Mogollan
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-08-
|
|
10
|
+
date: 2026-08-07 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: railties
|