ginjo-rfm 2.1.7 → 3.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.
- checksums.yaml +15 -0
- data/CHANGELOG.md +45 -16
- data/README.md +251 -274
- data/lib/rfm.rb +42 -20
- data/lib/rfm/VERSION +1 -1
- data/lib/rfm/base.rb +63 -196
- data/lib/rfm/database.rb +15 -16
- data/lib/rfm/layout.rb +244 -271
- data/lib/rfm/metadata/datum.rb +45 -0
- data/lib/rfm/metadata/field.rb +33 -13
- data/lib/rfm/metadata/field_control.rb +57 -25
- data/lib/rfm/metadata/layout_meta.rb +38 -0
- data/lib/rfm/metadata/resultset_meta.rb +66 -0
- data/lib/rfm/metadata/value_list_item.rb +7 -6
- data/lib/rfm/record.rb +54 -74
- data/lib/rfm/resultset.rb +63 -112
- data/lib/rfm/server.rb +6 -172
- data/lib/rfm/utilities/config.rb +100 -55
- data/lib/rfm/utilities/connection.rb +209 -0
- data/lib/rfm/utilities/core_ext.rb +14 -1
- data/lib/rfm/utilities/factory.rb +68 -65
- data/lib/rfm/utilities/sax_parser.rb +1039 -0
- metadata +154 -206
- data/lib/rfm/utilities/fmpxmlresult.rb +0 -167
- data/lib/rfm/utilities/fmresultset.rb +0 -153
- data/lib/rfm/utilities/xml_parser.rb +0 -124
- data/lib/rfm/xml_mini/hpricot.rb +0 -133
- data/lib/rfm/xml_mini/ox_sax.rb +0 -91
- data/lib/rfm/xml_mini/rexml_sax.rb +0 -81
data/lib/rfm.rb
CHANGED
@@ -3,16 +3,11 @@ module Rfm
|
|
3
3
|
$LOAD_PATH.unshift(PATH) unless $LOAD_PATH.include?(PATH)
|
4
4
|
end
|
5
5
|
|
6
|
-
require 'thread' # some versions of ActiveSupport will raise error about Mutex unless 'thread' is loaded.
|
7
|
-
|
8
|
-
require '
|
9
|
-
require 'active_support/ordered_hash'
|
10
|
-
require 'active_support/version'
|
6
|
+
#require 'thread' # some versions of ActiveSupport will raise error about Mutex unless 'thread' is loaded.
|
7
|
+
|
8
|
+
require 'logger'
|
11
9
|
require 'rfm/utilities/core_ext'
|
12
10
|
require 'rfm/utilities/case_insensitive_hash'
|
13
|
-
#require 'rfm/utilities/config'
|
14
|
-
#require 'rfm/utilities/factory'
|
15
|
-
#require 'rfm/version.rb'
|
16
11
|
|
17
12
|
module Rfm
|
18
13
|
|
@@ -27,45 +22,49 @@ module Rfm
|
|
27
22
|
autoload :Resultset, 'rfm/resultset'
|
28
23
|
autoload :Record, 'rfm/record'
|
29
24
|
autoload :Base, 'rfm/base'
|
30
|
-
autoload :
|
25
|
+
autoload :SaxParser, 'rfm/utilities/sax_parser'
|
31
26
|
autoload :Config, 'rfm/utilities/config'
|
32
27
|
autoload :Factory, 'rfm/utilities/factory'
|
33
28
|
autoload :CompoundQuery,'rfm/utilities/compound_query'
|
34
29
|
autoload :VERSION, 'rfm/version'
|
35
|
-
autoload :
|
36
|
-
autoload :Fmpxmlresult, 'rfm/utilities/fmpxmlresult.rb'
|
37
|
-
autoload :Fmpdsoresult, 'rfm/utilities/fmpdsoresult.rb'
|
38
|
-
autoload :Fmpxmllayout, 'rfm/utilities/fmpxmllayout.rb'
|
30
|
+
autoload :Connection, 'rfm/utilities/connection.rb'
|
39
31
|
|
40
32
|
module Metadata
|
41
33
|
autoload :Script, 'rfm/metadata/script'
|
42
34
|
autoload :Field, 'rfm/metadata/field'
|
43
35
|
autoload :FieldControl, 'rfm/metadata/field_control'
|
44
36
|
autoload :ValueListItem, 'rfm/metadata/value_list_item'
|
37
|
+
autoload :Datum, 'rfm/metadata/datum'
|
38
|
+
autoload :ResultsetMeta, 'rfm/metadata/resultset_meta'
|
39
|
+
autoload :LayoutMeta, 'rfm/metadata/layout_meta'
|
45
40
|
end
|
46
41
|
|
47
42
|
def info
|
48
43
|
rslt = <<-EEOOFF
|
49
|
-
|
44
|
+
Gem name: ginjo-rfm
|
50
45
|
Version: #{VERSION}
|
51
|
-
|
52
|
-
ActiveModel
|
53
|
-
|
54
|
-
|
46
|
+
ActiveModel loadable? #{begin; Gem::Specification::find_all_by_name('activemodel')[0].version.to_s; rescue Exception; false; end}
|
47
|
+
ActiveModel loaded? #{defined?(ActiveModel) ? 'true' : 'false'}
|
48
|
+
XML default parser: #{SaxParser::Handler.get_backend}
|
49
|
+
Ruby: #{RUBY_VERSION}
|
55
50
|
EEOOFF
|
56
51
|
rslt.gsub!(/^[ \t]*/, '')
|
52
|
+
rslt
|
57
53
|
rescue
|
58
54
|
"Could not retrieve info: #{$!}"
|
59
55
|
end
|
60
56
|
|
61
57
|
def info_short
|
62
|
-
"Using ginjo-rfm version #{::Rfm::VERSION} with #{
|
58
|
+
"Using ginjo-rfm version #{::Rfm::VERSION} with #{SaxParser::Handler.get_backend}"
|
63
59
|
end
|
64
60
|
|
65
61
|
def_delegators 'Rfm::Factory', :servers, :server, :db, :database, :layout
|
66
|
-
def_delegators 'Rfm::
|
62
|
+
def_delegators 'Rfm::SaxParser', :backend, :backend=
|
63
|
+
def_delegators 'Rfm::SaxParser::Handler', :get_backend
|
67
64
|
def_delegators 'Rfm::Config', :config, :get_config, :config_clear
|
68
65
|
def_delegators 'Rfm::Resultset', :load_data
|
66
|
+
alias_method :parser, :backend
|
67
|
+
alias_method :parser=, :backend=
|
69
68
|
|
70
69
|
def models(*args)
|
71
70
|
Rfm::Base
|
@@ -77,6 +76,29 @@ module Rfm
|
|
77
76
|
Rfm::Factory.modelize(*args)
|
78
77
|
end
|
79
78
|
|
79
|
+
#attr_accessor :log
|
80
|
+
|
81
|
+
def logger
|
82
|
+
@@logger ||= get_config[:logger] || Logger.new(STDOUT).tap {|l| l.formatter = proc {|severity, datetime, progname, msg| "#{datetime}: Rfm-#{severity} #{msg}\n"}}
|
83
|
+
end
|
84
|
+
|
85
|
+
alias_method :log, :logger
|
86
|
+
|
87
|
+
def logger=(obj)
|
88
|
+
@@logger = obj
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
|
80
93
|
extend self
|
94
|
+
|
95
|
+
SaxParser.default_class = CaseInsensitiveHash
|
96
|
+
SaxParser.template_prefix = File.join(File.dirname(__FILE__), 'rfm/utilities/sax/')
|
97
|
+
SaxParser.templates.merge!({
|
98
|
+
:fmpxmllayout => 'fmpxmllayout.yml',
|
99
|
+
:fmresultset => 'fmresultset.yml',
|
100
|
+
:fmpxmlresult => 'fmpxmlresult.yml',
|
101
|
+
:none => nil
|
102
|
+
})
|
81
103
|
|
82
104
|
end # Rfm
|
data/lib/rfm/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.0.0
|
data/lib/rfm/base.rb
CHANGED
@@ -30,137 +30,7 @@ module Rfm
|
|
30
30
|
# @person = Person.find({:name => 'mike'}, :max_records => 50)[0]
|
31
31
|
# @person.update_attributes(:name => 'Michael', :title => "Senior Partner")
|
32
32
|
# @person.save
|
33
|
-
#
|
34
33
|
#
|
35
|
-
require 'active_support/core_ext/string/inflections'
|
36
|
-
require 'rfm/database'
|
37
|
-
require 'rfm/layout'
|
38
|
-
require 'rfm/record'
|
39
|
-
require 'rfm/utilities/factory'
|
40
|
-
require 'delegate'
|
41
|
-
|
42
|
-
class Layout
|
43
|
-
|
44
|
-
class SubLayout < DelegateClass(Layout)
|
45
|
-
# Added by wbr to give config heirarchy: layout -> model -> sublayout
|
46
|
-
include Config
|
47
|
-
|
48
|
-
include Layout::LayoutModule
|
49
|
-
attr_accessor :model, :parent_layout
|
50
|
-
|
51
|
-
def initialize(master)
|
52
|
-
super(master)
|
53
|
-
self.parent_layout = master
|
54
|
-
end
|
55
|
-
end # SubLayout
|
56
|
-
|
57
|
-
attr_accessor :subs
|
58
|
-
|
59
|
-
alias_method :main_init, :initialize
|
60
|
-
def initialize(*args)
|
61
|
-
@subs ||= []
|
62
|
-
main_init(*args)
|
63
|
-
end
|
64
|
-
|
65
|
-
def sublayout
|
66
|
-
if self.is_a?(Rfm::Layout)
|
67
|
-
sub = SubLayout.new(self); subs << sub; sub
|
68
|
-
else
|
69
|
-
self
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# Creates new class with layout name, subclassed from Rfm::Base, and links the new model to a SubLayout instance.
|
74
|
-
def modelize
|
75
|
-
model_name = name.to_s.gsub(/\W/, '_').classify.gsub(/_/,'')
|
76
|
-
(return model_name.constantize) rescue nil
|
77
|
-
sub = sublayout
|
78
|
-
sub.instance_eval do
|
79
|
-
model_class = eval("::" + model_name + "= Class.new(Rfm::Base)")
|
80
|
-
model_class.class_exec(self) do |layout_obj|
|
81
|
-
@layout = layout_obj
|
82
|
-
end
|
83
|
-
@model = model_class
|
84
|
-
|
85
|
-
# Added by wbr to give config heirarchy: layout -> model -> sublayout
|
86
|
-
model.config :parent=>'@layout.parent_layout'
|
87
|
-
config :parent=>'model'
|
88
|
-
end
|
89
|
-
sub.model.to_s.constantize
|
90
|
-
rescue StandardError, SyntaxError
|
91
|
-
nil
|
92
|
-
end
|
93
|
-
|
94
|
-
def models
|
95
|
-
subs.collect{|s| s.model}
|
96
|
-
end
|
97
|
-
|
98
|
-
end # Layout
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
class Record
|
105
|
-
class << self
|
106
|
-
def new(*args)
|
107
|
-
#puts "Creating new record from RECORD. Layout: #{args[3].class} #{args[3].object_id}"
|
108
|
-
args[3].model.new(*args)
|
109
|
-
rescue
|
110
|
-
#puts "RECORD failed to send 'new' to MODEL"
|
111
|
-
super
|
112
|
-
#allocate.send(:initialize, *args)
|
113
|
-
end
|
114
|
-
end # class << self
|
115
|
-
end # class Record
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
class Database
|
122
|
-
def_delegators :layouts, :modelize, :models
|
123
|
-
end
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
module Factory
|
129
|
-
@models ||= []
|
130
|
-
|
131
|
-
class << self
|
132
|
-
attr_accessor :models
|
133
|
-
|
134
|
-
# Shortcut to Factory.db().layouts.modelize()
|
135
|
-
# If first parameter is regex, it is used for modelize filter.
|
136
|
-
# Otherwise, parameters are passed to Factory.database
|
137
|
-
def modelize(*args)
|
138
|
-
regx = args[0].is_a?(Regexp) ? args.shift : /.*/
|
139
|
-
db(*args).layouts.modelize(regx)
|
140
|
-
end
|
141
|
-
end # class << self
|
142
|
-
|
143
|
-
class LayoutFactory
|
144
|
-
def modelize(filter = /.*/)
|
145
|
-
all.values.each{|lay| lay.modelize if lay.name.match(filter)}
|
146
|
-
models
|
147
|
-
end
|
148
|
-
|
149
|
-
def models
|
150
|
-
rslt = {}
|
151
|
-
each do |k,lay|
|
152
|
-
layout_models = lay.models
|
153
|
-
rslt[k] = layout_models if !layout_models.blank?
|
154
|
-
end
|
155
|
-
rslt
|
156
|
-
end
|
157
|
-
|
158
|
-
end # LayoutFactory
|
159
|
-
end # Factory
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
34
|
class Base < Rfm::Record #Hash
|
165
35
|
extend Config
|
166
36
|
config :parent => 'Rfm::Config'
|
@@ -177,24 +47,6 @@ module Rfm
|
|
177
47
|
yield
|
178
48
|
end
|
179
49
|
end
|
180
|
-
|
181
|
-
def initialize(record={}, resultset_obj=[], field_meta='', layout_obj=self.class.layout, portal=nil)
|
182
|
-
if resultset_obj == [] and !record.respond_to?(:columns) #.has_key? 'field'
|
183
|
-
@mods = Rfm::CaseInsensitiveHash.new
|
184
|
-
@layout = layout_obj
|
185
|
-
@resultset = Resultset.allocate
|
186
|
-
# loop thru each layout field, creating hash keys with nil values
|
187
|
-
layout_obj.field_names.each do |field|
|
188
|
-
field_name = field.to_s
|
189
|
-
self[field_name] = nil
|
190
|
-
end
|
191
|
-
self.update_attributes(record) unless record == {}
|
192
|
-
self.merge!(@mods) unless @mods == {}
|
193
|
-
@loaded = true
|
194
|
-
else
|
195
|
-
super
|
196
|
-
end
|
197
|
-
end
|
198
50
|
|
199
51
|
def to_partial_path(object = self) #@object)
|
200
52
|
return 'some/partial/path'
|
@@ -220,39 +72,34 @@ module Rfm
|
|
220
72
|
(Rfm::Factory.models << model).uniq unless Rfm::Factory.models.include? model
|
221
73
|
model.config :parent=>'Rfm::Base'
|
222
74
|
end
|
223
|
-
|
224
|
-
# Build a new record without saving
|
225
|
-
def new(*args)
|
226
|
-
# Without this method, infinite recursion will happen from Record.new
|
227
|
-
#puts "Creating new record from BASE"
|
228
|
-
rec = self.allocate
|
229
|
-
rec.send(:initialize, *args)
|
230
|
-
rec
|
231
|
-
end
|
232
75
|
|
233
76
|
def config(*args)
|
234
|
-
super(*args){|
|
77
|
+
super(*args){|options| @config.merge!(:layout=>options[:strings][0]) if options[:strings] && options[:strings][0]}
|
235
78
|
end
|
236
79
|
|
237
80
|
# Access/create the layout object associated with this model
|
238
81
|
def layout
|
239
82
|
return @layout if @layout
|
240
|
-
|
241
|
-
|
242
|
-
|
83
|
+
# cnf = get_config
|
84
|
+
# raise "Could not get :layout from get_config in Base.layout method" unless cnf[:layout] #return unless cnf[:layout]
|
85
|
+
# @layout = Rfm::Factory.layout(cnf).sublayout
|
86
|
+
name = get_config[:layout] || 'test' # The 'test' was added to help active-model-lint tests pass.
|
87
|
+
@layout = Rfm::Factory.layout(name, self) #.sublayout
|
243
88
|
|
244
89
|
# Added by wbr to give config heirarchy: layout -> model -> sublayout
|
245
|
-
config :parent=>'parent_layout'
|
246
|
-
|
90
|
+
#config :parent=>'parent_layout'
|
91
|
+
#config :parent=>'Rfm::Config'
|
92
|
+
#@layout.config model
|
93
|
+
#@layout.config :parent=>self
|
247
94
|
|
248
95
|
@layout.model = self
|
249
96
|
@layout
|
250
97
|
end
|
251
98
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
99
|
+
# # Access the parent layout of this model
|
100
|
+
# def parent_layout
|
101
|
+
# layout #.parent_layout
|
102
|
+
# end
|
256
103
|
|
257
104
|
# Just like Layout#find, but searching by record_id will return a record, not a resultset.
|
258
105
|
def find(find_criteria, options={})
|
@@ -291,41 +138,57 @@ module Rfm
|
|
291
138
|
|
292
139
|
# Is this a newly created record, not saved yet?
|
293
140
|
def new_record?
|
294
|
-
return true if self.record_id.
|
141
|
+
return true if (self.record_id.nil? || self.record_id.empty?)
|
295
142
|
end
|
296
143
|
|
297
144
|
# Reload record from database
|
298
145
|
# TODO: handle error when record has been deleted
|
146
|
+
# TODO: Move this to Rfm::Record.
|
299
147
|
def reload(force=false)
|
300
148
|
if (@mods.empty? or force) and record_id
|
301
149
|
@mods.clear
|
302
|
-
self.
|
150
|
+
self.replace_with_fresh_data layout.find(self.record_id)[0] #self.class.find(self.record_id)
|
303
151
|
end
|
304
152
|
end
|
305
153
|
|
306
154
|
# Mass update of record attributes, without saving.
|
307
|
-
# TODO: return error or nil if input hash contains no recognizable keys.
|
308
155
|
def update_attributes(new_attr)
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
end
|
319
|
-
end
|
320
|
-
# loop thru each input key-value,
|
321
|
-
# creating new attribute if key doesn't exist in model.
|
322
|
-
input_hash.each do |k,v|
|
323
|
-
if !self.class.field_controls.keys.include?(k) and self.respond_to?(k)
|
324
|
-
self.instance_variable_set("@#{k}", v)
|
325
|
-
end
|
326
|
-
end
|
327
|
-
self.merge!(@mods) unless @mods == {}
|
156
|
+
new_attr.each do |k,v|
|
157
|
+
k = k.to_s.downcase
|
158
|
+
if keys.include?(k)
|
159
|
+
@mods[k] = v
|
160
|
+
self[k] = v
|
161
|
+
else
|
162
|
+
instance_variable_set("@#{k}", v)
|
163
|
+
end
|
164
|
+
end
|
328
165
|
end
|
166
|
+
# # Mass update of record attributes, without saving.
|
167
|
+
# # TODO: return error or nil if input hash contains no recognizable keys.
|
168
|
+
# def update_attributes(new_attr)
|
169
|
+
# # creates new special hash
|
170
|
+
# input_hash = Rfm::CaseInsensitiveHash.new
|
171
|
+
# # populate new hash with input, coercing keys to strings
|
172
|
+
# #new_attr.each{|k,v| input_hash.merge! k.to_s=>v}
|
173
|
+
# new_attr.each{|k,v| input_hash[k.to_s] = v}
|
174
|
+
# # loop thru each layout field, adding data to @mods
|
175
|
+
# self.class.field_controls.keys.each do |field|
|
176
|
+
# field_name = field.to_s
|
177
|
+
# if input_hash.has_key?(field_name)
|
178
|
+
# #@mods.merge! field_name=>(input_hash[field_name] || '')
|
179
|
+
# @mods[field_name] = (input_hash[field_name] || '')
|
180
|
+
# end
|
181
|
+
# end
|
182
|
+
# # loop thru each input key-value,
|
183
|
+
# # creating new attribute if key doesn't exist in model.
|
184
|
+
# input_hash.each do |k,v|
|
185
|
+
# if !self.class.field_controls.keys.include?(k) and self.respond_to?(k)
|
186
|
+
# self.instance_variable_set("@#{k}", v)
|
187
|
+
# end
|
188
|
+
# end
|
189
|
+
# self.merge!(@mods) unless @mods == {}
|
190
|
+
# #self.merge!(@mods) unless @mods == Rfm::CaseInsensitiveHash.new
|
191
|
+
# end
|
329
192
|
|
330
193
|
# Mass update of record attributes, with saving.
|
331
194
|
def update_attributes!(new_attr)
|
@@ -335,7 +198,8 @@ module Rfm
|
|
335
198
|
|
336
199
|
# Save record modifications to database (with callbacks & validations). If record cannot be saved will raise error.
|
337
200
|
def save!
|
338
|
-
#
|
201
|
+
#return unless @mods.size > 0
|
202
|
+
raise "Record Invalid" unless valid? rescue nil
|
339
203
|
if @record_id
|
340
204
|
self.update
|
341
205
|
else
|
@@ -347,7 +211,7 @@ module Rfm
|
|
347
211
|
def save
|
348
212
|
save!
|
349
213
|
rescue
|
350
|
-
|
214
|
+
(self.errors[:base] rescue []) << $!
|
351
215
|
return nil
|
352
216
|
end
|
353
217
|
|
@@ -405,7 +269,8 @@ module Rfm
|
|
405
269
|
raise "Record not valid" if (defined?(ActiveModel::Validations) && !valid?)
|
406
270
|
run_callbacks :create do
|
407
271
|
return unless @mods.size > 0
|
408
|
-
merge_rfm_result self.class.create_from_new(@mods)
|
272
|
+
# merge_rfm_result self.class.create_from_new(@mods)
|
273
|
+
replace_with_fresh_data self.class.create_from_new(@mods)
|
409
274
|
end
|
410
275
|
self
|
411
276
|
end
|
@@ -417,26 +282,28 @@ module Rfm
|
|
417
282
|
return unless @mods.size > 0
|
418
283
|
unless mod_id
|
419
284
|
# regular save
|
420
|
-
merge_rfm_result self.class.send :edit, record_id, @mods
|
285
|
+
# merge_rfm_result self.class.send :edit, record_id, @mods
|
286
|
+
replace_with_fresh_data self.class.send :edit, record_id, @mods
|
421
287
|
else
|
422
288
|
# save_if_not_modified
|
423
|
-
merge_rfm_result self.class.send :edit, record_id, @mods, :modification_id=>mod_id
|
289
|
+
# merge_rfm_result self.class.send :edit, record_id, @mods, :modification_id=>mod_id
|
290
|
+
replace_with_fresh_data self.class.send :edit, record_id, @mods, :modification_id=>mod_id
|
424
291
|
end
|
425
292
|
end
|
426
293
|
self
|
427
294
|
end
|
428
295
|
|
296
|
+
# Deprecated in favor of Record#replace_with_fresh_data
|
429
297
|
def merge_rfm_result(result_record)
|
430
298
|
return unless @mods.size > 0
|
431
299
|
@record_id ||= result_record.record_id
|
432
300
|
self.merge! result_record
|
433
301
|
@mods.clear
|
434
302
|
self || {}
|
303
|
+
#self || Rfm::CaseInsensitiveHash.new
|
435
304
|
end
|
436
305
|
|
437
306
|
end # Base
|
438
307
|
|
439
308
|
end # Rfm
|
440
309
|
|
441
|
-
|
442
|
-
|