Class: Goldencobra::Import

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/goldencobra/import.rb

Constant Summary collapse

EncodingTypes =
["UTF-8","ISO-8859-1", "ISO-8859-2", "ISO-8859-16", "US-ASCII", "Big5", "UTF-16BE", "IBM437", "Windows-1252"]
BlockedAttributes =
["id", "created_at", "updated_at", "url_name", "slug", "upload_id", "images", "article_images", "article_widgets", "permissions", "versions"]
DataHandling =
[["bestehenden Datensatz suchen oder erstellen","update"],["Datensatz immer neu anlegen", "create"]]
DataFunctions =
["Default", "Static Value", "DateTime"]

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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



71
72
73
74
75
# File 'app/models/goldencobra/import.rb', line 71

def method_missing(meth, *args, &block)
  if meth.to_s.include?("assignment_") && self.assignment.present?
    self.assignment[meth.to_s.split("_")[1]]
  end
end

Instance Method Details

#add_current_submodel_to_model(current_object, current_sub_object, sub_attribute_name) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'app/models/goldencobra/import.rb', line 273

def add_current_submodel_to_model(current_object, current_sub_object, sub_attribute_name )
  if sub_attribute_name.present? && current_object.present? && current_sub_object.present?
    begin
      if current_object.send(sub_attribute_name).class == Array
        current_object.send(sub_attribute_name) << current_sub_object
      else
        eval("current_object.#{sub_attribute_name} = current_sub_object")
      end
    rescue  => e
      logger.warn("***"*20)
      logger.warn("Current Submodel cannot be added to model: #{sub_attribute_name} #{e}")
    end
  end
end

#analyze_csvObject



38
39
40
41
42
43
44
45
46
47
48
49
# File 'app/models/goldencobra/import.rb', line 38

def analyze_csv
  begin
    result = []
    data = CSV.read(self.upload.image.path, "r:#{self.encoding_type}", {:col_sep => self.separator})
    data.first.each_with_index do |a, index|
      result << [a,index.to_s]
    end
  rescue
    result = []
  end
  @analyze_csv ||= result
end

#assignment_exists?(value) ⇒ Boolean

Returns:

  • (Boolean)


305
306
307
# File 'app/models/goldencobra/import.rb', line 305

def assignment_exists?(value)
  value.present? && ((value['data_function'].present? && value['data_function'] != 'Default') || value['csv'].present?)
end

#create_or_update_target_model(assignment_groups_definition, target_model, master_data_attribute_assignments, data_row) ⇒ Object



261
262
263
264
265
266
267
268
269
270
271
# File 'app/models/goldencobra/import.rb', line 261

def create_or_update_target_model(assignment_groups_definition,target_model,master_data_attribute_assignments, data_row )
  if self.assignment_groups.present?
    if self.assignment_groups[assignment_groups_definition] == "create"
      return target_model.constantize.new
    else
      return find_or_create_by_attributes(master_data_attribute_assignments, data_row, target_model)
    end
  else
    raise "self.assignment_groups is blank! #{}"
  end
end

#data_rowsObject



51
52
53
54
55
56
57
# File 'app/models/goldencobra/import.rb', line 51

def data_rows
  begin
    CSV.read(self.upload.image.path, "r:#{self.encoding_type}", {:col_sep => self.separator})
  rescue
    [["Error in reading File: Please check encoding type"]]
  end
end

#find_or_create_by_attributes(attribute_assignments, row, model_name) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'app/models/goldencobra/import.rb', line 197

def find_or_create_by_attributes(attribute_assignments, row, model_name)
  find_condition = []
  attribute_assignments.each do |attribute_name,value|
    if assignment_exists?(value)
      data_to_search = parse_data_with_method(value['csv'],value['data_function'],value['option'], model_name, row)
      if data_to_search.blank?
        find_condition << "#{attribute_name} = '#{data_to_search}'"
      end
    end
  end
  find_master = model_name.constantize.where(find_condition.join(' AND '))

  if find_master.count == 0
    return model_name.constantize.new
  elsif find_master.count == 1
    return find_master.first
  else
    self.result << "Dieses Object exisitiert schon mehrfach, keine eindeutige Zuweisung möglich: Erstes Objekt wird verwendet (#{row})"
    return find_master.first
  end
end

#get_association_names(current_target_model = nil) ⇒ Object



