ooor 1.9.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. data/README.md +23 -71
  2. data/Rakefile +5 -0
  3. data/bin/ooor +1 -0
  4. data/lib/ooor.rb +87 -129
  5. data/lib/ooor/associations.rb +64 -0
  6. data/lib/ooor/base.rb +218 -0
  7. data/lib/{app/models → ooor}/base64.rb +0 -0
  8. data/lib/ooor/connection.rb +37 -0
  9. data/lib/ooor/errors.rb +120 -0
  10. data/lib/ooor/field_methods.rb +153 -0
  11. data/lib/{app → ooor}/helpers/core_helpers.rb +2 -2
  12. data/lib/ooor/locale.rb +13 -0
  13. data/lib/ooor/mini_active_resource.rb +94 -0
  14. data/lib/ooor/model_registry.rb +19 -0
  15. data/lib/ooor/naming.rb +73 -0
  16. data/lib/ooor/rack.rb +114 -0
  17. data/lib/ooor/railtie.rb +41 -0
  18. data/lib/ooor/reflection.rb +537 -0
  19. data/lib/ooor/reflection_ooor.rb +92 -0
  20. data/lib/{app/models → ooor}/relation.rb +61 -22
  21. data/lib/ooor/relation/finder_methods.rb +113 -0
  22. data/lib/ooor/report.rb +53 -0
  23. data/lib/{app/models → ooor}/serialization.rb +18 -6
  24. data/lib/ooor/services.rb +133 -0
  25. data/lib/ooor/session.rb +120 -0
  26. data/lib/ooor/session_handler.rb +63 -0
  27. data/lib/ooor/transport.rb +34 -0
  28. data/lib/ooor/transport/json_client.rb +53 -0
  29. data/lib/ooor/transport/xml_rpc_client.rb +15 -0
  30. data/lib/ooor/type_casting.rb +193 -0
  31. data/lib/ooor/version.rb +8 -0
  32. data/spec/helpers/test_helper.rb +11 -0
  33. data/spec/install_nightly.sh +17 -0
  34. data/spec/ooor_spec.rb +197 -79
  35. data/spec/requirements.txt +19 -0
  36. metadata +58 -20
  37. data/lib/app/models/client_xmlrpc.rb +0 -34
  38. data/lib/app/models/open_object_resource.rb +0 -486
  39. data/lib/app/models/services.rb +0 -47
  40. data/lib/app/models/type_casting.rb +0 -134
  41. data/lib/app/models/uml.rb +0 -210
  42. data/lib/app/ui/action_window.rb +0 -96
  43. data/lib/app/ui/client_base.rb +0 -36
  44. data/lib/app/ui/form_model.rb +0 -88
  45. data/ooor.yml +0 -27
