Class: Famili::Child

Inherits:
BasicObject
Defined in:
lib/famili/child.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mother, attributes) ⇒ Child

Returns a new instance of Child.



5
6
7
8
# File 'lib/famili/child.rb', line 5

def initialize(mother, attributes)
  @mother = mother
  @attributes = attributes
end

Instance Attribute Details

#motherObject (readonly)

Returns the value of attribute mother.



3
4
5
# File 'lib/famili/child.rb', line 3

def mother
  @mother
end

Instance Method Details

#bornObject



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/famili/child.rb', line 10

def born
  @unresolved_property_names = @attributes.keys
  @model = @mother.class.model_class.new
  @meta_class = @model.singleton_class
  @model.instance_variable_set(:@__famili_child__, self)
  define_method_stub(:method_missing) do |name, *args|
    mother = @__famili_child__.mother
    if mother.respond_to?(name)
      mother.send(name, *args)
    else
      send(@__famili_child__.munge(:method_missing), name, *args)
    end
  end
  @unresolved_property_names.each do |key|
    define_property_stub(key)
  end
  resolve_property(@unresolved_property_names.first) until @unresolved_property_names.empty?
  undefine_method_stub(:method_missing)
  @model
end

#define_method_stub(method_name, &block) ⇒ Object



57
58
59
60
# File 'lib/famili/child.rb', line 57

def define_method_stub(method_name, &block)
  @meta_class.send(:alias_method, munge(method_name), method_name)
  @meta_class.send(:define_method, method_name, &block)
end

#define_property_stub(property_name) ⇒ Object



47
48
49
50
51
# File 'lib/famili/child.rb', line 47

def define_property_stub(property_name)
  define_method_stub property_name do
    @__famili_child__.resolve_property(property_name)
  end if @model.respond_to?(property_name)
end

#munge(property_name) ⇒ Object



31
32
33
# File 'lib/famili/child.rb', line 31

def munge(property_name)
  "__famili_child_proxied_#{property_name}"
end

#resolve_property(name) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
# File 'lib/famili/child.rb', line 35

def resolve_property(name)
  @unresolved_property_names.delete(name)
  undefine_property_stub(name)
  attribute_value = @attributes[name]
  if attribute_value.is_a?(::Proc)
    attribute_value = @model.instance_exec(&attribute_value)
  elsif attribute_value.is_a?(::Famili::Father)
    attribute_value = attribute_value.create
  end
  @model.send("#{name}=", attribute_value)
end

#undefine_method_stub(method_name) ⇒ Object



62
63
64
65
66
67
68
69
70
# File 'lib/famili/child.rb', line 62

def undefine_method_stub(method_name)
  munged_name = munge(method_name)
  if @meta_class.send(:method_defined?, munged_name)
    @meta_class.send(:alias_method, method_name, munged_name)
    @meta_class.send(:remove_method, munged_name)
  else
    @meta_class.send(:remove_method, method_name)
  end
end

#undefine_property_stub(property_name) ⇒ Object



53
54
55
# File 'lib/famili/child.rb', line 53

def undefine_property_stub(property_name)
  undefine_method_stub(property_name) if @meta_class.send(:method_defined?, munge(property_name))
end