ooor 1.4.2 → 1.5.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.
@@ -0,0 +1,145 @@
1
+ # OOOR: Open Object On Rails
2
+ # Copyright (C) 2009-2011 Akretion LTDA (<http://www.akretion.com>).
3
+ # Author: Raphaël Valyi
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Affero General Public License as
7
+ # published by the Free Software Foundation, either version 3 of the
8
+ # License, or (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Affero General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Affero General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ #TODO chainability of where via scopes
19
+ #TODO include relations for single read
20
+
21
+ module Ooor
22
+ # = Similar to Active Record Relation
23
+ class Relation
24
+
25
+ attr_reader :klass, :loaded
26
+ attr_accessor :context, :count_field, :includes_values, :eager_load_values, :preload_values,
27
+ :select_values, :group_values, :order_values, :reorder_flag, :joins_values, :where_values, :having_values,
28
+ :limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value, :from_value
29
+ alias :loaded? :loaded
30
+
31
+ def build_where(opts, other = [])
32
+ case opts
33
+ when Array
34
+ [opts]
35
+ when Hash
36
+ opts.keys.map {|key|["#{key}", "=", opts[key]]}
37
+ end
38
+ end
39
+
40
+ def where(opts, *rest)
41
+ relation = clone
42
+ relation.where_values += build_where(opts, rest) unless opts.blank?
43
+ relation
44
+ end
45
+
46
+ # def having(*args)
47
+ # relation = clone
48
+ # relation.having_values += build_where(*args) unless args.blank?
49
+ # relation
50
+ # end
51
+
52
+ def limit(value)
53
+ relation = clone
54
+ relation.limit_value = value
55
+ relation
56
+ end
57
+
58
+ def offset(value)
59
+ relation = clone
60
+ relation.offset_value = value
61
+ relation
62
+ end
63
+
64
+ def order(*args)
65
+ relation = clone
66
+ relation.order_values += args.flatten unless args.blank?
67
+ relation
68
+ end
69
+
70
+ def count(column_name = nil, options = {})
71
+ column_name, options = nil, column_name if column_name.is_a?(Hash)
72
+ calculate(:count, column_name, options)
73
+ end
74
+
75
+ def initialize(klass)
76
+ @klass = klass
77
+ @where_values = []
78
+ @loaded = false
79
+ @context = {}
80
+ @count_field = false
81
+ @limit_value = false
82
+ @offset_value = false
83
+ @order_values = []
84
+ end
85
+
86
+ def new(*args, &block)
87
+ #TODO inject current domain in *args
88
+ @klass.new(*args, &block)
89
+ end
90
+
91
+ def reload
92
+ reset
93
+ to_a # force reload
94
+ self
95
+ end
96
+
97
+ def initialize_copy(other)
98
+ reset
99
+ end
100
+
101
+ def reset
102
+ @first = @last = @to_sql = @order_clause = @scope_for_create = @arel = @loaded = nil
103
+ @should_eager_load = @join_dependency = nil
104
+ @records = []
105
+ self
106
+ end
107
+
108
+ # A convenience wrapper for <tt>find(:all, *args)</tt>. You can pass in all the
109
+ # same arguments to this method as you can to <tt>find(:all)</tt>.
110
+ def all(*args)
111
+ #args.any? ? apply_finder_options(args.first).to_a : to_a TODO
112
+ to_a
113
+ end
114
+
115
+ def to_a
116
+ return @records if loaded?
117
+ if @order_values.empty?
118
+ search_order = false
119
+ else
120
+ search_order = @order_values.join(", ")
121
+ end
122
+ ids = @klass.rpc_execute('search', @where_values, @offset_value, @limit_value, search_order, @context, @count_field)
123
+ @records = @klass.find(ids)
124
+ @loaded = true
125
+ @records
126
+ end
127
+
128
+ def eager_loading?
129
+ false
130
+ end
131
+
132
+ protected
133
+
134
+ def method_missing(method, *args, &block)
135
+ if Array.method_defined?(method)
136
+ to_a.send(method, *args, &block)
137
+ elsif @klass.respond_to?(method)
138
+ @klass.send(method, *args, &block)
139
+ else
140
+ @klass.rpc_execute(method.to_s, to_a.map {|record| record.id}, *args)
141
+ end
142
+ end
143
+
144
+ end
145
+ end
@@ -0,0 +1,119 @@
1
+ module Ooor
2
+ module TypeCasting
3
+
4
+ def self.included(base) base.extend(ClassMethods) end
5
+
6
+ module ClassMethods
7
+
8
+ def openerp_string_domain_to_ruby(string_domain)
9
+ eval(string_domain.gsub('(', '[').gsub(')',']'))
10
+ end
11
+
12
+ def to_openerp_domain(domain)
13
+ if domain.is_a?(Hash)
14
+ return domain.map{|k,v| [k.to_s, '=', v]}
15
+ elsif domain == []
16
+ return []
17
+ elsif domain.is_a?(Array) && !domain.last.is_a?(Array)
18
+ return [domain]
19
+ else
20
+ return domain
21
+ end
22
+ end
23
+
24
+ def clean_request_args!(args)
25
+ if args[-1].is_a? Hash
26
+ args[-1] = @ooor.global_context.merge(args[-1])
27
+ elsif args.is_a?(Array)
28
+ args += [@ooor.global_context]
29
+ end
30
+ cast_request_to_openerp!(args[-2]) if args[-2].is_a? Hash
31
+ end
32
+
33
+ def cast_request_to_openerp!(map)
34
+ map.each do |k, v|
35
+ if v == nil
36
+ map[k] = false
37
+ elsif !v.is_a?(Integer) && !v.is_a?(Float) && v.is_a?(Numeric) && v.respond_to?(:to_f)
38
+ map[k] = v.to_f
39
+ elsif !v.is_a?(Numeric) && !v.is_a?(Integer) && v.respond_to?(:sec) && v.respond_to?(:year)#really ensure that's a datetime type
40
+ map[k] = "#{v.year}-#{v.month}-#{v.day} #{v.hour}:#{v.min}:#{v.sec}"
41
+ elsif !v.is_a?(Numeric) && !v.is_a?(Integer) && v.respond_to?(:day) && v.respond_to?(:year)#really ensure that's a date type
42
+ map[k] = "#{v.year}-#{v.month}-#{v.day}"
43
+ end
44
+ end
45
+ end
46
+
47
+ def cast_answer_to_ruby!(answer)
48
+ def cast_map_to_ruby!(map)
49
+ map.each do |k, v|
50
+ if self.fields[k] && v.is_a?(String) && !v.empty?
51
+ case self.fields[k]['type']
52
+ when 'datetime'
53
+ map[k] = Time.parse(v)
54
+ when 'date'
55
+ map[k] = Date.parse(v)
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ if answer.is_a?(Array)
62
+ answer.each {|item| self.cast_map_to_ruby!(item) if item.is_a? Hash}
63
+ elsif answer.is_a?(Hash)
64
+ self.cast_map_to_ruby!(answer)
65
+ else
66
+ answer
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ def to_openerp_hash!
73
+ cast_relations_to_openerp!
74
+ @attributes.reject {|k, v| k == 'id'}.merge(@associations)
75
+ end
76
+
77
+ def cast_relations_to_openerp!
78
+ @associations.reject! do |k, v| #reject non assigned many2one or empty list
79
+ v.is_a?(Array) && (v.size == 0 or v[1].is_a?(String))
80
+ end
81
+
82
+ def cast_relation(k, v, one2many_associations, many2many_associations)
83
+ if one2many_associations[k]
84
+ return v.collect! do |value|
85
+ if value.is_a?(OpenObjectResource) #on the fly creation as in the GTK client
86
+ [0, 0, value.to_openerp_hash!]
87
+ else
88
+ if value.is_a?(Hash)
89
+ [0, 0, value]
90
+ else
91
+ [1, value, {}]
92
+ end
93
+ end
94
+ end
95
+ elsif many2many_associations[k]
96
+ return v = [[6, 0, v]]
97
+ end
98
+ end
99
+
100
+ @associations.each do |k, v| #see OpenERP awkward associations API
101
+ #already casted, possibly before server error!
102
+ next if (v.is_a?(Array) && v.size == 1 && v[0].is_a?(Array)) \
103
+ || self.class.many2one_associations[k] \
104
+ || !v.is_a?(Array)
105
+ new_rel = self.cast_relation(k, v, self.class.one2many_associations, self.class.many2many_associations)
106
+ if new_rel #matches a known o2m or m2m
107
+ @associations[k] = new_rel
108
+ else
109
+ self.class.many2one_associations.each do |k2, field| #try to cast the association to an inherited o2m or m2m:
110
+ linked_class = self.class.const_get(field['relation'])
111
+ new_rel = self.cast_relation(k, v, linked_class.one2many_associations, linked_class.many2many_associations)
112
+ @associations[k] = new_rel and break if new_rel
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ end
119
+ end
@@ -1,5 +1,5 @@
1
1
  # OOOR: Open Object On Rails
