Skip to content

Commit

Permalink
V0.11 refactor resource classes to modules (#1406)
Browse files Browse the repository at this point in the history
* Restore previous include directives behavior

* Default sort use _primary_key

* Remove support for pluck attributes

* Pass relationship instead of relationship name

* Update copyright date

* Ignore docker-compose override files

* add _relation_name method

* Rework resource class to support using modules for retrieving resources by way of a `resource_retrieval_strategy`

Removes BasicResource class and replaces ActiveRelationResource with a module

* Use `_relationship` helper method

* Add ActiveRelationRetrieval

Allows retrieval of resources by querying the primary table and joining the source table - the opposite of the v10 version

* Skip extra pluck queries when not caching a resource

* Test Cleanup

* Adjust tested query counts based on default_resource_retrieval_strategy

* create_implicit_polymorphic_type_relationships

* Add ActiveRelationRetrievalV09

* Move resource down in the load order

* Use underscore instead of downcase

* Refactor Resource to load retrieval strategy as class loads

* Simplify loading resource retrieval strategy modules

Add SimpleResource that does not load a resource retrieval strategy module

* Remove no longer need deferred_relationship code

* Add warning about potentially unused `records_for_populate`

* Rework loading the resource_retrieval_strategy to fix issue in real projects

* Use SortedSets for resource_identities

* Add sorted_set gem

* Remove rails 5 support
  • Loading branch information
lgebhardt authored Sep 19, 2023
1 parent 3cd93a2 commit a2fc02f
Show file tree
Hide file tree
Showing 42 changed files with 5,690 additions and 3,056 deletions.
14 changes: 0 additions & 14 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,35 +47,21 @@ jobs:
- '7.0'
- '6.1'
- '6.0'
- '5.2'
- '5.1'
database_url:
- sqlite3:test_db
- postgresql://postgres:password@localhost:5432/test
- mysql2://root:[email protected]:3306/test
exclude:
- ruby: '3.2'
rails: '6.0'
- ruby: '3.2'
rails: '5.2'
- ruby: '3.2'
rails: '5.1'
- ruby: '3.1'
rails: '6.0'
- ruby: '3.1'
rails: '5.2'
- ruby: '3.1'
rails: '5.1'
- ruby: '3.0'
rails: '6.0'
- ruby: '3.0'
rails: '5.2'
- ruby: '3.0'
rails: '5.1'
- ruby: '2.6'
rails: '7.0'
- database_url: postgresql://postgres:password@localhost:5432/test
rails: '5.1'
env:
RAILS_VERSION: ${{ matrix.rails }}
DATABASE_URL: ${{ matrix.database_url }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ test_db
test_db-journal
.idea
*.iml
*.override.yml
2 changes: 1 addition & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2014-2021 Cerebris Corporation
Copyright (c) 2014-2023 Cerebris Corporation

MIT License

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,4 @@ and **paste the content into the issue description or attach as a file**:

## License

Copyright 2014-2021 Cerebris Corporation. MIT License (see LICENSE for details).
Copyright 2014-2023 Cerebris Corporation. MIT License (see LICENSE for details).
2 changes: 2 additions & 0 deletions jsonapi-resources.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'pry'
spec.add_development_dependency 'concurrent-ruby-ext'
spec.add_development_dependency 'database_cleaner'
spec.add_development_dependency 'hashie'
spec.add_dependency 'activerecord', '>= 5.1'
spec.add_dependency 'railties', '>= 5.1'
spec.add_dependency 'concurrent-ruby'
spec.add_dependency 'sorted_set'
end
8 changes: 6 additions & 2 deletions lib/jsonapi-resources.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
require 'jsonapi/resources/railtie'
require 'jsonapi/naive_cache'
require 'jsonapi/compiled_json'
require 'jsonapi/basic_resource'
require 'jsonapi/active_relation_resource'
require 'jsonapi/active_relation_retrieval'
require 'jsonapi/active_relation_retrieval_v09'
require 'jsonapi/active_relation_retrieval_v10'
require 'jsonapi/resource_common'
require 'jsonapi/resource'
require 'jsonapi/simple_resource'
require 'jsonapi/cached_response_fragment'
require 'jsonapi/response_document'
require 'jsonapi/acts_as_resource_controller'
Expand Down Expand Up @@ -35,6 +38,7 @@
require 'jsonapi/link_builder'
require 'jsonapi/active_relation/adapters/join_left_active_record_adapter'
require 'jsonapi/active_relation/join_manager'
require 'jsonapi/active_relation/join_manager_v10'
require 'jsonapi/resource_identity'
require 'jsonapi/resource_fragment'
require 'jsonapi/resource_tree'
Expand Down
38 changes: 27 additions & 11 deletions lib/jsonapi/active_relation/join_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,22 @@ class JoinManager
attr_reader :resource_klass,
:source_relationship,
:resource_join_tree,
:join_details
:join_details,
:through_source

def initialize(resource_klass:,
source_relationship: nil,
source_resource_klass: nil,
through_source: false,
relationships: nil,
filters: nil,
sort_criteria: nil)

@resource_klass = resource_klass
@source_resource_klass = source_resource_klass
@join_details = nil
@collected_aliases = Set.new
@through_source = through_source

@resource_join_tree = {
root: {
Expand Down Expand Up @@ -45,7 +50,7 @@ def join(records, options)
# this method gets the join details whether they are on a relationship or are just pseudo details for the base
# resource. Specify the resource type for polymorphic relationships
#
def source_join_details(type=nil)
def source_join_details(type = nil)
if source_relationship
related_resource_klass = type ? resource_klass.resource_klass_for(type) : source_relationship.resource_klass
segment = PathSegment::Relationship.new(relationship: source_relationship, resource_klass: related_resource_klass)
Expand Down Expand Up @@ -90,14 +95,20 @@ def self.get_join_arel_node(records, options = {})
end

def self.alias_from_arel_node(node)
case node.left
# case node.left
case node&.left
when Arel::Table
node.left.name
when Arel::Nodes::TableAlias
node.left.right
when Arel::Nodes::StringJoin
# :nocov:
warn "alias_from_arel_node: Unsupported join type - use custom filtering and sorting"
warn "alias_from_arel_node: Unsupported join type `Arel::Nodes::StringJoin` - use custom filtering and sorting"
nil
# :nocov:
else
# :nocov:
warn "alias_from_arel_node: Unsupported join type `#{node&.left.to_s}`"
nil
# :nocov:
end
Expand Down Expand Up @@ -163,7 +174,8 @@ def perform_joins(records, options)
options: options)
}

details = {alias: self.class.alias_from_arel_node(join_node), join_type: join_type}
join_alias = self.class.alias_from_arel_node(join_node)
details = {alias: join_alias, join_type: join_type}

if relationship == source_relationship
if relationship.polymorphic? && relationship.belongs_to?
Expand All @@ -175,15 +187,19 @@ def perform_joins(records, options)

# We're adding the source alias with two keys. We only want the check for duplicate aliases once.
# See the note in `add_join_details`.
check_for_duplicate_alias = !(relationship == source_relationship)
add_join_details(PathSegment::Relationship.new(relationship: relationship, resource_klass: related_resource_klass), details, check_for_duplicate_alias)
check_for_duplicate_alias = relationship != source_relationship
path_segment = PathSegment::Relationship.new(relationship: relationship,
resource_klass: related_resource_klass)

add_join_details(path_segment, details, check_for_duplicate_alias)
end
end
records
end

def add_join(path, default_type = :inner, default_polymorphic_join_type = :left)
if source_relationship
# puts "add_join #{path} default_type=#{default_type} default_polymorphic_join_type=#{default_polymorphic_join_type}"
if source_relationship && through_source
if source_relationship.polymorphic?
# Polymorphic paths will come it with the resource_type as the first segment (for example `#documents.comments`)
# We just need to prepend the relationship portion the
Expand All @@ -195,9 +211,9 @@ def add_join(path, default_type = :inner, default_polymorphic_join_type = :left)
sourced_path = path
end

join_manager, _field = parse_path_to_tree(sourced_path, resource_klass, default_type, default_polymorphic_join_type)
join_tree, _field = parse_path_to_tree(sourced_path, resource_klass, default_type, default_polymorphic_join_type)

@resource_join_tree[:root].deep_merge!(join_manager) { |key, val, other_val|
@resource_join_tree[:root].deep_merge!(join_tree) { |key, val, other_val|
if key == :join_type
if val == other_val
val
Expand Down Expand Up @@ -294,4 +310,4 @@ def add_relationships(relationships)
end
end
end
end
end
Loading

0 comments on commit a2fc02f

Please sign in to comment.