ooor 1.2.2 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,13 +13,21 @@ class OpenObjectResource < ActiveResource::Base
13
13
 
14
14
  cattr_accessor :logger
15
15
  attr_accessor :openerp_id, :info, :access_ids, :name, :openerp_model, :field_ids, :state, #model class attributes assotiated to the OpenERP ir.model
16
- :fields, :fields_defined, :many2one_relations, :one2many_relations, :many2many_relations,
16
+ :fields, :fields_defined, :many2one_relations, :one2many_relations, :many2many_relations, :relations_keys,
17
17
  :openerp_database, :user_id, :scope_prefix, :ooor
18
18
 
19
19
  def class_name_from_model_key(model_key=self.openerp_model)
20
20
  self.scope_prefix + model_key.split('.').collect {|name_part| name_part.capitalize}.join
21
21
  end
22
22
 
23
+ #similar to Object#const_get but for OpenERP model key
24
+ def const_get(model_key)
25
+ klass_name = class_name_from_model_key(model_key)
26
+ klass = Object.const_defined?(klass_name) ? Object.const_get(klass_name) : @ooor.define_openerp_model(model_key, nil, nil, nil, nil, self.scope_prefix)
27
+ klass.reload_fields_definition unless klass.fields_defined
28
+ klass
29
+ end
30
+
23
31
  def reload_fields_definition(force = false)
24
32
  if not (self.to_s.match('IrModel') || self.to_s.match('IrModelFields')) and (force or not @fields_defined)#TODO have a way to force reloading @field_ids too eventually
25
33
  fields = Object.const_get(self.scope_prefix + 'IrModelFields').find(@field_ids)
@@ -36,6 +44,7 @@ class OpenObjectResource < ActiveResource::Base
36
44
  @fields[field.attributes['name']] = field
37
45
  end
38
46
  end
47
+ @relations_keys = @many2one_relations.merge(@one2many_relations).merge(@many2many_relations).keys
39
48
  logger.info "#{fields.size} fields loaded in model #{self.class}"
40
49
  end
41
50
  @fields_defined = true
@@ -113,15 +122,7 @@ class OpenObjectResource < ActiveResource::Base
113
122
  raise
114
123
  end
115
124
 
116
- def method_missing(method_symbol, *arguments) return self.rpc_execute(method_symbol.to_s, *arguments) end
117
-
118
- def load_relation(model_key, ids, scope_prefix, *arguments)
119
- options = arguments.extract_options!
120
- class_name = class_name_from_model_key(model_key)
121
- @ooor.define_openerp_model(model_key, nil, nil, nil, nil, scope_prefix) unless Object.const_defined?(class_name)
122
- relation_model_class = Object.const_get(class_name)
123
- relation_model_class.send :find, ids, :fields => options[:fields] || [], :context => options[:context] || {}
124
- end
125
+ def method_missing(method_symbol, *arguments) self.rpc_execute(method_symbol.to_s, *arguments) end
125
126
 
126
127
 
127
128
  # ******************** finders low level implementation ********************
@@ -226,15 +227,13 @@ class OpenObjectResource < ActiveResource::Base
226
227
  end
227
228
 
228
229
  @relations.each do |k, v| #see OpenERP awkward relations API
230
+ next if v.is_a?(Array) && v.size == 1 && v[0].is_a?(Array) #already casted, possibly before server error!
229
231
  new_rel = self.cast_relation(k, v, self.class.one2many_relations, self.class.many2many_relations)
230
232
  if new_rel #matches a known o2m or m2m
231
233
  @relations[k] = new_rel
232
234
  else
233
235
  self.class.many2one_relations.each do |k2, field| #try to cast the relation to na inherited o2m or m2m:
234
- class_name = self.class.class_name_from_model_key(field.relation)
235
- self.class.ooor.define_openerp_model(field.relation, nil, nil, nil, nil, self.class.scope_prefix) unless Object.const_defined?(class_name)
236
- linked_class = Object.const_get(class_name)
237
- linked_class.reload_fields_definition unless linked_class.fields_defined
236
+ linked_class = self.class.const_get(field.relation)
238
237
  new_rel = self.cast_relation(k, v, linked_class.one2many_relations, linked_class.many2many_relations)
