Class: Onoma::Item
- Inherits:
-
Object
show all
- Defined in:
- lib/onoma/item.rb
Overview
An item of a nomenclature is the core data.
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
#initialize(nomenclature, name, options = {}) ⇒ Item
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
# File 'lib/onoma/item.rb', line 12
def initialize(nomenclature, name, options = {})
@nomenclature = nomenclature
@name = name.to_s
@left, @right = @nomenclature.new_boundaries
@depth = 0
@parent = nil
@parent_name = nil
parent = options.delete(:parent)
if parent.is_a?(Symbol) || parent.is_a?(String)
@parent_name = parent.to_s
else
self.parent = parent
end
@attributes = {}.with_indifferent_access
@children = Set.new
options.each do |k, v|
set(k, v)
end
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args) ⇒ Object
Returns property descriptor
318
319
320
321
322
|
# File 'lib/onoma/item.rb', line 318
def method_missing(method_name, *args)
return property(method_name) if has_property?(method_name)
super
end
|
Instance Attribute Details
#aliases ⇒ Object
Returns the value of attribute aliases.
7
8
9
|
# File 'lib/onoma/item.rb', line 7
def aliases
@aliases
end
|
#attributes ⇒ Object
Also known as:
properties
Returns the value of attribute attributes.
8
9
10
|
# File 'lib/onoma/item.rb', line 8
def attributes
@attributes
end
|
#depth ⇒ Object
Returns the value of attribute depth.
7
8
9
|
# File 'lib/onoma/item.rb', line 7
def depth
@depth
end
|
#left ⇒ Object
Returns the value of attribute left.
7
8
9
|
# File 'lib/onoma/item.rb', line 7
def left
@left
end
|
#name ⇒ Object
Returns the value of attribute name.
8
9
10
|
# File 'lib/onoma/item.rb', line 8
def name
@name
end
|
#nomenclature ⇒ Object
Returns the value of attribute nomenclature.
7
8
9
|
# File 'lib/onoma/item.rb', line 7
def nomenclature
@nomenclature
end
|
#parent_name ⇒ Object
Returns the value of attribute parent_name.
7
8
9
|
# File 'lib/onoma/item.rb', line 7
def parent_name
@parent_name
end
|
#right ⇒ Object
Returns the value of attribute right.
7
8
9
|
# File 'lib/onoma/item.rb', line 7
def right
@right
end
|
Instance Method Details
#<(other) ⇒ Object
224
225
226
227
|
# File 'lib/onoma/item.rb', line 224
def <(other)
other = item_for_comparison(other)
(other.left < @left && @right < other.right)
end
|
#<=(other) ⇒ Object
234
235
236
237
|
# File 'lib/onoma/item.rb', line 234
def <=(other)
other = item_for_comparison(other)
(other.left <= @left && @right <= other.right)
end
|
#<=>(other) ⇒ Object
219
220
221
222
|
# File 'lib/onoma/item.rb', line 219
def <=>(other)
other = item_for_comparison(other)
nomenclature.name <=> other.nomenclature.name && name <=> other.name
end
|
#==(other) ⇒ Object
214
215
216
217
|
# File 'lib/onoma/item.rb', line 214
def ==(other)
other = item_for_comparison(other)
nomenclature == other.nomenclature && name == other.name
end
|
#>(other) ⇒ Object
229
230
231
232
|
# File 'lib/onoma/item.rb', line 229
def >(other)
other = item_for_comparison(other)
(@left < other.left && other.right < @right)
end
|
#>=(other) ⇒ Object
239
240
241
242
|
# File 'lib/onoma/item.rb', line 239
def >=(other)
other = item_for_comparison(other)
(@left <= other.left && other.right <= @right)
end
|
#add_child(item) ⇒ Object
63
64
65
|
# File 'lib/onoma/item.rb', line 63
def add_child(item)
@children << item
end
|
#children(options = {}) ⇒ Object
Returns children recursively by default
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# File 'lib/onoma/item.rb', line 117
def children(options = {})
if options[:index].is_a?(FalseClass)
if options[:recursively].is_a?(FalseClass)
@children.to_a
else
children(index: false, recursive: false).each_with_object([]) do |item, list|
list << item
list += item.children(index: false, recursive: true)
list
end
end
elsif options[:recursively].is_a?(FalseClass)
nomenclature.list.select do |item|
@left < item.left && item.right < @right && item.depth == @depth + 1
end
else
nomenclature.list.select do |item|
@left < item.left && item.right < @right
end
end
end
|
#degree_of_kinship_with(other) ⇒ Object
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
# File 'lib/onoma/item.rb', line 95
def degree_of_kinship_with(other)
other_item = item_for_comparison(other)
a = self_and_parents.reverse
b = other_item.self_and_parents.reverse
return nil if a.first != b.first
common_lineage = 0
a.size.times do |index|
break if a[index].nil? || b[index].nil? || a[index] != b[index]
common_lineage += 1
end
a.size + b.size - 2 * common_lineage
end
|
#delete_child(item) ⇒ Object
67
68
69
|
# File 'lib/onoma/item.rb', line 67
def delete_child(item)
@children.delete(item)
end
|
#find_parent ⇒ Object
91
92
93
|
# File 'lib/onoma/item.rb', line 91
def find_parent
@nomenclature.find(@parent_name)
end
|
#has_property?(name) ⇒ Boolean
Checks if item has property with given name
313
314
315
|
# File 'lib/onoma/item.rb', line 313
def has_property?(name)
!@nomenclature.properties[name].nil?
end
|
#human_name(options = {}) ⇒ Object
Also known as:
humanize, localize
Return human name of item
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
|
# File 'lib/onoma/item.rb', line 188
def human_name(options = {})
scope = options.delete(:scope)
no_attribute_translation = "nomenclatures.#{Onoma.escape_key(nomenclature.name)}.items.#{Onoma.escape_key(name)}"
if scope
scope_attribute = scope
other_attributes = attributes.except(scope_attribute)
scope_translation = "nomenclatures.#{Onoma.escape_key(nomenclature.name)}.items.#{Onoma.escape_key(scope_attribute)}.#{Onoma.escape_key(name)}"
other_translations = other_attributes.map { |attr_name, _value| "nomenclatures.#{Onoma.escape_key(nomenclature.name)}.items.#{Onoma.escape_key(attr_name)}.#{Onoma.escape_key(name)}" }
root = scope_translation
defaults = [no_attribute_translation, *other_translations]
else
scoped_by_attributes = attributes.map { |attr_name, _value| "nomenclatures.#{Onoma.escape_key(nomenclature.name)}.items.#{Onoma.escape_key(attr_name)}.#{Onoma.escape_key(name)}" }
root = "nomenclatures.#{Onoma.escape_key(nomenclature.name)}.items.#{Onoma.escape_key(name)}"
defaults = scoped_by_attributes
end
I18n.t(root, options.merge(default: [*defaults.map(&:to_sym), "items.#{Onoma.escape_key(name)}".to_sym, "enumerize.#{Onoma.escape_key(nomenclature.name)}.#{Onoma.escape_key(name)}".to_sym, "labels.#{Onoma.escape_key(name)}".to_sym, name.humanize]))
end
|
#human_notion_name(notion_name, options = {}) ⇒ Object
210
211
212
|
# File 'lib/onoma/item.rb', line 210
def human_notion_name(notion_name, options = {})
I18n.t("nomenclatures.#{nomenclature.name}.notions.#{notion_name}.#{name}", options.merge(default: ["labels.#{name}".to_sym]))
end
|
#include?(other) ⇒ Boolean
Returns true if the given item name match the current item or its children
183
184
185
|
# File 'lib/onoma/item.rb', line 183
def include?(other)
self >= other
end
|
#inspect ⇒ Object
244
245
246
|
# File 'lib/onoma/item.rb', line 244
def inspect
"#{@nomenclature.name}-#{@name}(#{@left}-#{@right})"
end
|
#original_nomenclature_name ⇒ Object
110
111
112
113
114
|
# File 'lib/onoma/item.rb', line 110
def original_nomenclature_name
return parent.name.to_sym unless root?
nil
end
|
#parent ⇒ Object
Also known as:
fetch_parent
81
82
83
84
85
86
87
|
# File 'lib/onoma/item.rb', line 81
def parent
return @parent if @parent
@parent = find_parent
@parent.add_child(self) if @parent
@parent
end
|
#parent=(item) ⇒ Object
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
# File 'lib/onoma/item.rb', line 36
def parent=(item)
old_parent_name = @parent_name
old_parent = @parent
if item.nil?
@parent = nil
@parent_name = nil
else
if item.is_a?(Symbol) || item.is_a?(String)
item = nomenclature.find!(item.to_s)
end
if item.nomenclature != nomenclature
raise 'Item must come from same nomenclature'
end
if item.parents.any? { |p| self == p } || self == item
raise 'Circular dependency. Item can be parent of itself.'
end
@parent = item
@parent_name = @parent.name.to_s
end
if old_parent_name != @parent_name
old_parent.delete_child(self) if old_parent
@parent.add_child(self) if @parent
@nomenclature.rebuild_tree!
end
end
|
#parent? ⇒ Boolean
77
78
79
|
# File 'lib/onoma/item.rb', line 77
def parent?
parent.present?
end
|
#parents ⇒ Object
Returns direct parents from the closest to the farthest
145
146
147
|
# File 'lib/onoma/item.rb', line 145
def parents
@parents ||= (parent.nil? ? [] : [parent] + parent.parents)
end
|
#property(name) ⇒ Object
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
|
# File 'lib/onoma/item.rb', line 274
def property(name)
return @name.to_sym if name == :name
property = @nomenclature.properties[name]
value = @attributes[name]
if property
if value.nil? && property.fallbacks
property.fallbacks.each do |fallback|
value ||= @name if fallback == :name
value ||= @attributes[fallback]
break if value
end
end
value = cast_property(name, property.default) if property.default && value.nil?
end
value
end
|
#rebuild_tree(left = 0, depth = 0) ⇒ Object
Computes left/right value for nested set Returns right index
172
173
174
175
176
177
178
179
180
|
# File 'lib/onoma/item.rb', line 172
def rebuild_tree(left = 0, depth = 0)
@depth = depth
@left = left
@right = @left + 1
children(index: false, recursively: false).each do |child|
@right = child.rebuild_tree(@right, @depth + 1) + 1
end
@right
end
|
#rebuild_tree! ⇒ Object
Computes left/right value for nested set Returns right index
166
167
168
|
# File 'lib/onoma/item.rb', line 166
def rebuild_tree!
@nomenclature.forest_right = rebuild_tree(@nomenclature.forest_right + 1)
end
|
#rise(&block) ⇒ Object
157
158
159
160
161
162
|
# File 'lib/onoma/item.rb', line 157
def rise(&block)
result = yield(self)
return result if result
parent ? parent.rise(&block) : nil
end
|
#root ⇒ Object
140
141
142
|
# File 'lib/onoma/item.rb', line 140
def root
parent? ? parent.root : self
end
|
#root? ⇒ Boolean
32
33
34
|
# File 'lib/onoma/item.rb', line 32
def root?
!parent
end
|
#selection(name) ⇒ Object
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
|
# File 'lib/onoma/item.rb', line 292
def selection(name)
property = @nomenclature.properties[name]
if property.list?
return property(name).collect do |i|
["nomenclatures.#{@nomenclature.name}.item_lists.#{self.name}.#{name}.#{i}".t, i]
end
elsif property.nomenclature?
target_nomenclature = Onoma.find(property(name).to_sym)
unless target_nomenclature
raise "Cannot find nomenclature: for #{property(name).inspect}"
end
return target_nomenclature.list.collect do |i|
[i.human_name, i.name]
end
else
raise StandardError.new('Cannot call selection for a non-list property')
end
end
|
#self_and_children(options = {}) ⇒ Object
149
150
151
|
# File 'lib/onoma/item.rb', line 149
def self_and_children(options = {})
[self] + children(options)
end
|
#self_and_parents ⇒ Object
153
154
155
|
# File 'lib/onoma/item.rb', line 153
def self_and_parents
[self] + parents
end
|
#set(name, value) ⇒ Object
324
325
326
327
328
329
330
331
332
333
334
335
336
|
# File 'lib/onoma/item.rb', line 324
def set(name, value)
raise "Invalid property: #{name.inspect}" if %i[name parent].include?(name.to_sym)
if value.nil?
@attributes.delete(name)
else
@attributes[name] = value
end
end
|
#to_xml_attrs ⇒ Object
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
|
# File 'lib/onoma/item.rb', line 256
def to_xml_attrs
attrs = {}
attrs[:name] = name
attrs[:parent] = @parent_name if parent?
properties.each do |pname, pvalue|
if p = nomenclature.properties[pname.to_s]
if p.type == :decimal
pvalue = pvalue.to_s.to_f
elsif p.list?
pvalue = pvalue.join(', ')
end
end
attrs[pname] = pvalue.to_s
end
attrs
end
|
#tree(depth = 0) ⇒ Object
248
249
250
251
252
253
254
|
# File 'lib/onoma/item.rb', line 248
def tree(depth = 0)
text = "#{left.to_s.rjust(4)}-#{right.to_s.ljust(4)} #{' ' * depth}#{@name}:\n"
text << children(index: false, recursively: false).collect do |c|
c.tree(depth + 1)
end.join("\n")
text
end
|