Class: JsonapiCompliable::Sideload
- Inherits:
-
Object
- Object
- JsonapiCompliable::Sideload
- Defined in:
- lib/jsonapi_compliable/sideload.rb
Instance Attribute Summary collapse
-
#assign_proc ⇒ Proc
readonly
The configured 'assign' block.
-
#foreign_key ⇒ Symbol
readonly
The attribute used to match objects - need not be a true database foreign key.
-
#grouper ⇒ Proc
readonly
The configured 'group_by' proc.
-
#name ⇒ Symbol
readonly
The name of the sideload.
-
#polymorphic ⇒ Boolean
readonly
Is this a polymorphic sideload?.
-
#polymorphic_groups ⇒ Hash
readonly
The subgroups, when polymorphic.
-
#primary_key ⇒ Symbol
readonly
The attribute used to match objects - need not be a true database primary key.
-
#resource_class ⇒ Class
readonly
The corresponding Resource class.
-
#scope_proc ⇒ Proc
readonly
The configured 'scope' block.
-
#sideloads ⇒ Hash
readonly
The associated sibling sideloads.
-
#type ⇒ Symbol
readonly
One of :has_many, :belongs_to, etc.
Instance Method Summary collapse
-
#allow_sideload(name, opts = {}, &blk) ⇒ Object
Configure a relationship between Resource objects.
-
#assign {|parents, children| ... } ⇒ Object
The proc used to assign the resolved parents and children.
-
#associate(parent, child) ⇒ Object
Configure how to associate parent and child records.
-
#group_by(&grouper) ⇒ Object
Define a proc that groups the parent records.
-
#initialize(name, type: nil, resource: nil, polymorphic: false, primary_key: :id, foreign_key: nil) ⇒ Sideload
constructor
NB - the adapter's
#sideloading_moduleis mixed in on instantiation. -
#polymorphic? ⇒ Boolean
Is this sideload polymorphic?.
-
#resolve(parents, query, namespace = nil) ⇒ void
private
Resolve the sideload.
-
#resource ⇒ Resource
An instance of
#resource_class. -
#scope {|parents| ... } ⇒ Object
Build a scope that will be used to fetch the related records This scope will be further chained with filtering/sorting/etc.
-
#sideload(name) ⇒ Object
Fetch a Sideload object by its name.
-
#to_hash(processed = []) ⇒ Hash
private
Looks at all nested sideload, and all nested sideloads for the corresponding Resources, and returns an Include Directive hash.
Constructor Details
#initialize(name, type: nil, resource: nil, polymorphic: false, primary_key: :id, foreign_key: nil) ⇒ Sideload
NB - the adapter's #sideloading_module is mixed in on instantiation
An anonymous Resource will be assigned when none provided.
31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/jsonapi_compliable/sideload.rb', line 31 def initialize(name, type: nil, resource: nil, polymorphic: false, primary_key: :id, foreign_key: nil) @name = name @resource_class = (resource || Class.new(Resource)) @sideloads = {} @polymorphic = !!polymorphic @polymorphic_groups = {} if polymorphic? @primary_key = primary_key @foreign_key = foreign_key @type = type extend @resource_class.config[:adapter].sideloading_module end |
Instance Attribute Details
#assign_proc ⇒ Proc (readonly)
The configured 'assign' block
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def assign_proc @assign_proc end |
#foreign_key ⇒ Symbol (readonly)
The attribute used to match objects - need not be a true database foreign key.
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def foreign_key @foreign_key end |
#grouper ⇒ Proc (readonly)
The configured 'group_by' proc
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def grouper @grouper end |
#name ⇒ Symbol (readonly)
The name of the sideload
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def name @name end |
#polymorphic ⇒ Boolean (readonly)
Is this a polymorphic sideload?
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def polymorphic @polymorphic end |
#polymorphic_groups ⇒ Hash (readonly)
The subgroups, when polymorphic
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def polymorphic_groups @polymorphic_groups end |
#primary_key ⇒ Symbol (readonly)
The attribute used to match objects - need not be a true database primary key.
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def primary_key @primary_key end |
#resource_class ⇒ Class (readonly)
The corresponding Resource class
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def resource_class @resource_class end |
#scope_proc ⇒ Proc (readonly)
The configured 'scope' block
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def scope_proc @scope_proc end |
#sideloads ⇒ Hash (readonly)
The associated sibling sideloads
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def sideloads @sideloads end |
#type ⇒ Symbol (readonly)
One of :has_many, :belongs_to, etc
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def type @type end |
Instance Method Details
#allow_sideload(name, opts = {}, &blk) ⇒ Object
Configure a relationship between Resource objects
You probably want to extract this logic into an adapter rather than using directly
264 265 266 267 268 269 270 271 272 273 |
# File 'lib/jsonapi_compliable/sideload.rb', line 264 def allow_sideload(name, opts = {}, &blk) sideload = Sideload.new(name, opts) sideload.instance_eval(&blk) if blk if polymorphic? @polymorphic_groups[name] = sideload else @sideloads[name] = sideload end end |
#assign {|parents, children| ... } ⇒ Object
The proc used to assign the resolved parents and children.
You probably want to wrap this logic in an Adapter, instead of specifying in your resource directly.
166 167 168 |
# File 'lib/jsonapi_compliable/sideload.rb', line 166 def assign(&blk) @assign_proc = blk end |
#associate(parent, child) ⇒ Object
Configure how to associate parent and child records.
183 184 185 |
# File 'lib/jsonapi_compliable/sideload.rb', line 183 def associate(parent, child) resource_class.config[:adapter].associate(parent, child, name, type) end |
#group_by(&grouper) ⇒ Object
Define a proc that groups the parent records. For instance, with
an ActiveRecord polymorphic belongs_to there will be a parent_id
and parent_type. We would want to group on parent_type:
allow_sideload :organization, polymorphic: true do
group parent_type, parent here is 'organization'
group_by ->(office) { office.organization_type } end
197 198 199 |
# File 'lib/jsonapi_compliable/sideload.rb', line 197 def group_by(&grouper) @grouper = grouper end |
#polymorphic? ⇒ Boolean
Is this sideload polymorphic?
Polymorphic sideloads group the parent objects in some fashion,
so different 'types' can be resolved differently. Let's say an
Office has a polymorphic Organization, which can be either a
Business or Government:
allow_sideload :organization, :polymorphic: true do
group_by { |record| record.organization_type }
allow_sideload 'Business', resource: BusinessResource do
# ... code ...
end
allow_sideload 'Governemnt', resource: GovernmentResource do
# ... code ...
end
end
You probably want to extract this code into an Adapter. For instance, with ActiveRecord:
polymorphic_belongs_to :organization,
group_by: ->(office) { office.organization_type },
groups: {
'Business' => {
scope: -> { Business.all },
resource: BusinessResource,
foreign_key: :organization_id
},
'Government' => {
scope: -> { Government.all },
resource: GovernmentResource,
foreign_key: :organization_id
}
}
89 90 91 |
# File 'lib/jsonapi_compliable/sideload.rb', line 89 def polymorphic? @polymorphic == true end |
#resolve(parents, query, namespace = nil) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Resolve the sideload.
- Uses the 'scope' proc to build a 'base scope'
- Chains additional criteria onto that 'base scope'
- Resolves that scope (see Scope#resolve)
- Assigns the resulting child objects to their corresponding parents
216 217 218 219 220 221 222 223 224 |
# File 'lib/jsonapi_compliable/sideload.rb', line 216 def resolve(parents, query, namespace = nil) namespace ||= name if polymorphic? resolve_polymorphic(parents, query) else resolve_basic(parents, query, namespace) end end |
#resource ⇒ Resource
Returns an instance of #resource_class.
46 47 48 |
# File 'lib/jsonapi_compliable/sideload.rb', line 46 def resource @resource ||= resource_class.new end |
#scope {|parents| ... } ⇒ Object
Build a scope that will be used to fetch the related records This scope will be further chained with filtering/sorting/etc
You probably want to wrap this logic in an Adapter, instead of specifying in your resource directly.
129 130 131 |
# File 'lib/jsonapi_compliable/sideload.rb', line 129 def scope(&blk) @scope_proc = blk end |
#sideload(name) ⇒ Object
Fetch a Sideload object by its name
279 280 281 |
# File 'lib/jsonapi_compliable/sideload.rb', line 279 def sideload(name) @sideloads[name] end |
#to_hash(processed = []) ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Looks at all nested sideload, and all nested sideloads for the corresponding Resources, and returns an Include Directive hash
For instance, this configuration:
class BarResource < ApplicationResource
allow_sideload :baz do
end
end
class PostResource < ApplicationResource
allow_sideload :foo do
allow_sideload :bar, resource: BarResource do
end
end
end
post_resource.sideloading.to_hash would return
{ base: { foo: { bar: { baz: {} } } } }
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/jsonapi_compliable/sideload.rb', line 306 def to_hash(processed = []) return { name => {} } if processed.include?(self) processed << self result = { name => {} }.tap do |hash| @sideloads.each_pair do |key, sideload| hash[name][key] = sideload.to_hash(processed)[key] || {} if sideload.polymorphic? sideload.polymorphic_groups.each_pair do |type, sl| hash[name][key].merge!(nested_sideload_hash(sl, processed)) end else hash[name][key].merge!(nested_sideload_hash(sideload, processed)) end end end result end |