class Representable::Binding

The flow when parsing is #read_fragment -> Populator -> Deserializer. Actual parsing the fragment from the document happens in Binding#read, everything after that is generic.

Serialization: Serializer -> {frag}/[frag]/frag -> Binding#write

Constants

Options

Options instance gets passed to lambdas when pass_options: true. This is considered the new standard way and should be used everywhere for forward-compat.

Attributes

array[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

array?[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

cached_representer[RW]
exec_context[R]
getter[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

has_default[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

has_default?[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

name[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

parent_decorator[R]
representable[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

representable?[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

represented[R]
setter[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

skip_filters[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

skip_filters?[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

typed[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

typed?[R]

DISCUSS: an overall strategy to speed up option reads will come around 3.0.

user_options[R]

Public Class Methods

build(definition, *args) click to toggle source
# File lib/representable/binding.rb, line 12
def self.build(definition, *args)
  # DISCUSS: move #create_binding to this class?
  return definition.create_binding(*args) if definition[:binding]
  build_for(definition, *args)
end
new(definition, parent_decorator) click to toggle source
# File lib/representable/binding.rb, line 18
def initialize(definition, parent_decorator)
  @definition       = definition
  @parent_decorator = parent_decorator # DISCUSS: where's this needed?

  # static options. do this once.
  @representable    = @definition.representable?
  @name             = @definition.name
  @skip_filters     = self[:readable]==false || self[:writeable]==false || self[:if] # Does this binding contain :if, :readable or :writeable settings?
  @getter           = @definition.getter
  @setter           = @definition.setter
  @array            = @definition.array?
  @typed            = @definition.typed?
  @has_default      = @definition.has_default?
end

Public Instance Methods

[](name) click to toggle source
# File lib/representable/binding.rb, line 133
def [](name)
  @definition[name]
end
as() click to toggle source
# File lib/representable/binding.rb, line 43
def as # DISCUSS: private?
  @as ||= evaluate_option(:as)
end
compile_fragment(doc) click to toggle source

Retrieve value and write fragment to the doc.

# File lib/representable/binding.rb, line 57
def compile_fragment(doc)
  evaluate_option(:writer, doc) do
    value = render_filter(get, doc)
    write_fragment(doc, value)
  end
end
default_for(value) click to toggle source
# File lib/representable/binding.rb, line 145
def default_for(value)
  return self[:default] if skipable_empty_value?(value)
  value
end
evaluate_option(name, *args) { || ... } click to toggle source

Evaluate the option (either nil, static, a block or an instance method call) or executes passed block when option not defined.

# File lib/representable/binding.rb, line 121
def evaluate_option(name, *args)
  unless proc = @definition[name] # TODO: this could dispatch directly to the @definition using #send?
    return yield if block_given?
    return
  end

  # TODO: it would be better if user_options was nil per default and then we just don't pass it into lambdas.
  options = self[:pass_options] ? Options.new(self, user_options, represented, parent_decorator) : user_options

  proc.evaluate(exec_context, *(args<<options)) # from Uber::Options::Value.
end
get() click to toggle source
# File lib/representable/binding.rb, line 99
def get
  evaluate_option(:getter) do
    exec_context.send(getter)
  end
end
parse_filter(value, doc) click to toggle source
# File lib/representable/binding.rb, line 95
def parse_filter(value, doc)
  evaluate_option(:parse_filter, value, doc) { value }
end
read_fragment(doc) click to toggle source
# File lib/representable/binding.rb, line 85
def read_fragment(doc)
  fragment = read(doc) # scalar, Array, or Hash (abstract format) or un-deserialised fragment(s).

  populator.call(fragment, doc)
end
render_filter(value, doc) click to toggle source
# File lib/representable/binding.rb, line 91
def render_filter(value, doc)
  evaluate_option(:render_filter, value, doc) { value }
end
render_fragment(value, doc) click to toggle source
# File lib/representable/binding.rb, line 79
def render_fragment(value, doc)
  fragment = serialize(value) { return } # render fragments of hash, xml, yaml.

  write(doc, fragment)
end
representer_module_for(object, *args) click to toggle source

DISCUSS: do we really need that?

1.38      0.104     0.021     0.000     0.083    40001   Representable::Binding#representer_module_for
1.13      0.044     0.017     0.000     0.027    40001   Representable::Binding#representer_module_for (with memoize).
# File lib/representable/binding.rb, line 114
def representer_module_for(object, *args)
  # TODO: cache this!
  evaluate_option(:extend, object) # TODO: pass args? do we actually have args at the time this is called (compile-time)?
end
set(value) click to toggle source
# File lib/representable/binding.rb, line 105
def set(value)
  evaluate_option(:setter, value) do
    exec_context.send(setter, value)
  end
end
skipable_empty_value?(value) click to toggle source
1.55      0.031     0.022     0.000     0.009    60004   Representable::Binding#skipable_empty_value?
1.51      0.030     0.022     0.000     0.008    60004   Representable::Binding#skipable_empty_value?

after polymorphism: 1.44 0.031 0.022 0.000 0.009 60002 #skipable_empty_value?

# File lib/representable/binding.rb, line 141
def skipable_empty_value?(value)
  value.nil? and not self[:render_nil]
end
uncompile_fragment(doc) click to toggle source

Parse value from doc and update the model property.

# File lib/representable/binding.rb, line 65
def uncompile_fragment(doc)
  evaluate_option(:reader, doc) do
    read_fragment(doc)
  end
end
update!(represented, user_options) click to toggle source

Note: this method is experimental.

# File lib/representable/binding.rb, line 151
def update!(represented, user_options)
  @represented = represented

  setup_user_options!(user_options)
  setup_exec_context!
end
write_fragment(doc, value) click to toggle source
# File lib/representable/binding.rb, line 71
def write_fragment(doc, value)
  value = default_for(value)

  return if skipable_empty_value?(value)

  render_fragment(value, doc)
end

Private Instance Methods

serialize(object, &block) click to toggle source
# File lib/representable/binding.rb, line 179
def serialize(object, &block)
  serializer.call(object, &block)
end
setup_exec_context!() click to toggle source

1.80 0.066 0.027 0.000 0.039 30002 #setup_exec_context! 0.98 0.034 0.014 0.000 0.020 30002 #setup_exec_context!

# File lib/representable/binding.rb, line 171
def setup_exec_context!
  return @exec_context = @represented unless self[:exec_context]
  @exec_context = self             if self[:exec_context] == :binding
  @exec_context = parent_decorator if self[:exec_context] == :decorator
end
setup_user_options!(user_options) click to toggle source
# File lib/representable/binding.rb, line 161
def setup_user_options!(user_options)
  @user_options  = user_options
  # this is the propagated_options.
  @user_options  = user_options.merge(wrap: false) if self[:wrap] == false

  # @user_options  = user_options.merge(wrap: self[:wrap]) if self[:wrap]
end