-
Notifications
You must be signed in to change notification settings - Fork 0
Adds separate configs for attributes and parameters #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
8b4f8d5
Adds separate configs for attributes and parameters
d-Pixie e2a113f
Updates README.md with new config structure
d-Pixie 137c784
Moves resolver defaults to parent module settings
d-Pixie df5b93c
Proxies old module setting to new config
d-Pixie 493f69c
Simplifies the memoized converter functions
d-Pixie 35d8512
Simplifies query param conversion logic
d-Pixie 545bf98
Drops the unused dry-inflector dependency
ehannes bab470f
Fixes Resource.get mutating caller-provided params hash
ehannes 786adaa
Stops re-propagating attribute_convention to conversions
ehannes 96abb3a
Preserves PascalCase as the default conversion
ehannes 42fdd74
Reconciles changelog wording on attribute_convention
ehannes df85a57
Drops converter memoisation and adds a parent-less fallback
ehannes 5437d3a
Cleans up after the conversions refactor
ehannes File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Changelog | ||
|
|
||
| ## [Unreleased] | ||
|
|
||
| ### Added | ||
|
|
||
| - **`conversions` configuration** with independent `query_parameters` and `json_attributes` sub-keys. This allows APIs that use different naming conventions for query parameters vs JSON body attributes to be configured correctly: | ||
|
|
||
| ```ruby | ||
| module MyAPI | ||
| extend RestEasy | ||
|
|
||
| configure do | ||
| conversions.json_attributes = :camelCase | ||
| conversions.query_parameters = :PascalCase | ||
| end | ||
| end | ||
| ``` | ||
|
|
||
| - **Automatic query parameter key transformation.** `Resource.get` now transforms parameter keys according to the `query_parameters` convention before sending the request. This removes the need for manual `transform_keys` calls in consuming gems. | ||
|
|
||
| - `conversions` can be overridden per Resource class, with inheritance falling back to the parent API module configuration. | ||
|
|
||
| ### Deprecated | ||
|
|
||
| - **`attribute_convention`** is deprecated in favour of `conversions.json_attributes`. The old setting continues to work — it is propagated to `conversions.json_attributes` at the module level and respected as a fallback at the resource level — but emits a deprecation warning in both cases. | ||
|
|
||
| ### Removed | ||
|
|
||
| - **`dry-inflector` runtime dependency.** The gem never used `Dry::Inflector` — Zeitwerk's own inflector is the only one used. | ||
| - **Default value for `attribute_convention`.** Previously defaulted to `:PascalCase`. The setting is now unset by default; reading `MyAPI::Settings.config.attribute_convention` directly returns `nil` unless explicitly configured. The effective default for naming conversion now lives on `conversions.json_attributes` (also `:PascalCase`). | ||
|
|
||
| ## [1.0.0] | ||
|
|
||
| Initial release. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,11 @@ class Resource | |
| setting :path | ||
| setting :debug, default: false | ||
|
|
||
| setting :conversions do | ||
| setting :query_parameters # nil default — falls back to parent module | ||
| setting :json_attributes # nil default — falls back to parent module | ||
| end | ||
|
|
||
| # ── Types ───────────────────────────────────────────────────────────── | ||
| # Include Types so the full Dry::Types vocabulary (Strict::String, | ||
| # Coercible::Integer, Params::Date, etc.) is available without prefix. | ||
|
|
@@ -143,16 +148,32 @@ def metadata(**kwargs) | |
| end | ||
| end | ||
|
|
||
| # -- attribute_convention ------------------------------------------ | ||
| # -- conversions --------------------------------------------------- | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happened with small single responsibility classes? This class is huge. Also I'm not a fan of these comments. If this is a separate concern in this class then it might be a sign that we can extract it to a separate class that we can test in isolation 😄 |
||
|
|
||
| def json_attribute_converter | ||
| Conventions.resolve( | ||
| config.conversions.json_attributes || | ||
| parent&.config&.conversions&.json_attributes || | ||
| Conventions::DEFAULT | ||
| ) | ||
| end | ||
|
|
||
| def query_parameter_converter | ||
| Conventions.resolve( | ||
| config.conversions.query_parameters || | ||
| parent&.config&.conversions&.query_parameters || | ||
| Conventions::DEFAULT | ||
| ) | ||
| end | ||
|
|
||
| # -- attribute_convention (deprecated) ------------------------------- | ||
|
|
||
| def attribute_convention(value = nil) | ||
| if value | ||
| @attribute_convention = Conventions.resolve(value) | ||
| else | ||
| @attribute_convention || | ||
| (superclass.respond_to?(:attribute_convention) ? superclass.attribute_convention : nil) || | ||
| Conventions.resolve(parent&.config&.attribute_convention || :PascalCase) | ||
| warn "RestEasy: attribute_convention is deprecated, use `configure { conversions.json_attributes = #{value.inspect} }` instead" | ||
| config.conversions.json_attributes = value | ||
| end | ||
| json_attribute_converter | ||
| end | ||
|
|
||
| private | ||
|
|
@@ -191,7 +212,7 @@ def attr(name_or_mapping, *args, &block) | |
| attribute_api_name = name_or_mapping[1].to_s | ||
| else | ||
| attribute_model_name = name_or_mapping.to_sym | ||
| attribute_api_name = attribute_convention.serialise(attribute_model_name) | ||
| attribute_api_name = json_attribute_converter.serialise(attribute_model_name) | ||
| end | ||
|
|
||
| # Extract type (non-Symbol), flags (Symbols), and optional mapper object | ||
|
|
@@ -459,7 +480,8 @@ def delete(id) | |
| # HTTP primitives — delegate to the parent API module's connection | ||
|
|
||
| def get(path:, params: {}, headers: {}) | ||
| parent.get(path:, params:, headers:) | ||
| converted_params = params.transform_keys { |k| query_parameter_converter.serialise(k) } | ||
| parent.get(path:, params: converted_params, headers:) | ||
| end | ||
|
|
||
| def post(path:, body: nil, headers: {}) | ||
|
|
@@ -578,7 +600,7 @@ def serialise | |
| serialised = attr_def.serialise_value(value) | ||
| if serialised.is_a?(::Array) | ||
| # Array return: zip with source field API names | ||
| convention = klass.attribute_convention | ||
| convention = klass.json_attribute_converter | ||
| attr_def.source_fields.zip(serialised).each do |field_name, field_value| | ||
| api_key = convention.serialise(field_name) | ||
| result[api_key] = field_value | ||
|
|
@@ -655,7 +677,7 @@ def init_from_api(api_data, extra_meta = {}) | |
| if attr_def.source_fields.any? | ||
| # Source fields declared via block params: extract individual | ||
| # values from api_data using convention, splat into parse block. | ||
| convention = klass.attribute_convention | ||
| convention = klass.json_attribute_converter | ||
| raw_values = attr_def.source_fields.map do |field_name| | ||
| api_key = convention.serialise(field_name) | ||
| api_data[api_key] | ||
|
|
@@ -678,7 +700,7 @@ def init_from_api(api_data, extra_meta = {}) | |
|
|
||
| if config.debug | ||
| # Warn about API fields that are neither declared attrs nor explicitly ignored | ||
| convention = klass.attribute_convention | ||
| convention = klass.json_attribute_converter | ||
| known_api_keys = klass.all_attribute_definitions.values.flat_map do |ad| | ||
| keys = [ad.api_name] | ||
| ad.source_fields.each { |sf| keys << convention.serialise(sf) } | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changelog says module-level
attribute_conventionis "silently supported" for backwards compatibility, butRestEasy.configurecurrently emits a deprecation warning when it seesattribute_conventionset. Either update the changelog wording or adjust the implementation to avoid warning at the module level (and only warn for resource-level usage).