Modernize for Ruby 3.1+, Rails 6.1+, Faraday 2.x#554
Open
voltechs wants to merge 31 commits intoremi:masterfrom
Open
Modernize for Ruby 3.1+, Rails 6.1+, Faraday 2.x#554voltechs wants to merge 31 commits intoremi:masterfrom
voltechs wants to merge 31 commits intoremi:masterfrom
Conversation
- Require Ruby >= 3.1, ActiveModel >= 6.1, Faraday >= 2.0 - Replace Travis CI with GitHub Actions (Ruby 3.1/3.2/3.3 × AM 6.1–8.0) - Remove multi_json dependency in favor of stdlib JSON - Drop ancient dev deps (json ~> 1.8, rake ~> 10.0) - Clean up Gemfile Ruby 1.9.3 conditional logic
- AssociationProxy: inherit from BasicObject instead of removed ActiveSupport::ProxyObject/BasicObject, add explicit proxy methods for ==, class, inspect, nil?, etc. - ParseJSON middleware: Faraday::Response::Middleware → Faraday::Middleware - Replace MultiJson.load/dump with stdlib JSON.parse/generate
Ref: remi#551 - functionnality → functionality - corrsponding → corresponding - substracts → subtracts - embeded_params → embedded_params - immediatly → immediately
Ref: remi#540 Route has_many fetches through get_collection instead of get, and guard instantiate_collection against blank response data. This prevents crashes when an API returns 204 No Content for an association endpoint.
Ref: remi#292 When fetching has_many associations, set the inverse parent through the association's cached_result rather than injecting it directly into the child's attributes hash. This prevents the parent object from appearing as a serializable attribute on child records.
Ref: remi#473 Drop the memoized setter_method_names Set in favor of a respond_to_without_missing? method that checks for real setter methods without triggering method_missing. This avoids stale cache issues and simplifies the setter detection logic.
Ref: remi#412 Short-circuit to an empty Her::Collection when any query parameter is an empty array, avoiding a pointless HTTP request that would return all records instead of none.
Ref: remi#360 Closes: remi#353 Resolve JSON API relationships against included resources in the JsonApiParser middleware. When a response contains both `relationships` and `included` keys, the parser matches resource linkages by type+id and merges the resolved data into each resource's attributes, enabling has_many/belongs_to associations to be populated without additional HTTP requests.
Closes: remi#355 Add initialize_copy to deep-dup the attributes hash, metadata, and response_errors so that modifying a dup'd or clone'd model does not mutate the original.
Closes: remi#494 Replace the id.nil? check in new?/persisted? with an explicit @_her_new_record flag. This correctly handles models initialized with a pre-assigned id (e.g. User.new(id: 5)) which should still be considered new/unpersisted until saved.
Closes: remi#176 When saving a new record, use the collection path instead of the resource path so that Model.create(id: '1234') correctly POSTs to /models rather than /models/1234. This was made possible by the explicit new record tracking from the previous commit.
Closes: remi#288 has_many#build now respects the foreign_key option instead of always inferring it from the parent's class name. This fixes cases like has_many :articles, foreign_key: :creator_id where the foreign key differs from convention.
Closes: remi#145 When API response data contains a key named "attributes", it collides with ActiveModel's internal attributes method, causing a crash during initialization. Filter reserved keys before calling respond_to_without_missing? to prevent the collision.
Centralizes the foreign key lookup (respecting :foreign_key option with convention fallback) in Association#foreign_key, replacing duplicated inline logic in has_many and has_one build methods.
Closes: remi#396 Symbolize keys on parsed_data when it enters the model layer so that custom middleware or caching layers (e.g. faraday-http-cache) that return string-keyed hashes work correctly.
Closes: remi#517 Remove duplicate run_callbacks :find in Relation#find since instantiate_record already triggers the :find callback. This was causing after_find hooks to execute twice per find.
Closes: remi#406 Use thread-local tracking in inspect to detect and truncate cyclic references with "..." instead of infinitely recursing through bidirectional associations.
Closes: remi#212, remi#469 In active_model_serializers format, only treat the response as a collection when the parsed data contains the pluralized root key. This prevents has_one and belongs_to associations from being incorrectly parsed as collections, which returned [] instead of the expected single resource.
Closes: remi#286 When creating a resource through a has_many association that already has fetched data, append to the cached collection rather than only checking @parent.attributes. This ensures the new resource is visible immediately without a refetch.
Closes: remi#272 When send_only_modified_attributes is enabled and to_params is called without changes (e.g. custom_post actions), don't strip all attributes. Only apply the filter when there are actual tracked changes to slice by.
- Remove DeprecatedMethods module (data/data=/assign_data/has_data?/ get_data/has_relationship?/get_relationship/relationships/her_api) — deprecated for 10+ years with no removal timeline - Remove deprecated options Hash support for custom_get/custom_post etc. (TODO said "remove after January 2020") - Replace (class << self; self; end) with singleton_class - Remove stale TODO comment from has_many#build
Closes: remi#287 has_many#build now appends the new resource to the cached collection so it's immediately visible via the association. If create fails (save returns false), the resource is removed from the collection.
Closes: remi#278 Override select, reject, map, and other Array methods on Her::Collection to return Collection instances that retain metadata and errors, instead of plain Arrays that lose this context.
- Remove dead badges (Travis, Gemnasium, CodeClimate, Gitter) - Update Faraday examples for 2.x (adapter syntax, middleware class) - Replace MultiJson with JSON in custom parser example - Update before_filter to before_action - Update BasicAuthentication to Faraday 2.x request syntax - Remove deprecated update_attributes from examples - Remove dead links (her-rb.org, rdoc.info, her-example repo) - Remove stale project list, history, and contributors sections - Update copyright years and add contributor copyright
Remove RuboCop 0.54 config (2018) and todo file in favor of Qlty with actionlint, markdownlint, trivy, trufflehog, and yamllint.
Author
|
Hey @remi, hope you're well. I took the liberty of addressing the majority of the issues. I see the project has been mostly stagnant for over five years now... Let me know if you want to discuss ownership/maintenance transfer if you're burnt out or no longer interested in the project. I've personally been a huge fan of it for about a decade now. |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Comprehensive modernization of Her for current Ruby/Rails ecosystem, with 30+ bug fixes from open issues.
multi_jsonin favor of stdlibJSONdata,assign_data,update_attributes, etc.)Bug fixes
BasicObjectinstead of removedActiveSupport::ProxyObject(remove deprecated ActiveSupport::ProxyObject #552)Faraday::Response::Middleware→Faraday::Middlewareattribute_changed_in_place?: enablesvalidates_numericality_of(NumericalityValidator support for activemodel #382, Implemented attribute_changed_in_place? on models so validates_numericality_of validation will work #383)classandattributesno longer crash when present in API data (Orm#save fails if an attribute "class" is present #371, Problem when an json object has an attribute called "attributes" #145)dup/clone: no longer share mutable state between copies (dupandclonedoesn't work on Her::Models #355)new?/persisted?: track record state explicitly instead of checkingid.nil?(primary_key and dirty tracking #494)build/create: append to existing collection, respectforeign_keyoption (creating resource on association #286, building resource on association #287, has_many build does not use declared foreign_key #288)after_findcalled twice: removed duplicate callback trigger (after_find called twice #517)inspectrecursion: cycle detection for circular associations (Calling inspect with associated objects results in recursion and unnecessarily long display output. #406)parsed_data: symbolize keys from caching middleware (Her::Model::Attributes.initialize_collection does not accept string keys #396)send_only_modified_attributes: no longer wipes all params on custom actions (Collection requests should ignore send_only_modified_attributes #272)parse_root_in_json true: now unwraps collection root without requiring AMS format (parse_root_in_json true, but not in active_model_serializers_format or json_api_format problems #380, Can't parse root with parse_root_in_json #331)Collection#select/map/etc.: preserve Collection type with metadata (Her::Collection send :select does not work #278)where(:foo => []): returns empty collection without HTTP request (Return an empty collection when where(:foo => []) is given #412)respond_to_without_missing?replaces stale cache (Drop the setter methods cache in favour of respond_to? (see #472) #473)Features
relationships+includedin JsonApiParser (Support for JSON API's Compound Documents #353, Feature/jsonapi compound documents #360)Cleanup
embeded_params→embedded_params, etc.) (Fix typos #551)(class << self; self; end)withsingleton_classAssociation#foreign_keyhelperTest plan
bundle exec rake specpasses (400 examples, 0 failures)