Module: MotionModelResource::ApiWrapper

Included in:
Task
Defined in:
lib/motion-model-resource/wrapper.rb

Defined Under Namespace

Modules: PublicClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



7
8
9
# File 'lib/motion-model-resource/wrapper.rb', line 7

def self.included(base)
  base.extend(PublicClassMethods)
end

Instance Method Details

#build_hash_from_model(main_key, model) ⇒ Object

Returns a hash with given model



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
# File 'lib/motion-model-resource/wrapper.rb', line 174

def build_hash_from_model(main_key, model)
  hash = {
    main_key => {}
  }
  hash[main_key] = {}

  model.attributes.each do |key, attribute|
    if model.class.has_many_columns.keys.include?(key)
      new_key = attribute.first.class.name.pluralize.underscore
      hash[main_key][new_key] = []
      for a in attribute
        hash[main_key][new_key].push(build_hash_from_model(new_key, a)[new_key])
      end
    elsif attribute.respond_to?(:attributes)
      new_key = attribute.class.name.underscore
      h = attribute.build_hash_from_model(new_key, attribute)
      hash[main_key][new_key] = h[new_key] if h.has_key?(new_key)
    else
      model.class.wrapper[:fields].each do |wrapper_key, wrapper_value|
        hash[main_key][wrapper_key] = attribute if wrapper_value == key
      end
    end
  end

  hash
end

#buildHashFromModel(mainKey, model) ⇒ Object



201
202
203
204
# File 'lib/motion-model-resource/wrapper.rb', line 201

def buildHashFromModel(mainKey, model)
  NSLog "[DEPRECATED - buildHashFromModel] please use build_hash_from_model instead."
  build_hash_from_model mainKey, model
end

#destroy(options = {}, &block) ⇒ Object



140
141
142
143
144
145
146
# File 'lib/motion-model-resource/wrapper.rb', line 140

def destroy(options = {}, &block)
  if block.present?
    destroy_remote(options, &block)
  else
    super
  end
end

#destroy!(options = {}, &block) ⇒ Object Also known as: destroy_remote!

Takes no care of the server response. UNTESTED # TODO write a test



166
167
168
169
170
# File 'lib/motion-model-resource/wrapper.rb', line 166

def destroy!(options = {}, &block)
  options.merge!(force: true)

  destroy_remote(options, &block)
end

#destroy_remote(options = {}, &block) ⇒ Object

Destroys a remote model UNTESTED # TODO write a test



150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/motion-model-resource/wrapper.rb', line 150

def destroy_remote(options = {}, &block)
  raise MotionModelResource::URLNotDefinedError.new "URL is not defined for #{self.class.name}!" unless self.class.respond_to?(:url)
  
  model = self

  BW::HTTP.delete(save_url, {payload: options[:params]}) do |response|
    if response.ok? || options[:force] == true
      model.delete
    end

    block.call if block.present? && block.respond_to?(:call)
  end
end

#fetch(site = nil, params = {}, &block) ⇒ Object

Loads the given URL and parse the JSON for a model. If the model is present, the model will updates. If block given, the block will called, when the the model is saved. The model will be passed as an argument to the block.



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/motion-model-resource/wrapper.rb', line 209

def fetch(site = nil, params = {}, &block)
  raise MotionModelResource::URLNotDefinedError.new "Resource URL ist not defined! (#{self.class.name}.url)" if site.blank? && self.class.try(:url).blank?
  raise MotionModelResource::WrapperNotDefinedError.new "Wrapper is not defined!" unless self.class.respond_to?(:wrapper)

  site = "#{self.class.url}/#{id}" if site.blank?

  model = self
  BW::HTTP.get(site, params) do |response|
    if response.ok? && response.body.present?
      begin
        json = BW::JSON.parse(response.body.to_str)
        model.wrap(json)

        model.save
      rescue BW::JSON::ParserError
        model = nil
      end
    else
      model = nil
    end

    block.call model if block.present? && block.respond_to?(:call)
  end
end

#parse_value(key, value) ⇒ Object

Parses given value for key in the right format for MotionModel. Currently only Date/Time support needed



267
268
269
270
271
272
# File 'lib/motion-model-resource/wrapper.rb', line 267

def parse_value(key, value)
  case self.column_type(key.to_sym)
  when :date, :time then MotionModelResource::DateParser.parse_date value
  else value
  end
end

#parseValue(key, value) ⇒ Object



274
275
276
277
# File 'lib/motion-model-resource/wrapper.rb', line 274

def parseValue(key, value)
  NSLog "[DEPRECATED - parseValue] please use parse_value instead."
  parse_value
end

#save(options = {}, &block) ⇒ Object

Saves the current model. Calls super when block is not given. If block is given, the url method will be needed to call the remote server. The answer of the server will be parsed and stored. If the record is a new one, a POST request will be fired, otherwise a PUT call comes to the server.



103
104
105
106
107
108
109
# File 'lib/motion-model-resource/wrapper.rb', line 103

def save(options = {}, &block)
  if block.present?
    save_remote(options, &block)
  else
    super
  end
end

#save_remote(options, &block) ⇒ Object



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
# File 'lib/motion-model-resource/wrapper.rb', line 111

def save_remote(options, &block)
  raise MotionModelResource::URLNotDefinedError.new "URL is not defined for #{self.class.name}!" unless self.class.respond_to?(:url)

  self.id = nil if self.id.present? && save_action == :create

  params = build_hash_from_model(self.class.name.underscore, self)
  params.merge!(options[:params]) if options[:params].present?

  model = self

  save_remote_call(params) do |response|
    if response.ok? && response.body.present?
      begin
        json = BW::JSON.parse(response.body.to_str)

        model.wrap json
        model.save
        model.touch_sync
      rescue BW::JSON::ParserError
        model = nil
      end
    else
      model = nil
    end

    block.call(model, json) if block.present? && block.respond_to?(:call)
  end
end

#touch_syncObject

When called, the lastSyncAt Column will be set with Time.now (if present)



95
96
97
# File 'lib/motion-model-resource/wrapper.rb', line 95

def touch_sync
  self.lastSyncAt = Time.now if self.respond_to?(:lastSyncAt=)
end

#wrap(model_json) ⇒ Object

Wraps the current model with the given JSON. All the fields found in JSON and self.wrapper will be parsed. Returns true, when no error exists



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/motion-model-resource/wrapper.rb', line 237

def wrap(model_json)
  return unless self.class.respond_to?(:wrapper)

  touch_sync

  self.class.wrapper[:fields].each do |online, local|
    if model_json.respond_to?("key?") && model_json.key?("#{online}")
      value = parse_value(local, model_json["#{online}"])
      self.send("#{local}=", value)
    end
  end

  if self.class.wrapper[:relations].present?
    self.class.wrapper[:relations].each do |relation|
      if model_json.respond_to?("key?") && model_json.key?("#{relation}") && model_json["#{relation}"].present?
        klass_name = column(relation.to_s).instance_variable_get("@options").try(:[], :joined_class_name) || relation.to_s.singularize.camelize

        klass = Object.const_get(klass_name)

        new_relation = klass.update_models(model_json["#{relation}"])
        self.send("#{relation}=", new_relation) rescue NoMethodError # not correct implemented in MotionModel
      end
    end
  end

  self
end