63
64
65
66
67
68
69
# File 'app/models/goldencobra/import.rb', line 63

def get_association_names(current_target_model=nil)
  if current_target_model.present?
    current_target_model.reflect_on_all_associations.collect { |r| r.name }.delete_if{|a| Goldencobra::Import::BlockedAttributes.include?(a.to_s) }
  else
    self.target_model.constantize.reflect_on_all_associations.collect { |r| r.name }.delete_if{|a| Goldencobra::Import::BlockedAttributes.include?(a.to_s) }
  end
end

#get_associations_for_current_object(current_object) ⇒ Object



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'app/models/goldencobra/import.rb', line 289

def get_associations_for_current_object(current_object)
  h = {}
  ass = current_object.class.reflect_on_all_associations.collect { |r| [r.name, r.macro] }
  ass.each do |a|
    #if a[1].to_s == "has_many"
      a_class_name = current_object.reflections[a[0].to_sym].class_name
      h[a_class_name] ||= []
      h[a_class_name] << a[0]
    # elsif current_object.respond_to?("build_#{a[0]}")
    #   h[current_object.send("build_#{a[0]}").class.to_s] ||= []
    #   h[current_object.send("build_#{a[0]}").class.to_s] << a[0]
    # end
  end
  return h
end

#get_model_attributesObject



59
60
61
# File 'app/models/goldencobra/import.rb', line 59

def get_model_attributes
  @get_model_attributes ||= eval("#{self.target_model}.new.attributes").delete_if{|a| BlockedAttributes.include?(a) }.keys
end

#init_nested_attributesObject



192
193
194
195
# File 'app/models/goldencobra/import.rb', line 192

def init_nested_attributes
  self.upload ||= build_upload
  self.assignment ||= {}
end

#parse_data_with_method(data, data_function, data_option, model_name = "", row) ⇒ Object

