Module: Minitwin::Assignment

Included in:
Minitwin
Defined in:
lib/minitwin/assignment.rb,
sig/generated/minitwin/assignment.rbs

Overview

Assign/update helpers to merge incoming data into an existing twin.

  • assign_object: copy readable attributes from an object and remember it
  • assign_hash / assign_params: update only known attributes, recursing into nested twins and collection items when possible

Instance Method Summary collapse

Instance Method Details

#assign_hash(hash = {}) ⇒ instance

: (Hash[ String | Symbol, untyped ] hash) -> instance

Parameters:

  • hash (Hash[String | Symbol, untyped]) (defaults to: {})

Returns:

  • (instance)


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/minitwin/assignment.rb', line 39

def assign_hash(hash = {})
  hash = hash.to_h.transform_keys(&:to_sym)
  allowed = assignable_attribute_methods

  was_skipping = @__skip_alias_recompute__
  @__skip_alias_recompute__ = true
  begin
    hash.each do |method, value|
      next unless allowed.include?(method)

      ivar_name = Minitwin::Utils.ivar_name(method)
      current_value = instance_variable_get(ivar_name) if instance_variable_defined?(ivar_name)

      if current_value.respond_to?(:assign_hash) && value.is_a?(Hash)
        current_value.assign_hash(value)
      elsif value.is_a?(Array) && current_value.is_a?(Array)
        value.each_with_index do |item, idx|
          if item.is_a?(Hash) && current_value.size > idx && current_value[idx].respond_to?(:assign_hash)
            current_value[idx].assign_hash(item)
          else
            current_value[idx] = item
          end
        end
      elsif respond_to?("#{method}=", true)
        send("#{method}=", value)
      end
    end
  ensure
    @__skip_alias_recompute__ = was_skipping
  end

  if !@__skip_alias_recompute__ && self.class.dynamic_aliases?
    __recompute_dynamic_aliases__
  end

  self
end

#assign_object(model) ⇒ instance

: (untyped) -> instance

Parameters:

  • (Object)

Returns:

  • (instance)


32
33
34
35
36
# File 'lib/minitwin/assignment.rb', line 32

def assign_object(model)
  to_object(model)
  instance_variable_set(self.class.internal_model_name("model"), model)
  self
end

#assign_params(params = {}) ⇒ instance

Actually, this is expected to be an ActionController::Parameters object. The type will be unknown when used without rails. So for RBS the argument is typed untyped. : (untyped params) -> instance

Parameters:

  • params (Object) (defaults to: {})

Returns:

  • (instance)


81
82
83
84
# File 'lib/minitwin/assignment.rb', line 81

def assign_params(params = {})
  params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
  assign_hash(params)
end

#assignable_attribute_methodsArray[Symbol]

Gets the non-readonly methods, which can be assigned with new values. : () -> Array

Returns:

  • (Array[Symbol])


88
89
90
91
92
93
# File 'lib/minitwin/assignment.rb', line 88

def assignable_attribute_methods
  attribute_methods.reject do |method|
    prop_meta = self.class.properties[method]
    prop_meta && prop_meta[:readonly]
  end
end

#to_object(model) ⇒ instance

Mirror values from a model's getters into this twin's setters : (untyped) -> instance

Parameters:

  • (Object)

Returns:

  • (instance)


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/minitwin/assignment.rb', line 13

def to_object(model)
  assignable_attribute_methods.each do |method|
    next unless model.respond_to?(method)

    value = model.public_send(method)

    ivar_name = Minitwin::Utils.ivar_name(method)
    current_value = instance_variable_get(ivar_name) if instance_variable_defined?(ivar_name)

    if current_value.is_a?(Minitwin) && !value.nil? && !value.is_a?(Hash)
      current_value.to_object(value)
    elsif respond_to?("#{method}=", true)
      send("#{method}=", value)
    end
  end
  self
end