ginjo-rfm 3.0.9 → 3.0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d2a03d23cf578b34173f800b1658fe22465b2736
4
- data.tar.gz: 02f0520fabc22fdaf653d02b1afa1b43867e65c9
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NzE0NWI5NTNjMDVhM2M0ZjZjMzI2Y2FiNDcyOGRiZmIxMGFlMmRiZQ==
5
+ data.tar.gz: !binary |-
6
+ MDY0MjgyNjJlYjM5NjBhNmVkYzFiN2NiMjI1ZWI3N2MzNzJiMDIxYQ==
5
7
  SHA512:
6
- metadata.gz: fd1ad124d35792b2959dbb3a6f82d0534c303dee8686df59cdf963e255778e843b32cab896437b8e07082d65a2b2f43bd8a27bc4f9a825c15fad892ac0f16773
7
- data.tar.gz: dd657b7d1a9fd7c4b85728da57e29fe6d480733bcf7d4ad65f32fbe34e3c6e033148d715198e8c84bb08985f30ef9a0dbce4f0bedcba9d0925b5676c56fad0e2
8
+ metadata.gz: !binary |-
9
+ NTcxNTk2YWQ2NzMwYjJmZDEwZWJmNjA3Nzc2MDIxNTBlMTc2OTY1ZjhkYmQx
10
+ MmU5ZjA3ZGU1MDY0NTY3NDlkNDA5YTc5MTNjNDNjZTdhZWY4NGQ2NmRmOTY1
11
+ OTMxNzkwZWVhZjkzZDhjOGViNGYyYjYzZDRmMTc3NzQyNmU2OTM=
12
+ data.tar.gz: !binary |-
13
+ MjY3MTNmYjBkNGU4YTE4ZTQ0MzA4YWU1NGQxYzY0NDdlZGIxOTQ2MGM4MGE2
14
+ Yjc2NTVlNDFhMjc5MzU4NDE3MGRlMjQ3NjFhMmY0Yzg1NjkwN2Q0YmJhMzky
15
+ YWEwZDg3ZTNhYzUwOWU2YWFkYTAwMWY4YTYxMmNjMTI5OTQwZDA=
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## Ginjo-Rfm 3.0.10
4
+
5
+ * Fixed bug where missing metadata would cause errors when creating/editing records.
6
+
7
+ * Added scoping support
8
+
9
+ scope = {:person_id => current_user.person_id}
10
+ Order.find([{:status => ['open', 'processing']}, {:omit => true, :item_count => "<1"}], :scope => scope)
11
+
12
+ class Orders < Rfm::Base
13
+ SCOPE = Proc.new { {:expired => "=" } }
14
+ end
15
+ Order.find({:user_id => '12345'})
16
+
17
+ class Orders < Rfm::Base
18
+ SCOPE = Proc.new {|args| {:user_id => args} }
19
+ end
20
+ Order.find([{:status => ['open', 'processing']}, {:omit => true, :item_count => "<1"}], :scope_args => current_user.id)
21
+
22
+ * Code cleanup
23
+
3
24
  ## Ginjo-Rfm 3.0.9
4
25
 
5
26
  * Fixed bug in parser that was appending each portal array recursively to itself.
@@ -14,20 +35,20 @@
14
35
 
15
36
  * Implemented proxy option for database connections thru a proxy server.
16
37
 
17
- config :proxy=>['my.proxy.com', 8888]
18
-
38
+ config :proxy=>['my.proxy.com', 8888]
39
+
19
40
  * Implemented erb parsing of config.yml
20
-
41
+
21
42
  * Disabled ```:grammar => :auto``` option. The current xml parser cannot yet use the FMPXMLRESULT grammar for general queries.
22
43
 
23
44
 
24
45
  ## Ginjo-Rfm 3.0.7
25
46
 
26
47
  * Changed record creation so that generic records created from non-modelized layouts will be instances of Rfm::Record, instead of instances of a transient model class based on the layout. Transient model classes will foul up serialization and any number of other things. Records created from a user-defined model class will continue to be instances of the model class.
27
-
28
- my_layout.find(12345).class == Rfm::Record
29
- MyModel.find(12345).class == MyModel
30
-
48
+
49
+ my_layout.find(12345).class == Rfm::Record
50
+ MyModel.find(12345).class == MyModel
51
+
31
52
 
32
53
  ## Ginjo-Rfm 3.0.6
33
54
 
@@ -36,7 +57,7 @@
36
57
 
37
58
  ## Ginjo-Rfm 3.0.5
38
59
 
39
- * Fixed parser handling of `<field>` element that's missing a `<data>` element.
60
+ * Fixed parser handling of ```<field>``` element that's missing a ```<data>``` element.
40
61
  * Fixed coercion of repeating field data.
41
62
  * Fixed case where special characters in Filemaker data yielded array instead of string (sax parsing split text).
42
63
  * Fixed various bugs in metadata parsing.