SELECT COUNT(*) FROM ‘providers` WHERE (title = ’Sportgemeinschaft Siemens Berlin e. V.‘ AND category_id = ’3’ AND metatag_external_id = ‘1804’ AND metatag_created_at = ‘06.01.2010’)



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
# File 'app/models/goldencobra/import.rb', line 221

def parse_data_with_method(data,data_function,data_option, model_name="", row)
  if data.present?
    row_data = row[data.to_i]
    conv = Iconv.new("UTF-8", self.encoding_type)
    output = conv.iconv(row_data)
  else
    output = nil
  end
  if data_function == "Default"
    return output
  elsif data_function == "Static Value"
    return data_option
  elsif data_function == "DateTime"
    if output.present? && data_option.present?
      return DateTime.strptime(output,data_option).strftime("%Y-%m-%d %H:%M")
    else
      return output
    end
  elsif model_name.present?
    if data_function.present? && model_name.constantize.respond_to?(data_function.parameterize.underscore)
      return model_name.constantize.send(data_function.parameterize.underscore, row_data, data_option )
    else
      return ""
    end
  else
    return ""
  end
end

#remove_emty_assignmentsObject



250
251
252
253
254
255
256
257
258
# File 'app/models/goldencobra/import.rb', line 250

def remove_emty_assignments
  self.assignment.each do |key, values|
    self.assignment[key].delete_if{|k,v| v['data_function'] == "Default" && v['csv'].blank?} if self.assignment[key].present? && self.assignment[key].class == Array
    if self.assignment[key].blank?
      self.assignment.delete(key)
    end
  end
  self.assignment
end

#run!Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'app/models/goldencobra/import.rb', line 82

def run!
  self.result = []
  count = 0
  all_data_attribute_assignments = remove_emty_assignments
  master_data_attribute_assignments = all_data_attribute_assignments[self.target_model]
  import_data_attribute_assignments = all_data_attribute_assignments["Goldencobra::ImportMetadata"]
  #all_data_attribute_assignments.delete("Goldencobra::ImportMetadata")

  data = CSV.read(self.upload.image.path, "r:#{self.encoding_type}", {:col_sep => self.separator})
  data.each do |row|
    if count == 0
      count = 1
      next
    end
    master_object = nil
    current_object = nil
    #Neues Object anlegen oder bestehendes suchen und aktualisieren
    master_object = create_or_update_target_model(self.target_model,self.target_model,master_data_attribute_assignments, row )

    #Wenn es aus irgend einem Grund kein Master Object gibt
    raise "No Master Object found" if master_object.blank?

    #Gehe alle Zugewiesenen Attribute durch und erzeuge die Datensätze
    all_data_attribute_assignments.each do |key_string,sub_assignments|
      raise "all_data_attribute_assignments is blank!" if all_data_attribute_assignments.blank?
      key = key_string.split("_")[0]
      key_relation_name = key_string.split("_")[1]
      #Metadaten werden zu jedem Datensatz separat erfasst
      next if key == "Goldencobra::ImportMetadata"
      if key == self.target_model
        current_object = master_object
      else
        unless key_relation_name.present?
          key_relation_name = get_associations_for_current_object(current_object)[key]
          key_relation_name = key_relation_name.first if key_relation_name.class == Array
        end
        current_object = create_or_update_target_model(key,key,sub_assignments, row )
        add_current_submodel_to_model(master_object, current_object, key_relation_name )
      end

      #Wenn es aus irgend einem Grund kein Current object gibt
      raise "current_object is blank: #{key}, #{sub_assignments}, #{row}" if current_object.blank?

      #die Werte für das Object werden gesetzt
      sub_assignments.each do |attribute_name,value|
        #Wenn das Aktuell zu speichernde Attribute kein attribute sondern eine Assoziazion zu einem anderen Model ist...
        sub_assoziations = get_associations_for_current_object(current_object)
        if sub_assoziations.map{|a| a[0]}.include?(attribute_name)
          self.assignment["#{current_object.class.to_s}"][attribute_name].each do |sub_attribute_name, sub_value|
            if current_object.send(sub_attribute_name).class == Array
              #Bei einer has_many beziehung
              cass_related_sub_model = eval("current_object.#{sub_attribute_name}.new")
            else
              #bei einer belongs_to Beziehung
              cass_related_sub_model = current_object.send("build_#{sub_attribute_name}")
            end

            sub_sub_assignments = self.assignment["#{current_object.class.to_s}"][attribute_name][sub_attribute_name]
            #Neues Unter Object anlegen oder bestehendes suchen und aktualisieren
            current_sub_object = create_or_update_target_model("#{current_object.class.to_s}_#{cass_related_sub_model.class.to_s}_#{sub_attribute_name}",attribute_name,sub_sub_assignments, row )
            puts current_sub_object.inspect
            #Das aktuelle unterobjeect wird dem Elternelement hinzugefügt
            # wenn es eine has_many beziehung ist:

            puts sub_sub_assignments.inspect
            sub_sub_assignments.each do |sub_ass_item|
              if assignment_exists?(value)
                sub_data_to_save = parse_data_with_method(value['csv'],value['data_function'],value['option'], current_sub_object.class.to_s, row)
                current_sub_object.send("#{sub_ass_item}=", sub_data_to_save) if sub_data_to_save.blank?
                puts current_sub_object.inspect
              end
            end
            if current_sub_object.save
              add_current_submodel_to_model(current_object, current_sub_object, sub_attribute_name )
            end
          end
        else
          if assignment_exists?(value)
            data_to_save = parse_data_with_method(value['csv'],value['data_function'],value['option'], current_object.class.to_s, row)
          end
          #Wenn das Aktuell zu speichernde Attribute wirklich ein Attribute ist, kann es gespeichert werden
          current_object.send("#{attribute_name}=", data_to_save) if data_to_save.present?
        end
      end
      #Das Object wird gespeichert
      if current_object.save
        #Create ImportMetadata
         = Goldencobra::ImportMetadata.new
        import_data_attribute_assignments.each do |attribute_name,value|
          data_to_save = parse_data_with_method(value['csv'],value['data_function'],value['option'], "Goldencobra::ImportMetadata", row)
          next if data_to_save.blank?
          .send("#{attribute_name}=", data_to_save)
        end
        .importmetatagable = current_object
        .save
      else
        #self.result << "#{count} - SubObject: #{current_object.errors.messages}"
      end
    end
    #Das Elternelement wird gespeichert
    unless master_object.save
      raise "master_object could not be saved! #{master_object.errors.inspect}"
      self.result << "#{count} - #{master_object.errors.messages}"
    end
    count += 1
  end
  self.save
end

#statusObject



77
78
79
# File 'app/models/goldencobra/import.rb', line 77

def status
  @status ||="ready to import"
end