@@ -1,47 +0,0 @@
1
- # OOOR: OpenObject On Ruby
2
- # Copyright (C) 2009-2013 Akretion LTDA (<http://www.akretion.com>).
3
- # Author: Raphaël Valyi
4
- # Licensed under the MIT license, see MIT-LICENSE file
5
-
6
- #proxies for server/openerp/service/web_services.py
7
- module Ooor
8
- module CommonService
9
- %w[ir_get ir_set ir_del about login logout timezone_get get_available_updates get_migration_scripts get_server_environment login_message check_connectivity about get_stats list_http_services version authenticate get_available_updates set_loglevel get_os_time get_sqlcount].each do |meth|
10
- self.instance_eval do
11
- define_method meth do |*args|
12
- get_rpc_client(@base_url + "/common").call(meth, *args)
13
- end
14
- end
15
- end
16
- end
17
-
18
- module DbService
19
- def create(password=@config[:db_password], db_name='ooor_test', demo=true, lang='en_US', user_password=@config[:password] || 'admin')
20
- process_id = get_rpc_client(@base_url + "/db").call("create", password, db_name, demo, lang, user_password)
21
- sleep(2)
22
- while get_progress(password, process_id)[0] != 1
23
- @logger.info "..."
24
- sleep(0.5)
25
- end
26
- global_login('admin', user_password, db_name, false)
27
- end
28
-
29
- %w[get_progress drop dump restore rename db_exist list change_admin_password list_lang server_version migrate_databases create_database duplicate_database].each do |meth|
30
- self.instance_eval do
31
- define_method meth do |*args|
32
- get_rpc_client(@base_url + "/db").call(meth, *args)
33
- end
34
- end
35
- end
36
- end
37
-
38
- module ReportService
39
- %w[report report_get render_report].each do |meth|
40
- self.instance_eval do
41
- define_method meth do
42
- |*args| get_rpc_client(@base_url + "/report").call(meth, *args)
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,134 +0,0 @@
1
- # OOOR: OpenObject On Ruby
2
- # Copyright (C) 2009-2012 Akretion LTDA (<http://www.akretion.com>).
3
- # Author: Raphaël Valyi
4
- # Licensed under the MIT license, see MIT-LICENSE file
5
-
6
- module Ooor
7
- module TypeCasting
8
-
9
- def self.included(base) base.extend(ClassMethods) end
10
-
11
- module ClassMethods
12
-
13
- def openerp_string_domain_to_ruby(string_domain)
14
- eval(string_domain.gsub('(', '[').gsub(')',']'))
15
- end
16
-
17
- def to_openerp_domain(domain)
18
- if domain.is_a?(Hash)
19
- return domain.map{|k,v| [k.to_s, '=', v]}
20
- elsif domain == []
21
- return []
22
- elsif domain.is_a?(Array) && !domain.last.is_a?(Array)
23
- return [domain]
24
- else
25
- return domain
26
- end
27
- end
28
-
29
- def clean_request_args!(args)
30
- if args[-1].is_a? Hash
31
- args[-1] = @ooor.global_context.merge(args[-1])
32
- elsif args.is_a?(Array)
33
- args.map! {|v| value_to_openerp(v)}
34
- args += [@ooor.global_context]
35
- end
36
- cast_map_to_openerp!(args[-2]) if args[-2].is_a? Hash
37
- end
38
-
39
- def value_to_openerp(v)
40
- if v == nil
41
- return false
42
- elsif !v.is_a?(Integer) && !v.is_a?(Float) && v.is_a?(Numeric) && v.respond_to?(:to_f)
43
- return v.to_f
44
- elsif !v.is_a?(Numeric) && !v.is_a?(Integer) && v.respond_to?(:sec) && v.respond_to?(:year)#really ensure that's a datetime type
45
- return "%d-%02d-%02d %02d:%02d:%02d" % [v.year, v.month, v.day, v.hour, v.min, v.sec]
46
- elsif !v.is_a?(Numeric) && !v.is_a?(Integer) && v.respond_to?(:day) && v.respond_to?(:year)#really ensure that's a date type
47
- return "%d-%02d-%02d" % [v.year, v.month, v.day]
48
- elsif v == "false" #may happen with OOORBIT
49
- return false
50
- else
51
- v
52
- end
53
- end
54
-
55
- def cast_map_to_openerp!(map)
56
- map.each do |k, v|
57
- map[k] = value_to_openerp(v)
58
- end
59
- end
60
-
61
- def cast_answer_to_ruby!(answer)
62
- def cast_map_to_ruby!(map)
63
- map.each do |k, v|
64
- if self.fields[k] && v.is_a?(String) && !v.empty?
65
- case self.fields[k]['type']
66
- when 'datetime'
67
- map[k] = DateTime.parse(v)
68
- when 'date'
69
- map[k] = Date.parse(v)
70
- end
71
- end
72
- end
73
- end
74
-
75
- if answer.is_a?(Array)
76
- answer.each {|item| self.cast_map_to_ruby!(item) if item.is_a? Hash}
77
- elsif answer.is_a?(Hash)
78
- self.cast_map_to_ruby!(answer)
79
- else
80
- answer
81
- end
82
- end
83
-
84
- end
85
-
86
- def to_openerp_hash!
87
- cast_relations_to_openerp!
88
- blacklist = %w[id write_date create_date write_ui create_ui]
89
- @attributes.reject {|k, v| blacklist.index(k)}.merge(@associations)
90
- end
91
-
92
- def cast_relations_to_openerp!
93
- @associations.reject! do |k, v| #reject non assigned many2one or empty list
94
- v.is_a?(Array) && (v.size == 0 or v[1].is_a?(String))
95
- end
96
-
97
- def cast_relation(k, v, one2many_associations, many2many_associations)
98
- if one2many_associations[k]
99
- return v.collect! do |value|
100
- if value.is_a?(OpenObjectResource) #on the fly creation as in the GTK client
101
- [0, 0, value.to_openerp_hash!]
102
- else
103
- if value.is_a?(Hash)
104
- [0, 0, value]
105
- else
106
- [1, value, {}]
107
- end
108
- end
109
- end
110
- elsif many2many_associations[k]
111
- return v = [[6, 0, v]]
112
- end
113
- end
114
-
115
- @associations.each do |k, v| #see OpenERP awkward associations API
116
- #already casted, possibly before server error!
117
- next if (v.is_a?(Array) && v.size == 1 && v[0].is_a?(Array)) \
118
- || self.class.many2one_associations[k] \
119
- || !v.is_a?(Array)
120
- new_rel = self.cast_relation(k, v, self.class.one2many_associations, self.class.many2many_associations)
121
- if new_rel #matches a known o2m or m2m
122
- @associations[k] = new_rel
123
- else
124
- self.class.many2one_associations.each do |k2, field| #try to cast the association to an inherited o2m or m2m:
125
- linked_class = self.class.const_get(field['relation'])
126
- new_rel = self.cast_relation(k, v, linked_class.one2many_associations, linked_class.many2many_associations)
127
- @associations[k] = new_rel and break if new_rel
128
- end
129
- end
130
- end
131
- end
132
-
133
- end
134
- end
@@ -1,210 +0,0 @@
1
- # OOOR: OpenObject On Ruby
2
- # Copyright (C) 2009-2012 Akretion LTDA (<http://www.akretion.com>).
3
- # Author: Raphaël Valyi
4
- # Licensed under the MIT license, see MIT-LICENSE file
5
-
6
- module Ooor
7
- module UML
8
- #usage: UML.print_uml or with options: UML.print_uml(:all, :detailed) or MyOpenObjectResource.print_uml or UML.print_uml([list_of_classes], :all, :detailed)
9
-
10
- def print_uml(options={})
11
- ooor = self.class.ooor
12
- UML.print_uml(ooor.config[:models] && ooor.loaded_models.select {|model| ooor.config[:models].index(model.openerp_model)} || ooor.loaded_models, options)
13
- end
14
-
15
- def serve_uml(options={})#TODO port
16
- ooor = self
17
- require 'sinatra'
18
- set :public, File.dirname(__FILE__) + '/../../'
19
-
20
- get '/model/:model_name' do
21
- model_name = params[:model_name]
22
- model = ooor.const_get(model_name)
23
- model.print_uml
24
- s = ""#"Hello world! #{model_name}"
25
- s << "<IMG SRC='/x.png' USEMAP='#UMLbyOOOR' />"
26
- f=File.open('x.map')
27
- f.each_line {|l| s << l}
28
- s
29
- end
30
-
31
- Sinatra::Application.run!
32
- end
33
-
34
- def self.display_fields(clazz)
35
- s = ""
36
- clazz.reload_fields_definition if clazz.fields.empty?
37
- #clazz.fields.sort {|a,b| a[1]['type'] <=> b[1]['type']}.each {|i| s << "+ #{i[1]['type']} : #{i[0]}\\l\\n"}
38
- clazz.fields.sort {|a,b| a[1]['type'] <=> b[1]['type']}.each {|i| s << "<TR><TD COLSPAN=\"2\" BGCOLOR=\"#bed1b8\" ALIGN=\"LEFT\">#{i[0]}</TD><TD ALIGN=\"LEFT\">#{i[1]['type']}</TD></TR>\\l\\n"}
39
- s
40
- end
41
-
42
- def self.print_uml(classes, options={})
43
- # options = options[0] if options[0].is_a?(Array)
44
- # local = (options.index(:all) == nil)
45
- # detailed = (options.index(:detailed) != nil) || local && (options.index(:nodetail) == nil)
46
- return if classes.empty?
47
- local = true
48
- detailed = true
49
- file_name = options[:file_name] || classes[0].name
50
- if classes.size > 8
51
- enabled_targets = classes.map {|i| i.openerp_model} #classes[0].ooor.config[:models] #defines the scope of the UML for option local
52
- else
53
- enabled_targets = classes[0].ooor.config[:models] #defines the scope of the UML for option local
54
- end
55
-
56
- m2o_edges = {}
57
- o2m_edges = {}
58
- m2m_edges = {}
59
- #instead of diplaying several relations of the same kind between two nodes which would bloat the graph,
60
- #we track them all and factor them on a common multiline edge label:
61
- connex_classes = UML.collect_edges(false, local, classes, enabled_targets, m2o_edges, o2m_edges, m2m_edges)
62
- #back links from connex classes:
63
- connex_classes += UML.collect_edges(true, local, connex_classes - classes, classes, m2o_edges, o2m_edges, m2m_edges)
64
-
65
- File.open("#{file_name}.dot", 'w') do |f|
66
- f << <<-eos
67
- digraph UMLbyOOOR {
68
- fontname = "Helvetica"
69
- #{classes.size < 5 && "layout = fdp" || ""}
70
- fontsize = 11
71
- splines = polyline
72
- label = "*** generated by OOOR by www.akretion.com ***"
73
- node [
74
- fontname = "Helvetica"
75
- fontsize = 11
76
- shape = "record"
77
- fillcolor=orange
78
- style="rounded,filled"
79
- ]
80
- edge [
81
- arrowhead = "none"
82
- fontname = "Helvetica"
83
- fontsize = 9
84
- ]
85
- eos
86
-
87
- #UML nodes definitions
88
- ((connex_classes - classes) + classes - [IrModel, IrModel.const_get('ir.model.fields')]).each do |model|
89
- #f << " #{model} [ label = \"{#{model.name}#{detailed ? '|' + display_fields(model) : ''}}\" URL=\"/model/#{model.openerp_model}\"];\n"
90
- f << "#{model}[label=<<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" BGCOLOR=\"#ffffff\"><TR><TD COLSPAN=\"3\" BGCOLOR=\"#9bab96\" ALIGN=\"CENTER\">#{model.name}</TD></TR>#{(classes.index(model) || classes.size == 1) && display_fields(model) || ''}</TABLE>> URL=\"/model/#{model.openerp_model}\"];\n"
91
- end
92
-
93
- #many2one:
94
- f << <<-eos
95
- edge [
96
- headlabel = "1"
97
- taillabel = "n"
98
- ]
99
- eos
100
- m2o_edges.each do |k, v|
101
- reverse_part = v[3].size > 0 ? "\\n/#{v[3].join("\\n")}\"]\n" : "\"]\n"
102
- f << "edge [label = \"#{v[2].join("\\n")}#{reverse_part}"
103
- f << "#{v[0]} -> #{v[1]}\n"
104
- end
105
-
106
- #one2many:
107
- f << <<-eos
108
- edge [
109
- headlabel = "n"
110
- taillabel = "1"
111
- ]
112
- eos
113
- o2m_edges.each do |k, v|
114
- f << "edge [label = \"#{v[3].join("\\n")}\"]\n"
115
- f << "#{v[0]} -> #{v[1]}\n"
116
- end
117
-
118
- #many2many:
119
- f << <<-eos
120
- edge [
121
- headlabel = "n"
122
- taillabel = "n"
123
- ]
124
- eos
125
- m2m_edges.each do |k, v|
126
- reverse_part = v[3].size > 0 ? "\\n/#{v[3].join("\\n")}\"]\n" : "\"]\n"
127
- f << "edge [label = \"#{v[2].join("\\n")}}#{reverse_part}"
128
- f << "#{v[0]} -> #{v[1]}\n"
129
- end
130
-
131
- f << "}"
132
- end
133
-
134
- begin
135
- cmd_line1 = "rm #{file_name}.png"
136
- #system(cmd_line1)
137
- rescue
138
- end
139
- #cmd_line2 = "dot -Tpng uml.dot -o uml.png"
140
- cmd_line2 = "dot -Tcmapx -o#{file_name}.map -Tpng -o#{file_name}.png #{file_name}.dot"
141
- system(cmd_line2)
142
- end
143
-
144
- def self.collect_edges(is_reverse, local, classes, enabled_targets, m2o_edges, o2m_edges, m2m_edges)
145
- connex_classes = Set.new
146
-
147
- classes.each do |model|
148
- model.reload_fields_definition if model.fields.empty?
149
-
150
- #many2one:
151
- model.many2one_associations.each do |k, field|
152
- target = UML.get_target(is_reverse, local, enabled_targets, field, model)
153
- if target
154
- connex_classes.add(target)
155
- if m2o_edges["#{model}-#{target}"]
156
- m2o_edges["#{model}-#{target}"][2] += [k]
157
- else
158
- m2o_edges["#{model}-#{target}"] = [model, target, [k], []]
159
- end
160
- end
161
-
162
- end
163
- end
164
-
165
- classes.each do |model|
166
- #one2many:
167
- model.one2many_associations.each do |k, field|
168
- target = UML.get_target(is_reverse, local, enabled_targets, field, model)
169
- if target
170
- connex_classes.add(target)
171
- if m2o_edges["#{target}-#{model}"]
172
- m2o_edges["#{target}-#{model}"][3] += [k]
173
- elsif o2m_edges["#{model}-#{target}"]
174
- o2m_edges["#{model}-#{target}"][3] += [k]
175
- else
176
- o2m_edges["#{model}-#{target}"] = [model, target, [], [k]]
177
- end
178
- end
179
- end
180
-
181
- #many2many:
182
- model.many2many_associations.each do |k, field|
183
- target = UML.get_target(is_reverse, local, enabled_targets, field, model)
184
- if target
185
- connex_classes.add(target)
186
- if m2m_edges["#{model}-#{target}"]
187
- m2m_edges["#{model}-#{target}"][2] += [k]
188
- elsif m2m_edges["#{target}-#{model}"]
189
- m2m_edges["#{target}-#{model}"][3] += [k]
190
- else
191
- m2m_edges["#{model}-#{target}"] = [model, target, [k], []]
192
- end
193
- end
194
- end
195
-
196
- end
197
- connex_classes
198
- end
199
-
200
- private
201
-
202
- def self.get_target(is_reverse, local, enabled_targets, field, model)
203
- if (is_reverse && !local) || (!enabled_targets) || enabled_targets.index(field['relation'])
204
- model.const_get(field['relation'])
205
- else
206
- false
207
- end
208
- end
209
- end
210
- end
@@ -1,96 +0,0 @@
1
- # OOOR: OpenObject On Ruby
2
- # Copyright (C) 2009-2012 Akretion LTDA (<http://www.akretion.com>).
3
- # Author: Raphaël Valyi
4
- # Licensed under the MIT license, see MIT-LICENSE file
5
-
6
- module Ooor
7
- class ActionWindow
8
- class << self
9
- attr_accessor :klass, :openerp_act_window, :views
10
-
11
- def from_menu(menu)
12
- act_win_class = Class.new(ActionWindow)
13
- act_win_class.openerp_act_window = menu.action
14
- act_win_class.klass = menu.class.const_get(menu.action.res_model)
15
- act_win_class.views = {}
16
- act_win_class
17
- end
18
-
19
- def from_act_window(act_window)
20
- act_win_class = Class.new(ActionWindow)
21
- act_win_class.openerp_act_window = act_window
22
- act_win_class.klass = act_window.class.const_get(act_window.res_model)
23
- act_win_class.views = {}
24
- act_win_class
25
- end
26
-
27
- def from_model(act_window_param)
28
- act_win_class = Class.new(ActionWindow)
29
- act_win_class.openerp_act_window = IrActionsAct_window.find(:first, :domain=>[['res_model', '=', act_window_param.openerp_model]])
30
- act_win_class.klass = act_window_param
31
- act_win_class.views = {}
32
- act_win_class
33
- end
34
-
35
- def get_url(mode='tree', id=nil, tab=nil) #TODO deal with visible tab in Javascript, possibly hacking web-client
36
- url = "#{self.ooor.base_url.gsub("xmlrpc", "web/webclient/home")}#action_id=#{@openerp_act_window.id}&view_type=#{mode}"
37
- url += "&id=#{id}" if id
38
- end
39
-
40
- def get_view_id(mode)
41
- ids = IrActionsAct_window.read(@openerp_act_window.id, ["view_ids"])["view_ids"]
42
- IrActionsAct_windowView.read(ids, ["view_mode", "view_id"]).each do |view_hash|
43
- return view_hash["view_id"][0] if view_hash["view_id"] && view_hash["view_mode"] == mode.to_s
44
- end
45
- IrUiView.search([['model', '=', act_window_param.openerp_model], ['type', '=', mode.to_s]])
46
- end
47
-
48
- def get_fields(mode)
49
- @views[mode] ||= @klass.fields_view_get(get_view_id(mode), mode)
50
- @views[mode]['fields'] #TODO order by occurrence in view XML
51
- end
52
-
53
- def column_names
54
- reload_fields_definition
55
- @column_names ||= ["id"] + get_fields('tree').keys()
56
- end
57
-
58
- def columns_hash
59
- reload_fields_definition
60
- unless @column_hash
61
- @column_hash = {"id" => {"string"=>"Id", "type"=>"integer"}}.merge(get_fields('tree'))
62
- def @column_hash.type
63
- col_type = @column_hash['type'].to_sym #TODO mapping ?
64
- col_type == :char && :string || col_type
65
- end
66
- end
67
- @column_hash
68
- end
69
-
70
- def primary_key
71
- "id"
72
- end
73
-
74
- def get_arch(mode)
75
- #TODO
76
- end
77
-
78
- def open(mode='tree', ids=nil)#TODO: fix!
79
- if view_mode.index(mode)
80
- the_view_id = false
81
- relations['views'].each do |tuple|
82
- the_view_id = tuple[0] if tuple[1] == mode
83
- end
84
- self.class.ooor.build_object_view(self.class.ooor.const_get(res_model), the_view_id, mode, domain || [], ids, {})
85
- end
86
- end
87
-
88
- def method_missing(method, *args, &block)
89
- @klass.send(method, *args, &block)
90
- end
91
-
92
- end
93
-
94
-
95
- end
96
- end