class Opium::Model::Relation

Attributes

metadata[R]
owner[R]

Public Class Methods

new( model_name ) click to toggle source
Calls superclass method Opium::Model::Criteria::new
# File lib/opium/model/relation.rb, line 65
def initialize( model_name )
  super
  update_variable!( :cache, true )
end
to_parse( object ) click to toggle source
# File lib/opium/model/relation.rb, line 7
def to_parse( object )
  class_name = determine_class_name_from( object, 'parse Relation hash' )
  fail ArgumentError, "could not determine class_name from #{ object.inspect }" unless class_name
  { __type: 'Relation', className: class_name }.with_indifferent_access
end
to_ruby( object ) click to toggle source
# File lib/opium/model/relation.rb, line 13
def to_ruby( object )
  return if object.nil? || object == []
  return object if object.is_a? self
  class_name = determine_class_name_from( object, self.name )
  new( class_name ).tap do |relation|
    case object
    when String
    when is_descendant.curry[Opium::Model]
      relation.push object
    when contains_descendant.curry[Opium::Model]
      object.select(&is_descendant.curry[Opium::Model]).each {|model| relation.push model}
    end
  end
end

Private Class Methods

contains_descendant() click to toggle source
# File lib/opium/model/relation.rb, line 51
def contains_descendant
  @contains_descendant ||= ->( expected_type, object ) do 
    object.is_a?( Enumerable ) ? object.any?( &is_descendant.curry[expected_type] ) : is_descendant.curry[expected_type]
  end
end
determine_class_name_from( object, context ) click to toggle source
# File lib/opium/model/relation.rb, line 30
def determine_class_name_from( object, context )
  case object
  when Hash
    fetch_hash_key_from( object, 'class_name' ) || fetch_hash_key_from( object, 'model_name' )
  when String, Symbol
    object
  when is_descendant.curry[Opium::Model]
    object.model_name
  when contains_descendant.curry[Opium::Model]
    object.select(&is_descendant.curry[Opium::Model]).first.model_name
  when self
    object.class_name
  else
    fail ArgumentError, "could not convert #{ object.inspect } to a #{ context }"
  end
end
fetch_hash_key_from( hash, key ) click to toggle source
# File lib/opium/model/relation.rb, line 57
def fetch_hash_key_from( hash, key )
  snake_case_key = key.to_s.underscore
  lower_camel_key = key.to_s.camelcase(:lower)
  
  hash[ snake_case_key ] || hash[ snake_case_key.to_sym ] || hash[ lower_camel_key ] || hash[ lower_camel_key.to_sym ]
end
is_descendant() click to toggle source
# File lib/opium/model/relation.rb, line 47
def is_descendant
  @is_descendant ||= ->( expected_type, object ) { ( object.is_a?( Class ) ? object : object.class ) <= expected_type }
end

Public Instance Methods

<<( object )
Alias for: push
build( params = {} ) click to toggle source
# File lib/opium/model/relation.rb, line 115
def build( params = {} )
  model.new( params || {} ).tap do |instance|
    push instance
  end
end
Also aliased as: new
delete( object ) click to toggle source
# File lib/opium/model/relation.rb, line 110
def delete( object )
  __deletions__.push( object )
  self
end
each(&block) click to toggle source

TODO: likely will need to reimplement .each

Calls superclass method Opium::Model::Criteria#each
# File lib/opium/model/relation.rb, line 94
def each(&block)
  if !block_given?
    to_enum(:each)
  else
    super() {|model| block.call( model ) unless __deletions__.include?( model ) }
    (__additions__ - __deletions__).each(&block)
  end
end
empty?() click to toggle source
Calls superclass method Opium::Model::Criteria#empty?
# File lib/opium/model/relation.rb, line 74
def empty?
  owner.nil? || owner.new_record? ? true : super
end
metadata=(value) click to toggle source
# File lib/opium/model/relation.rb, line 85
def metadata=(value)
  @metadata = value
  update_constraint!( :where, '$relatedTo' => { 'key' => value.relation_name.to_s } )
end
new( params = {} )
Alias for: build
owner=(value) click to toggle source
# File lib/opium/model/relation.rb, line 80
def owner=(value)
  @owner = value
  update_constraint!( :where, '$relatedTo' => { 'object' => value.to_parse } )
end
parse_response() click to toggle source
# File lib/opium/model/relation.rb, line 130
def parse_response
  @parse_response ||= []
end
push( object ) click to toggle source
# File lib/opium/model/relation.rb, line 103
def push( object )
  __additions__.push( object )
  self
end
Also aliased as: <<
save() click to toggle source
# File lib/opium/model/relation.rb, line 123
def save
  self.reject {|model| model.persisted?}.each(&:save)
  __apply_additions__
  __apply_deletions__
  true
end
to_parse() click to toggle source
# File lib/opium/model/relation.rb, line 70
def to_parse
  self.class.to_parse self
end

Private Instance Methods

__additions__() click to toggle source
# File lib/opium/model/relation.rb, line 140
def __additions__
  __relation_deltas__[:additions] ||= []
end
__apply_additions__() click to toggle source
# File lib/opium/model/relation.rb, line 148
def __apply_additions__
  unless __additions__.empty?
    parse_response << owner.class.http_put( owner.id, { metadata.relation_name => { __op: 'AddRelation', objects: __additions__.map(&:to_parse) } } )
    @cache.concat( __additions__ )
    __additions__.clear
  end
end
__apply_deletions__() click to toggle source
# File lib/opium/model/relation.rb, line 156
def __apply_deletions__
  unless __deletions__.empty?
    parse_response << owner.class.http_put( owner.id, { metadata.relation_name => { __op: 'RemoveRelation', objects: __deletions__.map(&:to_parse) } } )
    @cache = @cache - __deletions__
    __deletions__.clear
  end
end
__deletions__() click to toggle source
# File lib/opium/model/relation.rb, line 144
def __deletions__
  __relation_deltas__[:deletions] ||= []
end
__relation_deltas__() click to toggle source
# File lib/opium/model/relation.rb, line 136
def __relation_deltas__
  @__relation_deltas__ ||= {}
end