239
238
  @relations[k] = new_rel and break if new_rel
240
239
  end
@@ -244,7 +243,7 @@ class OpenObjectResource < ActiveResource::Base
244
243
 
245
244
  def reload_from_record!(record) load(record.attributes, record.relations) end
246
245
 
247
- def load(attributes, relations={})
246
+ def load(attributes, relations={})#an attribute might actually be a relation too, will be determined here
248
247
  self.class.reload_fields_definition() unless self.class.fields_defined
249
248
  raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
250
249
  @prefix_options, attributes = split_options(attributes)
@@ -253,8 +252,7 @@ class OpenObjectResource < ActiveResource::Base
253
252
  @loaded_relations = {}
254
253
  attributes.each do |key, value|
255
254
  skey = key.to_s
256
- if self.class.many2one_relations.has_key?(skey) || self.class.one2many_relations.has_key?(skey) ||
257
- self.class.many2many_relations.has_key?(skey) || value.is_a?(Array)
255
+ if self.class.relations_keys.index(skey) || value.is_a?(Array)
258
256
  relations[skey] = value #the relation because we want the method to load the association through method missing
259
257
  else
260
258
  case value
@@ -270,6 +268,12 @@ class OpenObjectResource < ActiveResource::Base
270
268
  self
271
269
  end
272
270
 
271
+ def load_relation(model_key, ids, *arguments)
272
+ options = arguments.extract_options!
273
+ related_class = self.class.const_get(model_key)
274
+ related_class.send :find, ids, :fields => options[:fields] || [], :context => options[:context] || {}
275
+ end
276
+
273
277
  def display_available_fields
274
278
  self.class.logger.debug ""
275
279
  self.class.logger.debug "*** DIRECTLY AVAILABLE FIELDS ON OBJECT #{self} ARE: ***\n"
@@ -323,7 +327,7 @@ class OpenObjectResource < ActiveResource::Base
323
327
  self.class.logger.info result["warning"]["title"]
324
328
  self.class.logger.info result["warning"]["message"]
325
329
  end
326
- load({field_name => field_value}.merge(result["value"]))
330
+ load(@attributes.merge({field_name => field_value}).merge(result["value"]), @relations)
327
331
  end
328
332
 
329
333
  #wrapper for OpenERP exec_workflow Business Process Management engine
@@ -337,17 +341,19 @@ class OpenObjectResource < ActiveResource::Base
337
341
  OpenObjectWizard.new(wizard_name, result[0], result[1], [self], self.class.ooor.global_context)
338
342
  end
339
343
 
344
+ def type() method_missing(:type) end #skips deprecated Object#type method
345
+
340
346
 
341
347
  # ******************** fake associations like much like ActiveRecord according to the cached OpenERP data model ********************
342
348
 
343
349
  def relationnal_result(method_name, *arguments)
344
350
  self.class.reload_fields_definition unless self.class.fields_defined
345
351
  if self.class.many2one_relations.has_key?(method_name)
346
- self.class.load_relation(self.class.many2one_relations[method_name].relation, @relations[method_name][0], self.class.scope_prefix, *arguments)
352
+ load_relation(self.class.many2one_relations[method_name].relation, @relations[method_name][0], *arguments)
347
353
  elsif self.class.one2many_relations.has_key?(method_name)
348
- self.class.load_relation(self.class.one2many_relations[method_name].relation, @relations[method_name], self.class.scope_prefix, *arguments)
354
+ load_relation(self.class.one2many_relations[method_name].relation, @relations[method_name], *arguments)
349
355
  elsif self.class.many2many_relations.has_key?(method_name)
