Class: DataActive::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/data_active/parser.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(first_element_name, options = []) ⇒ Parser

Returns a new instance of Parser.



8
9
10
11
12
13
14
15
# File 'lib/data_active/parser.rb', line 8

def initialize(first_element_name, options = [])
  @options = options
  @stack = []
  @first_element_name = first_element_name
  @started_parsing = false
  @processed_entities = {}
  @root_klass = nil
end

Instance Attribute Details

#first_element_nameObject (readonly)

Returns the value of attribute first_element_name.



5
6
7
# File 'lib/data_active/parser.rb', line 5

def first_element_name
  @first_element_name
end

#optionsObject

Returns the value of attribute options.



3
4
5
# File 'lib/data_active/parser.rb', line 3

def options
  @options
end

#root_klassObject (readonly)

Returns the value of attribute root_klass.



6
7
8
# File 'lib/data_active/parser.rb', line 6

def root_klass
  @root_klass
end

#stackObject (readonly)

Returns the value of attribute stack.



4
5
6
# File 'lib/data_active/parser.rb', line 4

def stack
  @stack
end

Instance Method Details

#begin(name) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/data_active/parser.rb', line 22

def begin(name)
  if not @started_parsing and @first_element_name == name
    @started_parsing = true
    begin
      @root_klass = Kernel.const_get(name.camelize)
    rescue
      raise "Unable to find class for '#{name}'"
    end
  end

  process_element(name)

  self
end

#content(value) ⇒ Object



88
89
90
91
92
93
94
95
96
# File 'lib/data_active/parser.rb', line 88

def content(value)
  if @stack.last.class.name == 'DataActive::Entity'
    raise "'#{@stack.last.tag_name}' contains text '#{value}'" if value.strip.length > 0
  else
    @stack.last.content = @stack.last.content.nil? ? value : @stack.last.content + value
  end

  self
end

#create_child_entity(name) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/data_active/parser.rb', line 76

def create_child_entity(name)
  entity = DataActive::Entity.new(name, @options, !@started_parsing)

  if @stack.last.tag_name == name.pluralize
    entity.belongs_to = @stack.last.belongs_to
  else
    entity.belongs_to = @stack.last
  end

  @stack << entity
end

#destroy(klass = self.root_klass) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/data_active/parser.rb', line 125

def destroy(klass = self.root_klass)
  @destroyed ||= []
  if options_include? :any, [:destroy, :sync]
    klass.reflect_on_all_associations.each do |a|
      if [:has_many, :has_many_and_belongs_to, :has_one].include? a.macro and @destroyed.exclude? a.klass.name
        @destroyed << a.klass.name
        destroy(a.klass)
      end
    end

    destroy_records(klass)
    @destroyed << klass.name
  end
end

#destroy_records(klass) ⇒ Object



140
141
142
143
# File 'lib/data_active/parser.rb', line 140

def destroy_records(klass)
  ids = @processed_entities[klass.name.to_sym]
  ids.nil? ? klass.destroy_all : klass.destroy_all([klass.primary_key.to_s + ' not in (?)', ids.collect])
end

#end(name) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/data_active/parser.rb', line 98

def end(name)
  case @stack.last.class.name
    when 'DataActive::Entity'
      end_entity(name)

    when 'DataActive::Attribute'
      end_attribute(name)

    else
      raise "Unhandled class '#{@stack.last.class.name}'"
  end

  self
end

#end_attribute(name) ⇒ Object



113
114
115
116
117
# File 'lib/data_active/parser.rb', line 113

def end_attribute(name)
  raise "Mismatched closing tag '#{name}' when opening tag was #{@stack.last.name}" unless @stack.last.name.eql? name
  attribute = @stack.pop()
  @stack.last.attributes[attribute.name] = attribute if attribute.known
end

#end_entity(name) ⇒ Object



119
120
121
122
123
# File 'lib/data_active/parser.rb', line 119

def end_entity(name)
  raise "Mismatched closing tag '#{name}' when opening tag was #{@stack.last.tag_name}" unless @stack.last.tag_name.eql? name
  entity = @stack.pop()
  store_processed_entity_id(entity.klass, entity.commit()) if not entity.excluded
end

#has_started_parsing?Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/data_active/parser.rb', line 155

def has_started_parsing?
  @started_parsing
end

#klass_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/data_active/parser.rb', line 63

def klass_exists? name
  is_klass = true

  begin
    klass = Kernel.const_get(name.camelize)
    fail unless klass.ancestors.include? ActiveRecord::Base
  rescue
    is_klass = false
  end

  is_klass
end

#options_include?(context, options) ⇒ Boolean

Returns:

  • (Boolean)


17
18
19
20
# File 'lib/data_active/parser.rb', line 17

def options_include? (context, options)
  ((@options & options).count.eql? options.count and context.eql? :all) ||
    ((@options & options).count > 0 and context.eql? :any)
end

#process_element(name) ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/data_active/parser.rb', line 37

def process_element(name)
  if @stack.last.nil?
    @stack << DataActive::Entity.new(name, @options, !@started_parsing)
  elsif @stack.last.class.name == 'DataActive::Entity'
    process_entity_child(name)
  elsif @stack.last.class.name == 'DataActive::Attribute' and not @stack.last.known
    @stack << DataActive::Attribute.new(name, false)
  end
end

#process_entity_child(name) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/data_active/parser.rb', line 47

def process_entity_child(name)
  parent = @stack.last
  if parent.has_association_with? name or parent.tag_name == name.pluralize
    create_child_entity(name)
  elsif parent.has_attribute? name
    @stack << DataActive::Attribute.new(name)
  elsif klass_exists? name
    create_child_entity(name)
  elsif parent.excluded
    @stack << DataActive::Attribute.new(name, false)
  else
    raise "Unknown element '#{name}' for #{parent.klass.name}" if @options.include? :strict
    @stack << DataActive::Attribute.new(name, false)
  end
end

#store_processed_entity_id(klass, id) ⇒ Object



145
146
147
148
149
150
151
152
153
# File 'lib/data_active/parser.rb', line 145

def store_processed_entity_id(klass, id)
  return if id.nil?

  if @processed_entities[klass.name.to_sym].present?
    @processed_entities[klass.name.to_sym] << id
  else
    @processed_entities[klass.name.to_sym] = [id]
  end
end