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.
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
- require 'active_support'
8
- require 'active_support/core_ext/object/blank'
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 :XmlParser, 'rfm/utilities/xml_parser'
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 :Fmresultset, 'rfm/utilities/fmresultset.rb'
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
- Name: ginjo-rfm
44
+ Gem name: ginjo-rfm
50
45
  Version: #{VERSION}
51
- ActiveSupport Version: #{ActiveSupport::VERSION::STRING}
52
- ActiveModel Loaded? #{defined?(ActiveModel) ? 'true' : 'false'}
53
- ActiveModel Loadable? #{begin; require 'active_model'; rescue LoadError; $!; end}
54
- XML Parser: #{XmlParser.backend}
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 #{XmlParser.backend}"
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::XmlParser', :backend, :backend=
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
@@ -1 +1 @@
1
- 2.1.7
1
+ 3.0.0
@@ -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){|strings| @config.merge!(:layout=>strings[0]) if strings[0]}
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
- cnf = get_config
241
- raise "Could not get :layout from get_config in Base.layout method" unless cnf[:layout] #return unless cnf[:layout]
242
- @layout = Rfm::Factory.layout(cnf).sublayout
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
- @layout.config :parent=>'model'
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
- # Access the parent layout of this model
253
- def parent_layout
254
- layout.parent_layout
255
- end
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.blank?
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.replace self.class.find(self.record_id)
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
- # creates new special hash
310
- input_hash = Rfm::CaseInsensitiveHash.new
311
- # populate new hash with input, coercing keys to strings
312
- new_attr.each{|k,v| input_hash.merge! k.to_s=>v}
313
- # loop thru each layout field, adding data to @mods
314
- self.class.field_controls.keys.each do |field|
315
- field_name = field.to_s
316
- if input_hash.has_key?(field_name)
317
- @mods.merge! field_name=>(input_hash[field_name] || '')
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
- #raise "Record Invalid" unless valid? rescue nil
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
- # (self.errors[:base] rescue []) << $!
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
-