2
- # Copyright (C) 2009-2010 Akretion LTDA (<http://www.akretion.com>).
2
+ # Copyright (C) 2009-2011 Akretion LTDA (<http://www.akretion.com>).
3
3
  # Author: Raphaël Valyi
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
@@ -14,183 +14,206 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Affero General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ module Ooor
18
+ module UML
19
+ #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)
17
20
 
18
- module UML
19
- #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)
21
+ def self.included(base) base.extend(ClassMethods) end
20
22
 
21
- def self.included(base) base.extend(ClassMethods) end
22
-
23
- def print_uml(*options)
24
- ooor = self.class.ooor
25
- UML.print_uml(ooor.config[:models] && ooor.loaded_models.select {|model| ooor.config[:models].index(model.openerp_model)} || ooor.loaded_models, options)
26
- end
27
-
28
- module ClassMethods
29
23
  def print_uml(*options)
30
- UML.print_uml([self], options)
24
+ ooor = self.class.ooor
25
+ UML.print_uml(ooor.config[:models] && ooor.loaded_models.select {|model| ooor.config[:models].index(model.openerp_model)} || ooor.loaded_models, options)
31
26
  end
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
- s
39
- end
40
-
41
- def self.print_uml(classes, *options)
42
- options = options[0] if options[0].is_a?(Array)
43
- local = (options.index(:all) == nil)
44
- detailed = (options.index(:detailed) != nil) || local && (options.index(:nodetail) == nil)
45
-
46
- enabled_targets = classes[0].ooor.config[:models] #defines the scope of the UML for option local
47
- m2o_edges = {}
48
- o2m_edges = {}
49
- m2m_edges = {}
50
- #instead of diplaying several relations of the same kind between two nodes which would bloat the graph,
51
- #we track them all and factor them on a common multiline edge label:
52
- connex_classes = UML.collect_edges(false, local, classes, enabled_targets, m2o_edges, o2m_edges, m2m_edges)
53
- #back links from connex classes:
54
- connex_classes += UML.collect_edges(true, local, connex_classes - classes, classes, m2o_edges, o2m_edges, m2m_edges)
55
-
56
- File.open('uml.dot', 'w') do |f|
57
- f << <<-eos
58
- digraph G {
59
- fontname = "Bitstream Vera Sans"
60
- fontsize = 8
61
- label = "*** generated by OOOR by www.akretion.com ***"
62
- node [
63
- fontname = "Bitstream Vera Sans"
64
- fontsize = 16
65
- shape = "record"
66
- fillcolor=orange
67
- style="rounded,filled"
68
- ]
69
- edge [
70
- arrowhead = "none"
71
- fontname = "Bitstream Vera Sans"
72
- fontsize = 9
73
- ]
74
- eos
75
-
76
- #UML nodes definitions
77
- ((connex_classes - classes) + classes - [IrModel, IrModelFields]).each do |model|
78
- f << " #{model} [ label = \"{#{model.name}#{detailed ? '|' + display_fields(model) : ''}}\" ]"
79
- end
80
27
 
81
- #many2one:
82
- f << <<-eos
83
- edge [
84
- headlabel = "1"
85
- taillabel = "n"
86
- ]
87
- eos
88
- m2o_edges.each do |k, v|
89
- reverse_part = v[3].size > 0 ? "\\n/#{v[3].join("\\n")}\"]\n" : "\"]\n"
90
- f << "edge [label = \"#{v[2].join("\\n")}#{reverse_part}"
91
- f << "#{v[0]} -> #{v[1]}\n"
28
+ def serve_uml(*options)#TODO port
29
+ ooor = self
30
+ require 'sinatra'
31
+ set :public, File.dirname(__FILE__) + '/../../'
32
+
33
+ get '/model/:model_name' do
34
+ model_name = params[:model_name]
35
+ model = ooor.const_get(model_name)
36
+ model.print_uml
37
+ s = ""#"Hello world! #{model_name}"
38
+ s << "<IMG SRC='/x.png' USEMAP='#UMLbyOOOR' />"
39
+ f=File.open('x.map')
40
+ f.each_line {|l| s << l}
41
+ s
92
42
  end
93
43
 
94
- #one2many:
95
- f << <<-eos
96
- edge [
97
- headlabel = "n"
98
- taillabel = "1"
99
- ]
100
- eos
101
- o2m_edges.each do |k, v|
102
- f << "edge [label = \"#{v[3].join("\\n")}\"]\n"
103
- f << "#{v[0]} -> #{v[1]}\n"
104
- end
44
+ Sinatra::Application.run!
45
+ end
105
46
 
106
- #many2many:
107
- f << <<-eos
108
- edge [
109
- headlabel = "n"
110
- taillabel = "n"
111
- ]
112
- eos
113
- m2m_edges.each do |k, v|
114
- reverse_part = v[3].size > 0 ? "\\n/#{v[3].join("\\n")}\"]\n" : "\"]\n"
115
- f << "edge [label = \"#{v[2].join("\\n")}}#{reverse_part}"
116
- f << "#{v[0]} -> #{v[1]}\n"
47
+ module ClassMethods
48
+ def print_uml(*options)
49
+ UML.print_uml([self], options)
117
50
  end
118
-
119
- f << "}"
120
51
  end
121
52
 
122
- begin
123
- cmd_line1 = "rm uml.png"
124
- system(cmd_line1)
125
- rescue
53
+ def self.display_fields(clazz)
54
+ s = ""
55
+ clazz.reload_fields_definition if clazz.fields.empty?
56
+ #clazz.fields.sort {|a,b| a[1]['type'] <=> b[1]['type']}.each {|i| s << "+ #{i[1]['type']} : #{i[0]}\\l\\n"}
57
+ 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"}
58
+ s
126
59
  end
127
- cmd_line2 = "dot -Tpng uml.dot -o uml.png"
128
- system(cmd_line2)
129
- end
130
60
 
131
- def self.collect_edges(is_reverse, local, classes, enabled_targets, m2o_edges, o2m_edges, m2m_edges)
132
- connex_classes = Set.new
133
-
134
- classes.each do |model|
135
- model.reload_fields_definition if model.fields.empty?
136
-
137
- #many2one:
138
- model.many2one_relations.each do |k, field|
139
- target = UML.get_target(is_reverse, local, enabled_targets, field, model)
140
- if target
141
- connex_classes.add(target)
142
- if m2o_edges["#{model}-#{target}"]
143
- m2o_edges["#{model}-#{target}"][2] += [k]
144
- else
145
- m2o_edges["#{model}-#{target}"] = [model, target, [k], []]
146
- end
61
+ def self.print_uml(classes, *options)
62
+ options = options[0] if options[0].is_a?(Array)
63
+ local = (options.index(:all) == nil)
64
+ detailed = (options.index(:detailed) != nil) || local && (options.index(:nodetail) == nil)
65
+
66
+ enabled_targets = classes[0].ooor.config[:models] #defines the scope of the UML for option local
67
+ m2o_edges = {}
68
+ o2m_edges = {}
69
+ m2m_edges = {}
70
+ #instead of diplaying several relations of the same kind between two nodes which would bloat the graph,
71
+ #we track them all and factor them on a common multiline edge label:
72
+ connex_classes = UML.collect_edges(false, local, classes, enabled_targets, m2o_edges, o2m_edges, m2m_edges)
73
+ #back links from connex classes:
74
+ connex_classes += UML.collect_edges(true, local, connex_classes - classes, classes, m2o_edges, o2m_edges, m2m_edges)
75
+
76
+ File.open('uml.dot', 'w') do |f|
77
+ f << <<-eos
78
+ digraph UMLbyOOOR {
79
+ fontname = "Helvetica"
80
+ fontsize = 11
81
+ label = "*** generated by OOOR by www.akretion.com ***"
82
+ node [
83
+ fontname = "Helvetica"
84
+ fontsize = 11
85
+ shape = "record"
86
+ fillcolor=orange
87
+ style="rounded,filled"
88
+ ]
89
+ edge [
90
+ arrowhead = "none"
91
+ fontname = "Helvetica"
92
+ fontsize = 9
93
+ ]
94
+ eos
95
+
96
+ #UML nodes definitions
97
+ ((connex_classes - classes) + classes - [IrModel, IrModel.const_get('ir.model.fields')]).each do |model|
98
+ #f << " #{model} [ label = \"{#{model.name}#{detailed ? '|' + display_fields(model) : ''}}\" URL=\"/model/#{model.openerp_model}\"];\n"
99
+ f << "#{model}[label=<<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" BGCOLOR=\"#ffffff\"><TR><TD COLSPAN=\"3\" BGCOLOR=\"#9bab96\" ALIGN=\"CENTER\">#{model.name}</TD></TR>#{display_fields(model)}</TABLE>> URL=\"/model/#{model.openerp_model}\"];\n"
100
+ end
101
+
102
+ #many2one:
103
+ f << <<-eos
104
+ edge [
105
+ headlabel = "1"
106
+ taillabel = "n"
107
+ ]
108
+ eos
109
+ m2o_edges.each do |k, v|
110
+ reverse_part = v[3].size > 0 ? "\\n/#{v[3].join("\\n")}\"]\n" : "\"]\n"
111
+ f << "edge [label = \"#{v[2].join("\\n")}#{reverse_part}"
112
+ f << "#{v[0]} -> #{v[1]}\n"
147
113
  end
148
114
 
115
+ #one2many:
116
+ f << <<-eos
117
+ edge [
118
+ headlabel = "n"
119
+ taillabel = "1"
120
+ ]
121
+ eos
122
+ o2m_edges.each do |k, v|
123
+ f << "edge [label = \"#{v[3].join("\\n")}\"]\n"
124
+ f << "#{v[0]} -> #{v[1]}\n"
125
+ end
126
+
127
+ #many2many:
128
+ f << <<-eos
129
+ edge [
130
+ headlabel = "n"
131
+ taillabel = "n"
132
+ ]
133
+ eos
134
+ m2m_edges.each do |k, v|
135
+ reverse_part = v[3].size > 0 ? "\\n/#{v[3].join("\\n")}\"]\n" : "\"]\n"
136
+ f << "edge [label = \"#{v[2].join("\\n")}}#{reverse_part}"
137
+ f << "#{v[0]} -> #{v[1]}\n"
138
+ end
139
+
140
+ f << "}"
149
141
  end
142
+
143
+ begin
144
+ cmd_line1 = "rm uml.png"
145
+ #system(cmd_line1)
146
+ rescue
147
+ end
148
+ #cmd_line2 = "dot -Tpng uml.dot -o uml.png"
149
+ cmd_line2 = "dot -Tcmapx -ox.map -Tpng -ox.png uml.dot"
150
+ system(cmd_line2)
150
151
  end
151
152
 
152
- classes.each do |model|
153
- #one2many:
154
- model.one2many_relations.each do |k, field|
155
- target = UML.get_target(is_reverse, local, enabled_targets, field, model)
156
- if target
157
- connex_classes.add(target)
158
- if m2o_edges["#{target}-#{model}"]
159
- m2o_edges["#{target}-#{model}"][3] += [k]
160
- elsif o2m_edges["#{model}-#{target}"]
161
- o2m_edges["#{model}-#{target}"][3] += [k]
162
- else
163
- o2m_edges["#{model}-#{target}"] = [model, target, [], [k]]
153
+ def self.collect_edges(is_reverse, local, classes, enabled_targets, m2o_edges, o2m_edges, m2m_edges)
154
+ connex_classes = Set.new
155
+
156
+ classes.each do |model|
157
+ model.reload_fields_definition if model.fields.empty?
158
+
159
+ #many2one:
160
+ model.many2one_associations.each do |k, field|
161
+ target = UML.get_target(is_reverse, local, enabled_targets, field, model)
162
+ if target
163
+ connex_classes.add(target)
164
+ if m2o_edges["#{model}-#{target}"]
165
+ m2o_edges["#{model}-#{target}"][2] += [k]
166
+ else
167
+ m2o_edges["#{model}-#{target}"] = [model, target, [k], []]
168
+ end
164
169
  end
170
+
165
171
  end
166
172
  end
167
173
 
168
- #many2many:
169
- model.many2many_relations.each do |k, field|
170
- target = UML.get_target(is_reverse, local, enabled_targets, field, model)
171
- if target
172
- connex_classes.add(target)
173
- if m2m_edges["#{model}-#{target}"]
174
- m2m_edges["#{model}-#{target}"][2] += [k]
175
- elsif m2m_edges["#{target}-#{model}"]
176
- m2m_edges["#{target}-#{model}"][3] += [k]
177
- else
178
- m2m_edges["#{model}-#{target}"] = [model, target, [k], []]
174
+ classes.each do |model|
175
+ #one2many:
176
+ model.one2many_associations.each do |k, field|
177
+ target = UML.get_target(is_reverse, local, enabled_targets, field, model)
178
+ if target
179
+ connex_classes.add(target)
180
+ if m2o_edges["#{target}-#{model}"]
181
+ m2o_edges["#{target}-#{model}"][3] += [k]
182
+ elsif o2m_edges["#{model}-#{target}"]
183
+ o2m_edges["#{model}-#{target}"][3] += [k]
184
+ else
185
+ o2m_edges["#{model}-#{target}"] = [model, target, [], [k]]
186
+ end
187
+ end
188
+ end
189
+
190
+ #many2many:
191
+ model.many2many_associations.each do |k, field|
192
+ target = UML.get_target(is_reverse, local, enabled_targets, field, model)
193
+ if target
194
+ connex_classes.add(target)
195
+ if m2m_edges["#{model}-#{target}"]
196
+ m2m_edges["#{model}-#{target}"][2] += [k]
197
+ elsif m2m_edges["#{target}-#{model}"]
198
+ m2m_edges["#{target}-#{model}"][3] += [k]
199
+ else
200
+ m2m_edges["#{model}-#{target}"] = [model, target, [k], []]
201
+ end
179
202
  end
180
203
  end
181
- end
182
204
 
205
+ end
206
+ connex_classes
183
207
  end
184
- connex_classes
185
- end
186
208
 
187
- private
209
+ private
188
210
 
189
- def self.get_target(is_reverse, local, enabled_targets, field, model)
190
- if (is_reverse && !local) || (!enabled_targets) || enabled_targets.index(field['relation'])
191
- model.const_get(field['relation'])
192
- else
193
- false
211
+ def self.get_target(is_reverse, local, enabled_targets, field, model)
212
+ if (is_reverse && !local) || (!enabled_targets) || enabled_targets.index(field['relation'])
213
+ model.const_get(field['relation'])
214
+ else
215
+ false
216
+ end
194
217
  end
195
218
  end
196
219
  end