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.
-
#grouping_field ⇒ Symbol
readonly
The configured 'group_by' symbol.
-
#name ⇒ Symbol
readonly
The name of the sideload.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
-
#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(grouping_field) ⇒ Object
Define an attribute that groups the parent records.
-
#initialize(name, type: nil, resource: nil, polymorphic: false, primary_key: :id, foreign_key: nil, parent: nil) ⇒ Sideload
constructor
NB - the adapter's
#sideloading_module
is mixed in on instantiation. -
#polymorphic? ⇒ Boolean
Is this sideload polymorphic?.
- #polymorphic_child_for_type(type) ⇒ Object private
-
#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, parent: nil) ⇒ Sideload
NB - the adapter's #sideloading_module
is mixed in on
instantiation
An anonymous Resource will be assigned when none provided.
32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/jsonapi_compliable/sideload.rb', line 32 def initialize(name, type: nil, resource: nil, polymorphic: false, primary_key: :id, foreign_key: nil, parent: nil) @name = name @resource_class = (resource || Class.new(Resource)) @sideloads = {} @polymorphic = !!polymorphic @polymorphic_groups = {} if polymorphic? @parent = parent @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 |
#grouping_field ⇒ Symbol (readonly)
The configured 'group_by' symbol
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def grouping_field @grouping_field end |
#name ⇒ Symbol (readonly)
The name of the sideload
13 14 15 |
# File 'lib/jsonapi_compliable/sideload.rb', line 13 def name @name end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent
14 15 16 |
# File 'lib/jsonapi_compliable/sideload.rb', line 14 def parent @parent 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
270 271 272 273 274 275 276 277 278 279 |
# File 'lib/jsonapi_compliable/sideload.rb', line 270 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.
168 169 170 |
# File 'lib/jsonapi_compliable/sideload.rb', line 168 def assign(&blk) @assign_proc = blk end |
#associate(parent, child) ⇒ Object
Configure how to associate parent and child records.
185 186 187 188 189 190 191 |
# File 'lib/jsonapi_compliable/sideload.rb', line 185 def associate(parent, child) association_name = @parent ? @parent.name : name resource_class.config[:adapter].associate parent, child, association_name, type end |
#group_by(grouping_field) ⇒ Object
Define an attribute 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 :organization_type
end
203 204 205 |
# File 'lib/jsonapi_compliable/sideload.rb', line 203 def group_by(grouping_field) @grouping_field = grouping_field 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 :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: :organization_type,
groups: {
'Business' => {
scope: -> { Business.all },
resource: BusinessResource,
foreign_key: :organization_id
},
'Government' => {
scope: -> { Government.all },
resource: GovernmentResource,
foreign_key: :organization_id
}
}
91 92 93 |
# File 'lib/jsonapi_compliable/sideload.rb', line 91 def polymorphic? @polymorphic == true end |
#polymorphic_child_for_type(type) ⇒ Object
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.
333 334 335 336 337 |
# File 'lib/jsonapi_compliable/sideload.rb', line 333 def polymorphic_child_for_type(type) polymorphic_groups.values.find do |v| v.resource_class.config[:type] == type end 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
222 223 224 225 226 227 228 229 230 |
# File 'lib/jsonapi_compliable/sideload.rb', line 222 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
48 49 50 |
# File 'lib/jsonapi_compliable/sideload.rb', line 48 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.
131 132 133 |
# File 'lib/jsonapi_compliable/sideload.rb', line 131 def scope(&blk) @scope_proc = blk end |
#sideload(name) ⇒ Object
Fetch a Sideload object by its name
285 286 287 |
# File 'lib/jsonapi_compliable/sideload.rb', line 285 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: {} } } } }
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/jsonapi_compliable/sideload.rb', line 312 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 |