Class: Lipa::Node

Inherits:
Object
  • Object
show all
Defined in:
lib/lipa/node.rb

Overview

Base object for all nested object of tree It supports initialization attributes by constant, variable or code

Examples:

tree = root :tree do 
  node :object, :param_1 => 4 do
    param_2 "some_param"
    param_3 run{1+param_3}
  end
end
tree.object.param_1 #=> 4
tree.object.param_2 #=> "some_param"
tree.object.param_3 #=> 5

Direct Known Subclasses

Root

Constant Summary collapse

@@init_methods =
{:node => self}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, attrs = {}, &block) ⇒ Node

Returns a new instance of Node.



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/lipa/node.rb', line 46

def initialize(name, attrs = {}, &block)
  @name = name.to_s
  @children = {}
  @parent = attrs.delete(:parent)
  @root = attrs.delete(:root)
  @full_name = attrs.delete(:full_name)
  @kind = attrs.delete(:kind)
  @attrs = attrs

  instance_eval &block if block_given?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/lipa/node.rb', line 58

def method_missing(name, *args, &block)
  unless Node.add_node(name, self, *args, &block)
    case args.size
      when 0
        child = children[name]
        return child if child

        val = @attrs[name]

        super if val.nil? #Raise MethodError if don't have it

        if val.class == Proc
          instance_eval &(val)
        else
          val
        end
      when 1
        name = name.to_s
        name["="] = "" if name["="]
        @attrs[name.to_sym] = args[0]
      else
        super
    end
  end
end

Instance Attribute Details

#attrsObject

Returns the value of attribute attrs.



43
44
45
# File 'lib/lipa/node.rb', line 43

def attrs
  @attrs
end

#childrenObject

Returns the value of attribute children.



43
44
45
# File 'lib/lipa/node.rb', line 43

def children
  @children
end

#full_nameObject

Returns the value of attribute full_name.



43
44
45
# File 'lib/lipa/node.rb', line 43

def full_name
  @full_name
end

#kindObject

Returns the value of attribute kind.



43
44
45
# File 'lib/lipa/node.rb', line 43

def kind
  @kind
end

#nameObject

Returns the value of attribute name.



43
44
45
# File 'lib/lipa/node.rb', line 43

def name
  @name
end

#parentObject

Returns the value of attribute parent.



43
44
45
# File 'lib/lipa/node.rb', line 43

def parent
  @parent
end

#rootObject

Returns the value of attribute root.



43
44
45
# File 'lib/lipa/node.rb', line 43

def root
  @root
end

Class Method Details

.add_node(name, parent, *args, &block) ⇒ Object

Making children node

Parameters:

  • name (String)

    of initial method or kind

  • parent (Node)

    node

  • args

    of node

  • block

    for node



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/lipa/node.rb', line 217

def self.add_node(name, parent, *args, &block)
  # OPTIMIZE: This code looks bad
  # Init from kind
  args[1] ||= {}
  attrs = {}

  k = parent.root.kinds[name]
  if k and k.for
    init_class = @@init_methods[k.for]
  else
    #from init methods
    init_class = @@init_methods[name]
  end

  if init_class
    # Init general attributes
    attrs[:parent] = parent
    attrs[:root] = parent.root
    fn = parent.full_name == "/" ? "" : parent.full_name
    attrs[:full_name] =  fn  + "/" + args[0].to_s

    node_name = args[0].to_sym
    children = parent.children
    if k
      attrs.merge! k.attrs
      attrs[:kind] = k.name
      #Node is descripted in kind
      existen_child = parent.children[node_name]
      attrs = existen_child.attrs.merge(attrs) if existen_child
      #Init from kind
      children[node_name] = init_class.send(:new, node_name, attrs, &k.block)
      #Local modification
      children[node_name].attrs.merge!(args[1])
      children[node_name].instance_exec(&block) if block_given?
    else
      children[node_name] = init_class.send(:new, node_name, attrs.merge(args[1]), &block )
    end
    true
  else  
    nil
  end
end

.init_methods(*names) ⇒ Object

Accesor for methods for initialization node objects

Examples:

class Folder < Lipa::Node
  init_methods :folder
end

fls = root :folders do
  folder :folder_1 do
    param_1 "some_param
  end
end

fls.folder_1.class #=> Folder

Parameters:

  • names

    of initial methods



201
202
203
204
205
206
207
208
209
# File 'lib/lipa/node.rb', line 201

def self.init_methods(*names)
  if names.size > 0
    names.each do |name|
      @@init_methods[name.to_sym] = self
    end
  else
    @@init_methods
  end
end

Instance Method Details

#[](path) ⇒ Node

Accessor for node by path in Unix style

Examples:

dir_2["dir_1/dir_2/searched_obj"] 
dir_2["searched_obj"] 
dir_2["./searched_obj"] 
dir_2["../dir_2/searched_obj"] 

Parameters:

  • path (String)

    nodes

Returns:



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/lipa/node.rb', line 113

def [](path)
  first, *rest_path = path.split("/")  
  obj = case first
  when nil
    if path == "/"
      root
    elsif path == ""
      self
    end
  when ""
    root
  when ".."
    parent
  when "."
    self
  else
    children[first.to_sym]
  end

  return nil if obj.nil?
  if rest_path.size > 0
    obj[rest_path.join("/")]
  else
    obj
  end
end

#eval_attrsObject

Copy attributes with eval

Examples:

node :some_node d:
  param_1 1
  param_2 run{ param_1 + 2}
end

node.attrs #=> {:param_1 => 1, :param_2 => Proc}
node.eval_attrs #=> {:param_1 => 1, :param_2 => 3}


96
97
98
99
100
101
102
# File 'lib/lipa/node.rb', line 96

def eval_attrs
  result = {}
  @attrs.each_pair do |k,v|
    result[k.to_sym] = instance_eval(k.to_s)
  end
  result
end

#ref(path) ⇒ Object

Reference to othe object

Examples:


node :node_1 
node :node_2 do
  param_1 ref("../node_1")
end

Parameters:

  • path

    in Unix style



180
181
182
# File 'lib/lipa/node.rb', line 180

def ref(path) 
 Proc.new { self[path] }
end

#run(&block) ⇒ Object

Wraping code in attribute

Examples:

root :tree do
  param_1 10
  param_2 run{ param_1 * 10 }
end

Parameters:

  • block

    of code



167
168
169
# File 'lib/lipa/node.rb', line 167

def run(&block)
  block
end

#with(attrs = {}, &block) ⇒ Object

Initial method for group description

Examples:

tree = root :tree do 
  with :param_1 => "some_param" do
    node :obj_1
    node :obj_2
  end
end

tree.obj_1.param_1 #=> "some_param"
tree.obj_2.param_1 #=> "some_param"


152
153
154
155
156
# File 'lib/lipa/node.rb', line 152

def with(attrs = {}, &block)
  if block_given?
    Lipa::Bunch.new(self, attrs, &block)
  end
end