350
- self.class.load_relation(self.class.many2many_relations[method_name].relation, @relations[method_name], self.class.scope_prefix, *arguments)
356
+ load_relation(self.class.many2many_relations[method_name].relation, @relations[method_name], *arguments)
351
357
  else
352
358
  false
353
359
  end
@@ -355,28 +361,31 @@ class OpenObjectResource < ActiveResource::Base
355
361
 
356
362
  def method_missing(method_symbol, *arguments)
357
363
  method_name = method_symbol.to_s
358
- return super if attributes.has_key?(method_name) or attributes.has_key?(method_name.first(-1))
359
- if method_name.end_with?('=') && @relations[method_name.sub('=', '')]
360
- @relations[method_name.sub('=', '')] = *arguments
361
- return
362
- end
364
+ is_assign = method_name.end_with?('=')
365
+ method_key = method_name.sub('=', '')
366
+ return super if attributes.has_key?(method_key)
367
+
368
+ @relations[method_key] = arguments[0] and return if is_assign && self.class.relations_keys.index(method_key)
369
+ @attributes[method_key] = arguments[0] and return if is_assign && self.class.fields.keys.index(method_key)
370
+
363
371
  return @loaded_relations[method_name] if @loaded_relations.has_key?(method_name)
364
372
  return false if @relations.has_key?(method_name) and !@relations[method_name]
365
373
 
366
374
  result = relationnal_result(method_name, *arguments)
367
- if result
368
- @loaded_relations[method_name] = result
369
- return result
370
- elsif !self.class.many2one_relations.empty? #maybe the relation is inherited or could be inferred from a related field
371
- self.class.many2one_relations.each do |k, field|
372
- if @relations[k]
373
- @loaded_relations[k] ||= self.class.load_relation(field.relation, @relations[k][0], self.class.scope_prefix, *arguments)
374
- model = @loaded_relations[k]
375
- model.loaded_relations[method_name] ||= model.relationnal_result(method_name, *arguments)
376
- return model.loaded_relations[method_name] if model.loaded_relations[method_name]
377
- end
375
+ @loaded_relations[method_name] = result and return result if result
376
+
377
+ #maybe the relation is inherited or could be inferred from a related field
378
+ self.class.many2one_relations.each do |k, field| #TODO could be recursive eventually
379
+ if @relations[k]
380
+ @loaded_relations[k] ||= load_relation(field.relation, @relations[k][0], *arguments)
381
+ model = @loaded_relations[k]
382
+ model.loaded_relations[method_key] ||= model.relationnal_result(method_key, *arguments)
383
+ return model.loaded_relations[method_key] if model.loaded_relations[method_key]
384
+ elsif is_assign
385
+ klazz = self.class.const_get(field.relation)
386
+ @relations[method_key] = arguments[0] and return if klazz.relations_keys.index(method_key)
387
+ @attributes[method_key] = arguments[0] and return if klazz.fields.keys.index(method_key)
378
388
  end
379
- super
380
389
  end
381
390
 
382
391
  rescue
@@ -172,9 +172,9 @@ module UML
172
172
 
173
173
  def self.get_target(is_reverse, local, enabled_targets, field, model)
174
174
  if (is_reverse && !local) || (!enabled_targets) || enabled_targets.index(field.relation)
175
- target_name = model.class_name_from_model_key(field.relation)
176
- return Object.const_defined?(target_name) ? Object.const_get(target_name) : model.ooor.define_openerp_model(field.relation, nil, nil, nil, nil, model.scope_prefix)
175
+ model.const_get(field.relation)
176
+ else
177
+ false
177
178
  end
178
- return false
179
179
  end
180
180
  end
@@ -77,6 +77,7 @@ class Ooor
77
77
  klass.many2one_relations = {}
78
78
  klass.one2many_relations = {}
79
79
  klass.many2many_relations = {}
80
+ klass.relations_keys = []
80
81
  klass.fields = {}
81
82
  klass.scope_prefix = scope_prefix
82
83
  model_class_name = klass.class_name_from_model_key
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ooor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Raphael Valyi - www.akretion.com