@@ -79,10 +100,10 @@
79
100
  * Record.new now automatically creats models based on layout name. Should there be an option to disable this?
80
101
  * Removed ActiveSupport requirement (of course, ActiveSupport will load if ActiveModle is used, but that is the users' choice).
81
102
  * Removed XmlMini, XmlParser, and related code & specs.
82
- * Detached resultset from record, so record doesn't drag resultset around with it.
103
+ * Detached resultset from record, so record doesn't drag resultset around with it.
83
104
  * Disabled automatic model creation from a table-name in a new Rfm::Record when initializing.
84
- * Consolidated Base.new, Base#inititalize into Rfm::Record.
85
- * Fixed validation callbacks issue.
105
+ * Consolidated Base.new, Base#inititalize into Rfm::Record.
106
+ * Fixed validation callbacks issue.
86
107
  * Fixed: Resultset will politely return [] when asked for non-existent portal\_names.
87
108
  * Mods to rakefile benchmarking/profiling.
88
109
  * Refactored Resultset metadata methods.
@@ -117,7 +138,7 @@
117
138
  ## Ginjo-Rfm 2.1.2
118
139
 
119
140
  * Fixed config.rb so that :file\_path (to user-defined yml config file) can be specified as a single path string
120
- or as an array of path strings.
141
+ or as an array of path strings.
121
142
 
122
143
  ## Ginjo-Rfm 2.1.1
123
144
 
@@ -127,9 +148,9 @@
127
148
 
128
149
  ## Ginjo-Rfm 2.1.0
129
150
 
130
- * Removed `:include_portals` query option in favor of `:ignore_portals`.
151
+ * Removed ```:include_portals``` query option in favor of ```:ignore_portals```.
131
152
 
132
- * Added `:max_portal_rows` query option.
153
+ * Added ```:max_portal_rows``` query option.
133
154
 
134
155
  * Added field-remapping framework to allow model fields with different names than Filemaker fields.
135
156
 
@@ -138,11 +159,11 @@
138
159
  * Detached new Server objects from Factory.servers hash, so wont reuse or stack-up servers.
139
160
 
140
161
  * Added grammar translation layer between xml parser and Rfm, allowing all supported xml grammars to be used with Rfm.
141
- This will also streamline changes/additions to Filemaker's xml grammar(s).
142
-
162
+ This will also streamline changes/additions to Filemaker's xml grammar(s).
163
+
143
164
  * Fixed case statement for ruby 1.9
144
165
 
145
- * Configuration `:use` option now works for all Rfm objects that respond to `config`.
166
+ * Configuration ```:use``` option now works for all Rfm objects that respond to ```config```.
146
167
 
147
168
  ## Ginjo-Rfm 2.0.2
148
169
 
@@ -192,47 +213,47 @@
192
213
 
193
214
  * Re-implemented:
194
215
 
195
- Layout#field\_controls
216
+ Layout#field\_controls
196
217
 
197
- Layout#value\_lists
218
+ Layout#value\_lists
198
219
 
199
220
  * Enhanced:
200
221
 
201
- ValueListItem handles both display & data items now.
222
+ ValueListItem handles both display & data items now.
202
223
 
203
- Timeout feature from timting (github/timting/rfm).
224
+ Timeout feature from timting (github/timting/rfm).
204
225
 
205
- Added specs for Record#save.
226
+ Added specs for Record#save.
206
227
 
207
228
  * Fixed:
208
229
 
209
- [Bug] Getting & setting fields with symbol-based keys was producing error.
230
+ [Bug] Getting & setting fields with symbol-based keys was producing error.
210
231
 
211
- [Bug] Setting fields would not update main record hash.
232
+ [Bug] Setting fields would not update main record hash.
212
233
 
213
- [Bug] Record#save wasn't merging back into self.
234
+ [Bug] Record#save wasn't merging back into self.
214
235
 
215
236
  * Partial Fix:
216
237
 
217
- server.db.all
218
- db.layout.all
219
- db.script.all
238
+ server.db.all
239
+ db.layout.all
240
+ db.script.all
220
241
 
221
- Note: the "#all" method returns object names (as keys) only. The receiver of the method maintains the full object collection.
242
+ Note: the "#all" method returns object names (as keys) only. The receiver of the method maintains the full object collection.
222
243
 
223
- Example:
244
+ Example:
224
245
 
225
- server.db.all #=> ['dbname1', 'dbname2', ...]
226
- server.db #=> a DbFactory object (descendant of Hash), containing 0 or more Database objects
246
+ server.db.all #=> ['dbname1', 'dbname2', ...]
247
+ server.db #=> a DbFactory object (descendant of Hash), containing 0 or more Database objects
227
248
 
228
249
  ## Lardawge-Rfm 1.4.2 (unreleased)
229
250
 
230
251
  * Made nil default on fields with no value.
231
252
 
232
- Example:
253
+ Example:
233
254
 
234
- Old: record.john #=> ""
235
- New: record.john #=> nil
255
+ Old: record.john #=> ""
256
+ New: record.john #=> nil
236
257
 
237
258
  ## Lardawge-Rfm 1.4.1.2
238
259
 
@@ -252,13 +273,13 @@
252
273
 
253
274
  * Added an option to load portal records which defaults to false. This significantly speeds up load time when portals are present on the layout.
254
275
 
255
- Example:
276
+ Example:
256
277
 
257
- result = fm_server('layout').find({:username => "==#{username}"}, {:include_portals => true})
258
- # => This will fetch all records with portal records attached.
278
+ result = fm_server('layout').find({:username => "==#{username}"}, {:include_portals => true})
279
+ # => This will fetch all records with portal records attached.
259
280
 
260
- result.first.portals
261
- # => would return an empty hash by default.
281
+ result.first.portals
282
+ # => would return an empty hash by default.
262
283
 
263
284
  * Internal file restructuring. Some classes have changed but it should be nothing a developer would use API wise. Please let me know if it is.
264
285
 
data/README.md CHANGED
@@ -24,12 +24,12 @@ Ginjo-rfm version 3 has been tested successfully on Ruby 1.8.7 thru 2.1.3.
24
24
 
25
25
  ## Documentation & Links
26
26
 
27
- * Ginjo-rfm rubygem <https://rubygems.org/gems/ginjo-rfm>
28
- * Rdoc location <http://rubydoc.info/github/ginjo/rfm/frames>
27
+ * Gem <https://rubygems.org/gems/ginjo-rfm>
28
+ * Rdoc <http://rubydoc.info/github/ginjo/rfm>
29
+ * Github <https://github.com/ginjo/rfm>
29
30
  * Discussion <http://groups.google.com/group/rfmcommunity>
30
- * Ginjo at github <https://github.com/ginjo/rfm>
31
- * Original homepage <http://sixfriedrice.com/wp/products/rfm/>
32
- * Lardawge at github <https://github.com/lardawge/rfm>
31
+ * Original <http://sixfriedrice.com/wp/products/rfm/>
32
+ * Lardawge <https://github.com/lardawge/rfm>
33
33
 
34
34
  ## Requirements
35
35
 
@@ -183,7 +183,7 @@ You can also include or extend the Rfm::Config module in any object in your proj
183
183
  # using :parent to set where this object inherits config settings from
184
184
  end
185
185
 
186
- Use `get_config` to view the compiled configuration settings for any object. Configuration compilation will start at the top (rfm.yml), then work down the heirarchy of objects to wherever you call the `get_config` method, merging in all global settings along the way. Subgroupings of settings will also be merged, if they are specified in a subgroup filter. A subgroup filter occurs any time you put `:use => :subgroup` in your configuration setting. You can have multiple subgroup filters, and when configuration compilation occurs, all subgroup filters are stacked up into an array and processed in order (as if you typed `:use=>[:subgroup1, :subgroup2, subgroup3, ...]` which is also allowed). `get_config` returns a compiled configuration hash, leaving all configuration settings in all modules and classes un-touched.
186
+ Use `get_config` to view the compiled configuration settings for any object. Configuration compilation will start at the top (rfm.yml), then work down the hierarchy of objects to wherever you call the `get_config` method, merging in all global settings along the way. Subgroupings of settings will also be merged, if they are specified in a subgroup filter. A subgroup filter occurs any time you put `:use => :subgroup` in your configuration setting. You can have multiple subgroup filters, and when configuration compilation occurs, all subgroup filters are stacked up into an array and processed in order (as if you typed `:use=>[:subgroup1, :subgroup2, subgroup3, ...]` which is also allowed). `get_config` returns a compiled configuration hash, leaving all configuration settings in all modules and classes un-touched.
187
187
 
188
188
  Person.get_config
189
189
 
@@ -512,7 +512,7 @@ All of these methods return an Rfm::Resultset object (see below), and every one
512
512
 
513
513
  my_layout.find({:state => "AZ"}, {:max_records => 10, :skip_records => 100})
514
514
 
515
- For a complete list of the available options, see the "expand_options" method in the Rfm::Server object in the file named server.rb.
515
+ For a complete list of the available options, see the "Common Options" section in the layout.rb file.
516
516
 
517
517
  Finally, if filemaker returns an error when executing any of these methods, an error will be raised in your Ruby script. There is one exception to this, though. If a find results in no records being found (FileMaker error # 401) I just ignore it and return you a Resultset with zero records in it. If you prefer an error in this case, add :raise_on_401 => true to the options you pass the Rfm::Server when you create it.
518
518
 
@@ -864,6 +864,6 @@ Other lead contributors:
864
864
  * Atsushi Matsuo was an early Rfm tester, and provided outstanding feedback, critical code fixes, and a lot of web exposure.
865
865
  * Jesse Antunes helped ensure that Rfm is stable and functional.
866
866
  * Larry Sprock added ssl support, switched the xml parser to a much faster Nokogiri, added the rspec testing framework, and refined code architecture.
867
- * William Richardson is the current maintainer of the ginjo-rfm fork and added support for multiple xml parsers, ActiveModel integration, field mapping, compound queries, logging, and a configuration framework.
867
+ * William Richardson is the current maintainer of the ginjo-rfm fork and added support for multiple xml parsers, ActiveModel integration, field mapping, compound queries, logging, scoping, and a configuration framework.
868
868
 
869
869
 
data/lib/rfm.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Rfm
2
- PATH = File.expand_path(File.dirname(__FILE__))
3
- $LOAD_PATH.unshift(PATH) unless $LOAD_PATH.include?(PATH)
2
+ PATH = File.expand_path(File.dirname(__FILE__))
3
+ $LOAD_PATH.unshift(PATH) unless $LOAD_PATH.include?(PATH)
4
4
  end
5
5
 
6
6
  #require 'thread' # some versions of ActiveSupport will raise error about Mutex unless 'thread' is loaded.
@@ -10,7 +10,7 @@ require 'rfm/utilities/core_ext'
10
10
  require 'rfm/utilities/case_insensitive_hash'
11
11
 
12
12
  module Rfm
13
-
13
+
14
14
  class CommunicationError < StandardError; end
15
15
  class ParameterError < StandardError; end
16
16
  class AuthenticationError < StandardError; end
@@ -28,18 +28,19 @@ module Rfm
28
28
  autoload :CompoundQuery,'rfm/utilities/compound_query'
29
29
  autoload :VERSION, 'rfm/version'
30
30
  autoload :Connection, 'rfm/utilities/connection.rb'
31
+ autoload :Scope, 'rfm/utilities/scope.rb'
32
+
33
+ module Metadata
34
+ autoload :Script, 'rfm/metadata/script'
35
+ autoload :Field, 'rfm/metadata/field'
36
+ autoload :FieldControl, 'rfm/metadata/field_control'
37
+ autoload :ValueListItem, 'rfm/metadata/value_list_item'
38
+ autoload :Datum, 'rfm/metadata/datum'
39
+ autoload :ResultsetMeta, 'rfm/metadata/resultset_meta'
40
+ autoload :LayoutMeta, 'rfm/metadata/layout_meta'
41
+ end
31
42
 
32
- module Metadata
33
- autoload :Script, 'rfm/metadata/script'
34
- autoload :Field, 'rfm/metadata/field'
35
- autoload :FieldControl, 'rfm/metadata/field_control'
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'
40
- end
41
-
42
- def info
43
+ def info
43
44
  rslt = <<-EEOOFF
44
45
  Gem name: ginjo-rfm
45
46
  Version: #{VERSION}
@@ -51,57 +52,55 @@ module Rfm
51
52
  rslt.gsub!(/^[ \t]*/, '')
52
53
  rslt
53
54
  rescue
54
- "Could not retrieve info: #{$!}"
55
- end
56
-
57
- def info_short
58
- "Using ginjo-rfm version #{::Rfm::VERSION} with #{SaxParser::Handler.get_backend}"
59
- end
60
-
61
- def_delegators 'Rfm::Factory', :servers, :server, :db, :database, :layout
62
- def_delegators 'Rfm::Config', :config, :get_config, :config_clear
63
- def_delegators 'Rfm::Resultset', :load_data
64
-
65
- def models(*args)
66
- Rfm::Base
67
- Rfm::Factory.models(*args)
68
- end
69
-
70
- def modelize(*args)
71
- Rfm::Base
72
- Rfm::Factory.modelize(*args)
73
- end
74
-
75
- def logger
76
- @@logger ||= get_config[:logger] || Logger.new(STDOUT).tap {|l| l.formatter = proc {|severity, datetime, progname, msg| "#{datetime}: Rfm-#{severity} #{msg}\n"}}
77
- end
78
-
79
- alias_method :log, :logger
80
-
81
- def logger=(obj)
82
- @@logger = obj
83
- end
84
-
85
- # DEFAULT_CLASS = CaseInsensitiveHash
86
- # TEMPLATE_PREFIX = File.join(File.dirname(__FILE__), 'rfm/utilities/sax/')
87
- # TEMPLATES = {
88
- # :fmpxmllayout => 'fmpxmllayout.yml',
89
- # :fmresultset => 'fmresultset.yml',
90
- # :fmpxmlresult => 'fmpxmlresult.yml',
91
- # :none => nil
92
- # }
93
-
94
- PARSER_DEFAULTS = {
95
- :default_class => CaseInsensitiveHash,
96
- :template_prefix => File.join(File.dirname(__FILE__), 'rfm/utilities/sax/'),
97
- :templates => {
98
- :fmpxmllayout => 'fmpxmllayout.yml',
99
- :fmresultset => 'fmresultset.yml',
100
- :fmpxmlresult => 'fmpxmlresult.yml',
101
- :none => nil
102
- }
103
- }
104
-
105
- extend self
106
-
55
+ "Could not retrieve info: #{$!}"
56
+ end
57
+
58
+ def info_short
59
+ "Using ginjo-rfm version #{::Rfm::VERSION} with #{SaxParser::Handler.get_backend}"
60
+ end
61
+
62
+ def_delegators 'Rfm::Factory', :servers, :server, :db, :database, :layout
63
+ def_delegators 'Rfm::Config', :config, :get_config, :config_clear
64
+ def_delegators 'Rfm::Resultset', :load_data
65
+
66
+ def models(*args)
67
+ Rfm::Factory.models(*args)
68
+ end
69
+
70
+ def modelize(*args)
71
+ Rfm::Factory.modelize(*args)
72
+ end
73
+
74
+ def logger
75
+ @@logger ||= get_config[:logger] || Logger.new(STDOUT).tap {|l| l.formatter = proc {|severity, datetime, progname, msg| "#{datetime}: Rfm-#{severity} #{msg}\n"}}
76
+ end
77
+
78
+ alias_method :log, :logger
79
+
80
+ def logger=(obj)
81
+ @@logger = obj
82
+ end
83
+
84
+ # DEFAULT_CLASS = CaseInsensitiveHash
85
+ # TEMPLATE_PREFIX = File.join(File.dirname(__FILE__), 'rfm/utilities/sax/')
86
+ # TEMPLATES = {
87
+ # :fmpxmllayout => 'fmpxmllayout.yml',
88
+ # :fmresultset => 'fmresultset.yml',
89
+ # :fmpxmlresult => 'fmpxmlresult.yml',
90
+ # :none => nil
91
+ # }
92
+
93
+ PARSER_DEFAULTS = {
94
+ :default_class => CaseInsensitiveHash,
95
+ :template_prefix => File.join(File.dirname(__FILE__), 'rfm/utilities/sax/'),
96
+ :templates => {
97
+ :fmpxmllayout => 'fmpxmllayout.yml',
98
+ :fmresultset => 'fmresultset.yml',
99
+ :fmpxmlresult => 'fmpxmlresult.yml',
100
+ :none => nil
101
+ }
102
+ }
103
+
104
+ extend self
105
+
107
106
  end # Rfm
@@ -1 +1 @@
1
- 3.0.9
1
+ 3.0.10
@@ -1,201 +1,197 @@
1
1
  module Rfm
2
- #
3
- # Adds ability to create Rfm::Base model classes that behave similar to ActiveRecord::Base models.
4
- # If you set your Rfm.config (or RFM_CONFIG) with your host, database, account, password, and
5
- # any other server/database options, you can provide your models with nothing more than a layout.
6
- #
7
- # class Person < Rfm::Base
8
- # config :layout => 'mylayout'
9
- # end
10
- #
11
- # And similar to ActiveRecord, you can define callbacks, validations, attributes, and methods on your model.
12
- # (if you have ActiveModel loaded).
13
- #
14
- # class Account < Rfm::Base
15
- # config :layout=>'account_xml'
16
- # before_create :encrypt_password
17
- # validates :email, :presence => true
18
- # validates :username, :presence => true
19
- # attr_accessor :password
20
- # end
21
- #
22
- # Then in your project, you can use these models just like ActiveRecord models.
23
- # The query syntax and options are still Rfm under the hood. Treat your model
24
- # classes like Rfm::Layout objects, with a few enhancements.
25
- #
26
- # @account = Account.new :username => 'bill', :password => 'pass'
27
- # @account.email = 'my@email.com'
28
- # @account.save!
29
- #
30
- # @person = Person.find({:name => 'mike'}, :max_records => 50)[0]
31
- # @person.update_attributes(:name => 'Michael', :title => "Senior Partner")
32
- # @person.save
33
- #
2
+
3
+ # Adds ability to create Rfm::Base model classes that behave similar to ActiveRecord::Base models.
4
+ # If you set your Rfm.config (or RFM_CONFIG) with your host, database, account, password, and
5
+ # any other server/database options, you can provide your models with nothing more than a layout.
6
+ #
7
+ # class Person < Rfm::Base
8
+ # config :layout => 'mylayout'
9
+ # end
10
+ #
11
+ # And similar to ActiveRecord, you can define callbacks, validations, attributes, and methods on your model.
12
+ # (if you have ActiveModel loaded).
13
+ #
14
+ # class Account < Rfm::Base
15
+ # config :layout=>'account_xml'
16
+ # before_create :encrypt_password
17
+ # validates :email, :presence => true
18
+ # validates :username, :presence => true
19
+ # attr_accessor :password
20
+ # end
21
+ #
22
+ # Then in your project, you can use these models just like ActiveRecord models.
23
+ # The query syntax and options are still Rfm under the hood. Treat your model
24
+ # classes like Rfm::Layout objects, with a few enhancements.
25
+ #
26
+ # @account = Account.new :username => 'bill', :password => 'pass'
27
+ # @account.email = 'my@email.com'
28
+ # @account.save!
29
+ #
30
+ # @person = Person.find({:name => 'mike'}, :max_records => 50)[0]
31
+ # @person.update_attributes(:name => 'Michael', :title => "Senior Partner")
32
+ # @person.save
33
+
34
34
  class Base < Rfm::Record #Hash
35
35
  extend Config
36
36
  config :parent => 'Rfm::Config'
37
-
37
+
38
38
  begin
39
- require 'active_model'
39
+ require 'active_model'
40
40
  include ActiveModel::Validations
41
41
  include ActiveModel::Serialization
42
42
  extend ActiveModel::Callbacks
43
43
  include ActiveModel::Validations::Callbacks
44
44
  define_model_callbacks(:create, :update, :destroy)
45
45
  rescue LoadError, StandardError
46
- def run_callbacks(*args)
47
- yield
48
- end
46
+ def run_callbacks(*args)
47
+ yield
48
+ end
49
49
  end
50
-
50
+
51
51
  def to_partial_path(object = self) #@object)
52
- return 'some/partial/path'
53
- ##### DISABLED HERE - ActiveModel Lint only needs a string #####
54
- ##### TODO: implement to_partial_path to return meaningful string.
55
- @partial_names[object.class.name] ||= begin
56
- object = object.to_model if object.respond_to?(:to_model)
57
-
58
- object.class.model_name.partial_path.dup.tap do |partial|
59
- path = @view.controller_path
60
- partial.insert(0, "#{File.dirname(path)}/") if partial.include?(?/) && path.include?(?/)
52
+ return 'some/partial/path'
53
+ ##### DISABLED HERE - ActiveModel Lint only needs a string #####
54
+ ##### TODO: implement to_partial_path to return meaningful string.
55
+ # @partial_names[object.class.name] ||= begin
56
+ # object = object.to_model if object.respond_to?(:to_model)
57
+
58
+ # object.class.model_name.partial_path.dup.tap do |partial|
59
+ # path = @view.controller_path
60
+ # partial.insert(0, "#{File.dirname(path)}/") if partial.include?(?/) && path.include?(?/)
61
+ # end
62
+ # end
63
+ end
64
+
65
+ class << self
66
+
67
+ # Access layout functions from base model
68
+ def_delegators :layout, :db, :server, :field_controls, :field_names, :value_lists, :total_count,
69
+ :query, :all, :delete, :portal_meta, :portal_names, :database, :table, :count, :ignore_bad_data
70
+
71
+ def inherited(model)
72
+ (Rfm::Factory.models << model).uniq unless Rfm::Factory.models.include? model
73
+ model.config :parent=>'Rfm::Base'
74
+ end
75
+
76
+ def config(*args)
77
+ super(*args){|options| @config.merge!(:layout=>options[:strings][0]) if options[:strings] && options[:strings][0]}
78
+ end
79
+
80
+ # Access/create the layout object associated with this model
81
+ def layout
82
+ return @layout if @layout
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
88
+
89
+ # Added by wbr to give config hierarchy: layout -> model -> sublayout
90
+ #config :parent=>'parent_layout'
91
+ #config :parent=>'Rfm::Config'
92
+ #@layout.config model
93
+ #@layout.config :parent=>self
94
+
95
+ @layout.model = self
96
+ @layout
97
+ end
98
+
99
+ # # Access the parent layout of this model
100
+ # def parent_layout
101
+ # layout #.parent_layout
102
+ # end
103
+
104
+ # Just like Layout#find, but searching by record_id will return a record, not a resultset.
105
+ def find(find_criteria, options={})
106
+ #puts "base.find-#{layout.object_id}"
107
+ r = layout.find(find_criteria, options)
108
+ if ![Hash,Array].include?(find_criteria.class) and r.size == 1
109
+ r[0]
110
+ else
111
+ r
61
112
  end
113
+ rescue Rfm::Error::RecordMissingError
114
+ nil
115
+ end
116
+
117
+ # Layout#any, returns single record, not resultset
118
+ def any(*args)
119
+ layout.any(*args)[0]
120
+ end
121
+
122
+ # New record, save, (with callbacks & validations if ActiveModel is loaded)
123
+ def create(*args)
124
+ new(*args).send :create
125
+ end
126
+
127
+ # Using this method will skip callbacks. Use instance method +#update+ instead
128
+ def edit(*args)
129
+ layout.edit(*args)[0]
62
130
  end
131
+
132
+ end # class << self
133
+
134
+
135
+ # Is this a newly created record, not saved yet?
136
+ def new_record?
137
+ return true if (self.record_id.nil? || self.record_id.empty?)
63
138
  end
64
-
65
- class << self
66
-
67
- # Access layout functions from base model
68
- def_delegators :layout, :db, :server, :field_controls, :field_names, :value_lists, :total_count,
69
- :query, :all, :delete, :portal_meta, :portal_names, :database, :table, :count, :ignore_bad_data
70
-
71
- def inherited(model)
72
- (Rfm::Factory.models << model).uniq unless Rfm::Factory.models.include? model
73
- model.config :parent=>'Rfm::Base'
74
- end
75
-
76
- def config(*args)
77
- super(*args){|options| @config.merge!(:layout=>options[:strings][0]) if options[:strings] && options[:strings][0]}
78
- end
79
-
80
- # Access/create the layout object associated with this model
81
- def layout
82
- return @layout if @layout
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
88
-
89
- # Added by wbr to give config heirarchy: layout -> model -> sublayout
90
- #config :parent=>'parent_layout'
91
- #config :parent=>'Rfm::Config'
92
- #@layout.config model
93
- #@layout.config :parent=>self
94
-
95
- @layout.model = self
96
- @layout
97
- end
98
-
99
- # # Access the parent layout of this model
100
- # def parent_layout
101
- # layout #.parent_layout
102
- # end
103
-
104
- # Just like Layout#find, but searching by record_id will return a record, not a resultset.
105
- def find(find_criteria, options={})
106
- #puts "base.find-#{layout.object_id}"
107
- r = layout.find(find_criteria, options)
108
- if ![Hash,Array].include?(find_criteria.class) and r.size == 1
109
- r[0]
110
- else
111
- r
112
- end
113
- rescue Rfm::Error::RecordMissingError
114
- nil
115
- end
116
-
117
- # Layout#any, returns single record, not resultset
118
- def any(*args)
119
- layout.any(*args)[0]
120
- end
121
-
122
- # New record, save, (with callbacks & validations if ActiveModel is loaded)
123
- def create(*args)
124
- new(*args).send :create
125
- end
126
-
127
- # Using this method will skip callbacks. Use instance method +#update+ instead
128
- def edit(*args)
129
- layout.edit(*args)[0]
130
- end
131
-
132
- end # class << self
133
-
134
-
135
-
136
-
137
-
138
-
139
- # Is this a newly created record, not saved yet?
140
- def new_record?
141
- return true if (self.record_id.nil? || self.record_id.empty?)
142
- end
143
-
144
- # Reload record from database
145
- # TODO: handle error when record has been deleted
146
- # TODO: Move this to Rfm::Record.
147
- def reload(force=false)
148
- if (@mods.empty? or force) and record_id
149
- @mods.clear
150
- self.replace_with_fresh_data layout.find(self.record_id)[0] #self.class.find(self.record_id)
139
+
140
+ # Reload record from database
141
+ # TODO: handle error when record has been deleted
142
+ # TODO: Move this to Rfm::Record.
143
+ def reload(force=false)
144
+ if (@mods.empty? or force) and record_id
145
+ @mods.clear
146
+ self.replace_with_fresh_data layout.find(self.record_id)[0] #self.class.find(self.record_id)
151
147
  end
152
148
  end
153
-
149
+
154
150
  # Mass update of record attributes, without saving.
155
151
  def update_attributes(new_attr)
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
152
+ new_attr.each do |k,v|
153
+ k = k.to_s.downcase
154
+ if keys.include?(k)
155
+ @mods[k] = v
156
+ self[k] = v
157
+ else
158
+ instance_variable_set("@#{k}", v)
159
+ end
160
+ end
165
161
  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
192
-
162
+ # # Mass update of record attributes, without saving.
163
+ # # TODO: return error or nil if input hash contains no recognizable keys.
164
+ # def update_attributes(new_attr)
165
+ # # creates new special hash
166
+ # input_hash = Rfm::CaseInsensitiveHash.new
167
+ # # populate new hash with input, coercing keys to strings
168
+ # #new_attr.each{|k,v| input_hash.merge! k.to_s=>v}
169
+ # new_attr.each{|k,v| input_hash[k.to_s] = v}
170
+ # # loop thru each layout field, adding data to @mods
171
+ # self.class.field_controls.keys.each do |field|
172
+ # field_name = field.to_s
173
+ # if input_hash.has_key?(field_name)
174
+ # #@mods.merge! field_name=>(input_hash[field_name] || '')
175
+ # @mods[field_name] = (input_hash[field_name] || '')
176
+ # end
177
+ # end
178
+ # # loop thru each input key-value,
179
+ # # creating new attribute if key doesn't exist in model.
180
+ # input_hash.each do |k,v|
181
+ # if !self.class.field_controls.keys.include?(k) and self.respond_to?(k)
182
+ # self.instance_variable_set("@#{k}", v)
183
+ # end
184
+ # end
185
+ # self.merge!(@mods) unless @mods == {}
186
+ # #self.merge!(@mods) unless @mods == Rfm::CaseInsensitiveHash.new
187
+ # end
188
+
193
189
  # Mass update of record attributes, with saving.
194
190
  def update_attributes!(new_attr)
195
191
  self.update_attributes(new_attr)
196
192
  self.save!
197
193
  end
198
-
194
+
199
195
  # Save record modifications to database (with callbacks & validations). If record cannot be saved will raise error.
200
196
  def save!
201
197
  #return unless @mods.size > 0
@@ -206,95 +202,95 @@ module Rfm
206
202
  self.create
207
203
  end
208
204
  end
209
-
210
- # Same as save!, but will not raise error.
205
+
206
+ # Same as save!, but will not raise error.
211
207
  def save
212
208
  save!
213
209
  rescue
214
210
  (self.errors[:base] rescue []) << $!
215
211
  return nil
216
212
  end
217
-
218
- # Just like Layout#save_if_not_modified, but with callbacks & validations.
213
+
214
+ # Just like Layout#save_if_not_modified, but with callbacks & validations.
219
215
  def save_if_not_modified
220
216
  update(@mod_id) if @mods.size > 0
221
- end
222
-
217
+ end
218
+
223
219
  # Delete record from database, with callbacks & validations.
224
- def destroy
225
- return unless record_id
226
- run_callbacks :destroy do
227
- self.class.delete(record_id)
228
- @destroyed = true
229
- @mods.clear
230
- end
231
- self.freeze
232
- #self
233
- end
234
-
235
- def destroyed?
236
- @destroyed
237
- end
238
-
239
- # For ActiveModel compatibility
240
- def to_model
241
- self
242
- end
243
-
244
- def persisted?
245
- record_id ? true : false
246
- end
247
-
248
- def to_key
249
- record_id ? [record_id] : nil
250
- end
251
-
252
- def to_param
253
- record_id
254
- end
255
-
256
-
257
- protected # Base
258
-
259
- def self.create_from_new(*args)
260
- layout.create(*args)[0]
261
- end
262
-
220
+ def destroy
221
+ return unless record_id
222
+ run_callbacks :destroy do
223
+ self.class.delete(record_id)
224
+ @destroyed = true
225
+ @mods.clear
226
+ end
227
+ self.freeze
228
+ #self
229
+ end
230
+
231
+ def destroyed?
232
+ @destroyed
233
+ end
234
+
235
+ # For ActiveModel compatibility
236
+ def to_model
237
+ self
238
+ end
239
+
240
+ def persisted?
241
+ record_id ? true : false
242
+ end
243
+
244
+ def to_key
245
+ record_id ? [record_id] : nil
246
+ end
247
+
248
+ def to_param
249
+ record_id
250
+ end
251
+
252
+
253
+ protected # Base
254
+
255
+ def self.create_from_new(*args)
256
+ layout.create(*args)[0]
257
+ end
258
+
263
259
  # shunt for callbacks when not using ActiveModel
264
260
  def callback_deadend (*args)
265
261
  yield #(*args)
266
262
  end
267
-
263
+
268
264
  def create
269
265
  raise "Record not valid" if (defined?(ActiveModel::Validations) && !valid?)
270
266
  run_callbacks :create do
271
267
  return unless @mods.size > 0
272
- # merge_rfm_result self.class.create_from_new(@mods)
273
- replace_with_fresh_data self.class.create_from_new(@mods)
274
- end
275
- self
276
- end
277
-
268
+ # merge_rfm_result self.class.create_from_new(@mods)
269
+ replace_with_fresh_data self.class.create_from_new(@mods)
270
+ end
271
+ self
272
+ end
273
+
278
274
  def update(mod_id=nil)
279
275
  raise "Record not valid" if (defined?(ActiveModel::Validations) && !valid?)
280
276
  return false unless record_id
281
- run_callbacks :update do
282
- return unless @mods.size > 0
283
- unless mod_id
284
- # regular save
285
- # merge_rfm_result self.class.send :edit, record_id, @mods
286
- replace_with_fresh_data self.class.send :edit, record_id, @mods
287
- else
288
- # save_if_not_modified
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
277
+ run_callbacks :update do
278
+ return unless @mods.size > 0
279
+ unless mod_id
280
+ # regular save
281
+ # merge_rfm_result self.class.send :edit, record_id, @mods
282
+ replace_with_fresh_data self.class.send :edit, record_id, @mods
283
+ else
284
+ # save_if_not_modified
285
+ # merge_rfm_result self.class.send :edit, record_id, @mods, :modification_id=>mod_id
286
+ replace_with_fresh_data self.class.send :edit, record_id, @mods, :modification_id=>mod_id
291
287
  end
292
- end
293
- self
294
- end
295
-
296
- # Deprecated in favor of Record#replace_with_fresh_data
297
- def merge_rfm_result(result_record)
288
+ end
289
+ self
290
+ end
291
+
292
+ # Deprecated in favor of Record#replace_with_fresh_data
293
+ def merge_rfm_result(result_record)
298
294
  return unless @mods.size > 0
299
295
  @record_id ||= result_record.record_id
300
296
  self.merge! result_record
@@ -302,7 +298,7 @@ module Rfm
302
298
  self || {}
303
299
  #self || Rfm::CaseInsensitiveHash.new
304
300
  end
305
-
301
+
306
302
  end # Base
307
303
 
308
304
  end # Rfm