Class: Expressir::Model::ModelElement

Inherits:
Object
  • Object
show all
Defined in:
lib/expressir/model/model_element.rb

Overview

Base model element

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(_options = {}) ⇒ ModelElement

Returns a new instance of ModelElement.

Parameters:

  • options (Hash)


19
20
21
# File 'lib/expressir/model/model_element.rb', line 19

def initialize(_options = {})
  attach_parent_to_children
end

Instance Attribute Details

#parentModelElement

Returns:



16
17
18
# File 'lib/expressir/model/model_element.rb', line 16

def parent
  @parent
end

Class Method Details

.from_hash(hash, root_path: nil) ⇒ ModelElement

Parameters:

  • hash (Hash)
  • root_path (String) (defaults to: nil)

Returns:



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/expressir/model/model_element.rb', line 172

def self.from_hash(hash, root_path: nil)
  node_class = Object.const_get(hash[CLASS_KEY])
  node_options = {}

  node_class.model_attrs.each do |variable|
    value = hash[variable.to_s]

    node_options[variable] = case value
                             when Array
                               value.map do |value|
                                 if value.is_a? Hash
                                   from_hash(value, root_path: root_path)
                                 else
                                   value
                                 end
                               end
                             when Hash
                               from_hash(value, root_path: root_path)
                             else
                               value
                             end
  end

  if (node_class == Declarations::Schema) && hash[FILE_KEY]
    node_options[FILE_KEY.to_sym] = root_path ? File.expand_path("#{root_path}/#{hash[FILE_KEY]}") : hash[FILE_KEY]
  end

  node_class.new(node_options)
end

.model_attr_accessor(attr_name, _attr_type = nil) ⇒ Object

Define a new model attribute

Parameters:

  • attr_name (Symbol)

    attribute name

  • attr_type (Symbol)

    attribute type



213
214
215
216
217
218
# File 'lib/expressir/model/model_element.rb', line 213

def self.model_attr_accessor(attr_name, _attr_type = nil)
  @model_attrs ||= []
  @model_attrs << attr_name

  attr_accessor attr_name
end

.model_attrsArray<Symbol>

Returns:

  • (Array<Symbol>)


203
204
205
# File 'lib/expressir/model/model_element.rb', line 203

def self.model_attrs
  @model_attrs ||= []
end

Instance Method Details

#childrenArray<Declaration>

Returns:



79
80
81
# File 'lib/expressir/model/model_element.rb', line 79

def children
  []
end

#children_by_idHash<String, Declaration>

Returns:



84
85
86
# File 'lib/expressir/model/model_element.rb', line 84

def children_by_id
  @children_by_id ||= children.select(&:id).map { |x| [x.id.safe_downcase, x] }.to_h
end

#find(path) ⇒ ModelElement

Parameters:

Returns:



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
76
# File 'lib/expressir/model/model_element.rb', line 46

def find(path)
  return self if path.empty?

  path_parts = path.safe_downcase.split(/\./).map do |current_path|
    _, _, current_path = current_path.rpartition(":") # ignore prefix
    current_path
  end

  current_scope = self
  target_node = nil
  loop do
    # find in current scope
    current_node = current_scope
    path_parts.each do |current_path|
      current_node = current_node.children_by_id[current_path]
      break unless current_node
    end
    target_node = current_node
    break if target_node

    # retry search in parent scope
    current_scope = current_scope.parent
    break unless current_scope
  end

  if target_node.is_a? Model::Declarations::InterfacedItem
    target_node = target_node.base_item
  end

  target_node
end

#pathString

Returns:



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/expressir/model/model_element.rb', line 24

def path
  # this creates an implicit scope
  return if is_a?(Statements::Alias) || is_a?(Statements::Repeat) || is_a?(Expressions::QueryExpression)

  current_node = self
  path_parts = []
  loop do
    if current_node.class.method_defined?(:id) && !(current_node.is_a? References::SimpleReference)
      path_parts << current_node.id
    end

    current_node = current_node.parent
    break unless current_node
  end

  return if path_parts.empty?

  path_parts.reverse.join(".")
end

#reset_children_by_idnil

Returns:

  • (nil)


89
90
91
92
# File 'lib/expressir/model/model_element.rb', line 89

def reset_children_by_id
  @children_by_id = nil
  nil
end

#to_hash(root_path: nil, formatter: nil, include_empty: nil, select_proc: nil) ⇒ Hash

Parameters:

  • root_path (String) (defaults to: nil)
  • formatter (Express::Formatter) (defaults to: nil)
  • include_empty (Boolean) (defaults to: nil)
  • select_proc (Proc) (defaults to: nil)

Returns:

  • (Hash)


99
100
101
102
103
104
105
106
107
108
109
110
111
112
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
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/expressir/model/model_element.rb', line 99

def to_hash(root_path: nil, formatter: nil, include_empty: nil, select_proc: nil)
  # Filter out entries
  has_filter = !select_proc.nil? && select_proc.is_a?(Proc)
  return nil if has_filter && !select_proc.call(self)

  hash = {}
  hash[CLASS_KEY] = self.class.name

  self.class.model_attrs.each do |variable|
    value = send(variable)
    empty = value.nil? || (value.is_a?(Array) && value.count.zero?)

    # skip empty values
    next unless !empty || include_empty

    value_hash = case value
                 when Array
                   value.map do |v|
                     if v.is_a? ModelElement
                       v.to_hash(
                         root_path: root_path,
                         formatter: formatter,
                         include_empty: include_empty,
                         select_proc: select_proc,
                       )
                     else
                       v
                     end
                   end.compact
                 when ModelElement
                   value.to_hash(
                     root_path: root_path,
                     formatter: formatter,
                     include_empty: include_empty,
                     select_proc: select_proc,
                   )
                 else
                   value
                 end

    hash[variable.to_s] = value_hash unless value_hash.nil?
  end

  if is_a?(Declarations::Schema) && file
    hash[FILE_KEY] = root_path ? Pathname.new(file).relative_path_from(root_path).to_s : file
  end

  if self.class.method_defined?(:source) && formatter
    hash[SOURCE_KEY] = formatter.format(self)
  end

  hash
end

#to_liquid(selected_schemas: nil, options: nil) ⇒ Liquid::Drop

Returns:

  • (Liquid::Drop)


154
155
156
157
158
# File 'lib/expressir/model/model_element.rb', line 154

def to_liquid(selected_schemas: nil, options: nil)
  klass_name = "#{self.class.name.gsub('::Model::', '::Liquid::')}Drop"
  klass = Object.const_get(klass_name)
  klass.new(self, selected_schemas: selected_schemas, options: options)
end

#to_s(no_remarks: false, formatter: nil) ⇒ Object



160
161
162
163
164
165
166
167
# File 'lib/expressir/model/model_element.rb', line 160

def to_s(no_remarks: false, formatter: nil)
  formatter ||= Class.new(Expressir::Express::Formatter) do
    if no_remarks
      def format_remarks(_node); []; end
    end
  end
  formatter.format(self)
end