ginjo-rfm 2.0.pre31 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Changelog
2
2
 
3
- ## Ginjo-Rfm 2.0.pre
3
+ ## Ginjo-Rfm 2.0.0
4
4
 
5
- * Alternative XML parsers using ActiveSupport::XmlMini interface
5
+ * ActiveModel compatibility allows Rails ActiveRecord-style models
6
6
 
7
- * ActiveModel compatibility allows Rails-like models
7
+ * Alternative XML parsers using ActiveSupport::XmlMini interface
8
8
 
9
- * Complex queries with Layout#query method
9
+ * Compound queries with multiple omitable find-requests
10
10
 
11
11
  * Configuration API manages settings of multiple server/db/layout/etc setups
12
12
 
data/README.md CHANGED
@@ -1,37 +1,36 @@
1
1
  # ginjo-rfm
2
2
 
3
- Rfm is a Ruby/Filemaker adapter - a ruby gem that allows scripts and applications to exchange commands and data with Filemaker Pro using Filemaker's XML interface. Ginjo-rfm picks up from the lardawge-rfm gem and continues to refine code and fix bugs. Version 2.0 adds some major enhancements, while remaining compatible with ginjo-rfm 1.4.x and lardawge-rfm 1.4.x.
3
+ Rfm is a Ruby-Filemaker adapter, a Ruby gem that allows scripts and applications to exchange commands and data with Filemaker Pro using Filemaker's XML interface. Ginjo-rfm picks up from the lardawge-rfm gem and continues to refine code and fix bugs. Version 2.0 adds some major enhancements, while remaining compatible with ginjo-rfm 1.4.x and lardawge-rfm 1.4.x.
4
4
 
5
5
 
6
6
  ## Documentation & Links
7
7
 
8
- * Ginjo-rfm rubygem <https://rubygems.org/gems/ginjo-rfm>
9
- * Original homepage <http://sixfriedrice.com/wp/products/rfm/>
10
- * Rdoc location <http://rubydoc.info/github/ginjo/rfm/frames>
11
- * Discussion <http://groups.google.com/group/rfmcommunity>
12
- * Ginjo at github <https://github.com/ginjo/rfm>
13
- * Lardawge at github <https://github.com/lardawge/rfm>
8
+ * Ginjo-rfm rubygem <https://rubygems.org/gems/ginjo-rfm>
9
+ * Original homepage <http://sixfriedrice.com/wp/products/rfm/>
10
+ * Rdoc location <http://rubydoc.info/github/ginjo/rfm/frames>
11
+ * Discussion <http://groups.google.com/group/rfmcommunity>
12
+ * Ginjo at github <https://github.com/ginjo/rfm>
13
+ * Lardawge at github <https://github.com/lardawge/rfm>
14
14
 
15
15
 
16
16
  ## New in version 2.0
17
17
 
18
- ### Data modeling with ActiveModel and graceful degradation without ActiveModel.
18
+ Ginjo-rfm 2.0 brings new features to Rfm, making it easier than ever to work with Filemaker data from your Ruby scripts.
19
+
20
+ * Rails-like modeling with ActiveModel
21
+ * Support for multiple XML Parsers
22
+ * Configuration API
23
+ * Compound Filemaker queries with omitable requests
24
+ * Full metadata support
25
+
26
+
27
+ ### Data Modeling with ActiveModel
19
28
 
20
29
  If you can load ActiveModel in your project, you can have model callbacks, validations, and other ActiveModel features.
21
30
  If you can't load ActiveModel (because you're using something incompatible, like Rails 2),
22
- you can still use Rfm models... minus callbacks & validations. Rfm models give you basic
31
+ you can still use Rfm models... minus the ActiveModel-specific features like callbacks and validations. Rfm models give you basic
23
32
  data modeling with easy configuration and CRUD features.
24
33
 
25
- class User < Rfm::Base
26
- config :layout => 'user_layout'
27
- end
28
-
29
- @user = User.find 12345
30
- @user.update_attributes(:name => 'bill', :login => 'admin')
31
- @user.save!
32
-
33
- With ActiveModel loaded, you get callbacks, validations, and many other ActiveModel features.
34
-
35
34
  class User < Rfm::Base
36
35
  config :layout=>'user_layout'
37
36
  before_save :encrypt_password
@@ -41,25 +40,13 @@ With ActiveModel loaded, you get callbacks, validations, and many other ActiveMo
41
40
  @user = User.new :username => 'bill', :password => 'pass'
42
41
  @user.email = 'my@email.com'
43
42
  @user.save!
44
-
45
- If you prefer, you can create models on-the-fly from any layout.
46
43
 
47
- my_layout.modelize
48
-
49
- # => MyLayoutName (subclassed from Rfm::Base, represented by your layout's name)
50
-
51
- Or create models for an entire database, all at once.
52
44
 
53
- Rfm.modelize :my_db_name_or_config
54
-
55
- # => [MyLayout, AnotherLayout, ThirdLayout, AndSoOn, ...]
56
-
57
-
58
- ### Choice of XML parsers
45
+ ### Choice of XML Parsers
59
46
 
60
47
  Ginjo-rfm 2.0 uses ActiveSupport's XmlMini parsing interface, which has built-in support for
61
- LibXML, Nokogiri, and REXML. Additionally, ginjo-rfm includes a module for Hpricot parsing.
62
- You can specifiy which parser to use or load them all and let Rfm decide.
48
+ LibXML, Nokogiri, and REXML. Additionally, ginjo-rfm includes adapters for Ox and Hpricot parsing.
49
+ You can specifiy which parser to use or let Rfm decide.
63
50
 
64
51
  Rfm.config :parser => :libxml
65
52
 
@@ -74,89 +61,75 @@ Choose your preferred parser globaly, as in the above example, or set a differen
74
61
  config :parser => :hpricot
75
62
  end
76
63
 
77
- Not only do you have 4 XML backend parsers to choose from, but you also have the option of choosing from different parsing shemes - the DOM parsing scheme, or the streaming (SAX or SAX-like) scheme. This gives you six different available parsing possilities.
78
-
79
- * LibXML DOM
80
- * LibXML SAX
81
- * Nokogiri DOM
82
- * Nokogiri SAX
83
- * Hpricot DOM
84
- * REXML DOM
85
-
86
- ### Configuration API
87
-
88
- The ginjo-rfm configuration module is a heirarchical system that allows you to configure settings at a global level
89
- and then recall just the settings you need, where you need them. Configuration settings can be simple
90
- values, or they can be named groups of values.
64
+ The current parsing options are
65
+
66
+ :jdom -> JDOM (for JRuby)
67
+ :oxsax -> Ox SAX
68
+ :libxml -> LibXML Tree
69
+ :libxmlsax -> LibXML SAX
70
+ :nokogirisax -> Nokogiri SAX
71
+ :nokogiri -> Nokogiri Tree
72
+ :hpricot -> Hpricot Tree
73
+ :rexml -> REXML Tree
74
+ :rexmlsax -> REXML SAX
75
+
76
+ If you're wondering about performance, here are some preliminary benchmark results. Each backend parsed a fmresultset.xml and a FMPXMLLAYOUT.xml 30 times each. Results have differed across environments with different test data, so this data is by no means definitive. Also note that earlier versions of ActiveSupport did not contain all of the parsing backend options mentioned here.
77
+
78
+ user system total real
79
+ ActiveSupport::XmlMini_OxSAX
80
+ 0.200000 0.010000 0.210000 ( 0.211842)
81
+ ActiveSupport::XmlMini_LibXML
82
+ 0.400000 0.010000 0.410000 ( 0.411823)
83
+ ActiveSupport::XmlMini_LibXMLSAX
84
+ 0.400000 0.010000 0.410000 ( 0.411360)
85
+ ActiveSupport::XmlMini_NokogiriSAX
86
+ 0.670000 0.010000 0.680000 ( 0.682885)
87
+ ActiveSupport::XmlMini_Nokogiri
88
+ 0.970000 0.030000 1.000000 ( 0.998673)
89
+ ActiveSupport::XmlMini_Hpricot
90
+ 1.950000 0.060000 2.010000 ( 2.011355)
91
+ ActiveSupport::XmlMini_REXML
92
+ 8.710000 0.180000 8.890000 ( 9.015836)
93
+ ActiveSupport::XmlMini_REXMLSAX
94
+ 6.320000 0.040000 6.360000 ( 6.377179)
91
95
 
92
- For simple applications, put all of your configuration in a top-level hash, RFM_CONFIG,
93
- and let Rfm do the rest. For more complicated setups, use configuration subgroups,
94
- and/or set configuration on-the-fly when you create Server, Database, Layout, or Base objects.
95
96
 
96
- Use RFM_CONFIG
97
97
 
98
- RFM_CONFIG = {
99
- :host => 'main_host',
100
- :database => 'main_database',
101
- :account_name => 'myname',
102
- :password => 'somepass',
103
- :second_server => {
104
- :host => 'second_host',
105
- :database => 'second_database'
106
- }
98
+ ### Configuration API
107
99
 
108
- Or set global configuration with the 'config' method
100
+ The ginjo-rfm configuration module lets you store your settings in several different ways. Store some, or all, of your project-specific settings in a rfm.yml file at the root of your project, or in your Rails config/ directory. Settings can also be put in a RFM_CONFIG constant at the top level of your project. Configuration settings can be simple key=>values, or they can be named groups of key=>values. Configuration can also be passed to various Rfm methods during load and runtime, as individual settings or as groups.
109
101
 
110
- Rfm.config :host => 'main_host',
111
- :database => 'main_database',
112
- :account_name => 'myname',
113
- :password => 'somepass',
114
- :second_server => {
115
- :host => 'second_host',
116
- :database => 'second_database'
117
- }
118
-
119
- Set configuration of RFM::Base
102
+ rfm.yml
120
103
 
121
- Rfm::Base.config :ssl => true
104
+ :ssl: true
105
+ :root_cert: false
106
+ :timeout: 10
107
+ :port: 443
108
+ :host: live.mydomain.com
109
+ :account_name: admin
110
+ :password: pass
111
+ :database: MyFmDb
122
112
 
123
- Set a model's configuration
113
+ Set a model's configuration.
124
114
 
125
- class MyClass < Rfm::Base
126
- config :second_server, :layout => 'mylayout'
115
+ class MyModel < Rfm::Base
116
+ config :layout => 'mylayout'
127
117
  end
128
-
129
- View model-specific configuration
130
-
131
- MyClass.config
132
-
133
- # => {:host => 'second_host', :database => 'second_database'}
134
118
 
135
- View the merged configurations of all relevent levels in the configuration chain.
136
-
137
- MyClass.get_config
138
-
139
- # => {:host => 'second_host', :database => 'second_database', :account_name => 'myname', :password => 'somepass', :ssl => true}
140
119
 
120
+ ### Compound Filemaker Queries, with Omitable FMP Find Requests
141
121
 
142
- Calling the get_config method will show you what compilation of config settings are seen at any given point in Rfm and/or in your application. The current heirarchy of configurable objects in Rfm, starting at the top:
122
+ Create a Filemaker 'omit' request by including an :omit key with a value of true.
143
123
 
144
- * RFM_CONFIG # a user-defined hash
145
- * Rfm::Config # top-level config module
146
- * Rfm::Factory # where server, database, and layout objects are managed
147
- * Rfm::Base # master modeling class
148
- * MyModel # custom modeling class
124
+ my_layout.find :field1 => 'val1', :field2 => 'val2', :omit => true
149
125
 
126
+ Create multiple Filemaker find requests by passing an array of hashes to the #find method.
150
127
 
128
+ my_layout.find [{:field1 => 'bill', :field2 => 'admin'}, {:field2 => 'staff', :field3 => 'inactive', :omit => true}, ...]
151
129
 
130
+ If the value of a field in a find request is an array of strings, the string values will be logically OR'd in the query.
152
131
 
153
- ### Complex Queries
154
-
155
- Create queries with mixed boolean logic, mimicing Filemaker's multiple-request find.
156
-
157
- layout.query :fieldOne => ['=val1','>=val2','<val3'], :fieldTwo =>'someValue'
158
-
159
- This will create 3 "find requests" (in a single call to FM Server), one for each value in the fieldOne array, AND'd with the fieldTwo value.
132
+ my_layout.find :fieldOne => ['bill','mike','bob'], :fieldTwo =>'staff'
160
133
 
161
134
 
162
135
  ### Full Metadata Support
@@ -167,16 +140,10 @@ This will create 3 "find requests" (in a single call to FM Server), one for each
167
140
  * Layout fields
168
141
  * Layout portals
169
142
  * Resultset meta
170
- * Field meta
171
- * Portal meta
172
-
173
- From ginjo-rfm 1.4.x, the following enhancements are also included.
143
+ * Field definition meta
144
+ * Portal definition meta
174
145
 
175
- * Connection timeout settings
176
-
177
- * Value-list alternate display
178
-
179
- There are also many enhancements to make it easier than ever to get the objects or data you want. Some examples:
146
+ There are also many enhancements to make it easier to get the objects or data you want. Some examples:
180
147
 
181
148
  Get a database object using default config
182
149
 
@@ -197,23 +164,49 @@ Get the portal names (table-occurence names) on the current layout
197
164
  Get the names of fields on the current layout
198
165
 
199
166
  my_record.field_names
167
+
168
+ ### From ginjo-rfm 1.4.x
169
+
170
+ From ginjo-rfm 1.4.x, the following features are also included.
171
+
172
+ Connection timeout settings
173
+
174
+ Rfm.config :timeout => 10
175
+
176
+ Value-list alternate display
177
+
178
+ i = array_of_value_list_items[3] # => '8765'
179
+ i.value # => '8765'
180
+ i.display # => '8765 Amy'
181
+
200
182
 
201
183
  ### Compatibility
202
184
 
203
- Ginjo-rfm 2.0 is compatible with previous versions of Rfm - Ginjo, Lardawge, and SFR. However, much has been changed in the low-level workings of the code, in orer to pave the way for data modeling and flexible XML adapters. If you have scripts that reach deep into the guts of Rfm 1.0 thru 1.4.x, you may find that some things are slightly different in 2.0. Additionally, some long-standing bugs have been fixed that may have been so de rigeur, that the "correct behavior" in Rfm 2.0 may break scripts that relied on the previously buggy functions. These low level changes, and the addition of major new functionality, led the decision to release this version of Rfm as 2.0, instead of 1.5.
185
+ Ginjo-rfm 2.0 is compatible with previous versions of Rfm - Ginjo, Lardawge, and SFR. However, much has been changed in the low-level workings of the code. If you have scripts that reach deep into the guts of Rfm 1.0 thru 1.4.x, you may find that some things are slightly different in 2.0. Additionally, some long-standing bugs have been fixed that may have been so de rigeur, that the "correct behavior" in Rfm 2.0 may break scripts that relied on the previously buggy functions. These low level changes, and the addition of major new functionality, led the decision to release this version of Rfm as 2.0, instead of 1.5.
186
+
187
+
188
+ ## Download & Installation
189
+
190
+ There are at least 4 ways to download ginjo-rfm.
204
191
 
192
+ * With Bundler: gem 'ginjo-rfm'
193
+ * With the command line: gem install ginjo-rfm
194
+ * From https://rubygems.org/gems/ginjo-rfm
195
+ * From https://github.com/ginjo/rfm
205
196
 
206
- ## Installation
197
+ Ginjo-rfm requires the ActiveSupport gem for several features, including XML parsing. Rfm has been tested and works with ActiveSupport 2.3.5 thru 3.1.3, on both ruby 1.8.7 and ruby 1.9.2. ActiveModel requires ActiveSupport 3+ and is not compatible with ActiveSupport 2.3.x. So while you CAN use ginjo-rfm with Rails 2.3, you will not have ActiveModel features like callbacks and validations. Basic modeling functionality and Filemaker interaction will continue to work, unaffected by the presence or absence of ActiveModel.
207
198
 
208
- Ginjo-rfm requires ActiveSupport for several features, including XML parsing. Rfm has been tested and works with ActiveSupport 2.3.5 thru 3.1.3. ActiveModel requires ActiveSupport 3+ and is not compatible with ActiveSupport 2.3.x. So while you CAN use ginjo-rfm with Rails 2.3, you will not have ActiveModel features like callbacks and validations. Basic model functionality and Filemaker interaction will continue to work, unaffected by the presence or absence of ActiveModel.
199
+ For the best performance, it is recommended that you use the Ox, Libxml-ruby, Nokogiri, or Hpricot parser. Ginjo-rfm does not require these gems by dependency, so you will have to make sure they are installed on your machine and/or specified in your Gemfile, if you wish to use them. If you don't want to install any of these parsers, Rfm will use the REXML parser included with the Ruby standard library. Similarly, ginjo-rfm does not require ActiveModel by dependency, so also make sure that is installed and/or specified in your Gemfile if you wish to use ActiveModel features.
200
+
201
+ Note that the installation of Ox, Libxml-ruby, Nokogiri, or Hpricot gems will require further dependencies. Please see the install instructions for each parser to get them installed and running on your system.
209
202
 
210
- To get the best performance, it is recommended that you use the LibXML or Nokogiri parser. Ginjo-rfm does not require these gems by dependency, so you will have to make sure they are installed on your machine and/or specified in your Gemfile, if you wish to use them. Similarly, ginjo-rfm does not require ActiveModel by dependency, so also make sure that is installed and/or specified in your Gemfile, if you wish to use ActiveModel features.
211
203
 
212
204
  ### Using Bundler and/or Rails >= 3.0
213
205
 
214
- In the Gemfile:
206
+ In your Gemfile:
215
207
 
216
208
  gem 'ginjo-rfm'
209
+ gem 'ox' # optional
217
210
  gem 'libxml-ruby' # optional
218
211
  gem 'nokogiri' # optional
219
212
  gem 'hpricot' # optional
@@ -234,6 +227,7 @@ If you are not using Bundler, Rfm will pick up the XML parsers and ActiveModel a
234
227
  In your shell:
235
228
 
236
229
  gem install ginjo-rfm
230
+ gem install ox # optional
237
231
  gem install nokogiri # optional
238
232
  gem install libxml-ruby # optional
239
233
  gem install hpricot # optional
@@ -245,55 +239,251 @@ Once the gem is installed, you can use rfm in your ruby scripts by requiring it:
245
239
  require 'rfm'
246
240
 
247
241
 
248
-
249
242
  ### Edge - in an upcoming version of ginjo-rfm
250
243
 
251
244
  Try out unreleased features of ginjo-rfm in the edge branch.
252
245
 
253
246
  #gemfile
254
247
  gem 'ginjo-rfm', :git=>'git://github.com/ginjo/rfm.git', :branch=>'edge'
255
-
256
-
257
248
 
258
- ## Basic usage
259
249
 
260
- Put your configuration settings in a hash represented by RFM_CONFIG. This will make it easier to get and use objects in Rfm.
250
+
251
+ ## Ginjo-rfm Basic Usage
252
+
253
+ The first step in getting connected to your Filemaker databases with Rfm is to store your configuration settings in a yaml file or in the RFM_CONFIG hash. The second step is creating a model that represents a layout from one of your Filemaker databases.
254
+
255
+ ### Configuration
256
+
257
+ In previous versions of Rfm, you may have stored your configuration settings in a variable or constant, then passed those settings to Rfm::Server.new(MY_SETTINGS). Now you can put your configuration settings in a rfm.yml file at the root of your project or in your project's config/ directory, and Rfm will use those settings automatically when building your Model's Server, Database, and Layout objects.
258
+
259
+ rfm.yml
260
+
261
+ :ssl: true
262
+ :root_cert: false
263
+ :timeout: 10
264
+ :port: 443
265
+ :host: my.host.com
266
+ :account_name: myname
267
+ :password: somepass
268
+ :database: MyFmDb
269
+
270
+ Or put your configuration settings in a hash called RFM_CONFIG. Rfm will pick those up just as with the yaml file.
261
271
 
262
272
  RFM_CONFIG = {
263
- :host => 'main_host',
264
- :database => 'main_database',
273
+ :host => 'my.host.com',
274
+ :database => 'MyFmDb',
265
275
  :account_name => 'myname',
266
276
  :password => 'somepass',
267
- :ssl => false,
268
- :second_server => {
269
- :host => 'second_host',
270
- :database => 'second_database'
277
+ :ssl => true,
278
+ :root_cert => false,
279
+ :port => 443,
280
+ :timeout => 10
271
281
  }
272
282
 
273
- Then you have two easy ways to access your layouts - and your data.
283
+ You can use configuration subgroups to seperate global settings from environment-specific settings.
284
+
285
+ :ssl: true
286
+ :root_cert: false
287
+ :timeout: 10
288
+ :port: 443
289
+ :development:
290
+ :host: dev.mydomain.com
291
+ :account_name: admin
292
+ :password: pass
293
+ :database: DevFmDb
294
+ :production:
295
+ :host: live.mydomain.com
296
+ :account_name: admin
297
+ :password: pass
298
+ :database: LiveFmDb
299
+
300
+ Then in your environment files (or wherever you put environment-specific configuration in your ruby project),
301
+ specifiy which subgroup to use.
302
+
303
+ RFM_CONFIG = {:use => :development}
304
+
305
+ You can use configuration subgroups to contain any arbitrary groups of settings.
306
+
307
+ :ssl: true
308
+ :root_cert: false
309
+ :timeout: 10
310
+ :port: 443
311
+ :customer1:
312
+ :host: customer1.com
313
+ :account_name: cust1
314
+ :password: pass
315
+ :database: custOneFmDb
316
+ :customer2:
317
+ :host: customer2.com
318
+ :account_name: cust2
319
+ :password: pass
320
+ :database: custTwoFmDb
321
+
322
+ Use the configuration setting method `config` to set configuration for specific objects, like Rfm models. When you pass a `:use => :subgroup` to the `config` method, you're saying use that subgroup of settings.
323
+
324
+ class MyModel < Rfm::Base
325
+ config :use => :customer1, :layout => 'some_layout'
326
+ end
327
+
328
+ The current heirarchy of configurable objects in Rfm, starting at the top, is:
329
+
330
+ * rfm.yml # file of settings in yaml format
331
+ * RFM_CONFIG # user-defined hash
332
+ * Rfm::Config # top-level config module, inherits settings from RFM_CONFIG and rfm.yml
333
+ * Rfm::Factory # where server, database, and layout objects are managed, inherits settings from Rfm::Config
334
+ * Rfm::Base # master modeling class, inherits settings from Rfm::Config
335
+ * MyModel # sublcassed custom modeling class, inherits settings from Rfm::Base
274
336
 
337
+ You can also include or extend the Rfm::Config module in any object in your project to gain Rfm configuration abilities for that object.
338
+
339
+ module MyModule
340
+ include Rfm::Config
341
+ config :host => 'myhost.com', :database => 'mydb', :account_name => 'name', :password => 'pass'
342
+ # inherits settings from Rfm::Config by default
343
+ end
344
+
345
+ class Person < Rfm::Base
346
+ config :parent => MyModule, :layout => 'some_layout'
347
+ # using :parent to set where this object inherits config settings from
348
+ end
349
+
350
+ 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.
351
+
352
+ Person.get_config
353
+
354
+ # => {:ssl => true, :timeout => 10, :root_cert => false, :port => 443,
355
+ :host => 'myhost', :database => 'mydb', :layout => 'some_layout',
356
+ :account_name => 'name', :password => 'pass'
357
+ }
358
+
359
+ #### Possible Configuration Options
360
+
361
+ Following are all of the recognized configuration options, including defaults if applicable.
362
+
363
+ :host => 'localhost'
364
+ :port => 80
365
+ :ssl => true
366
+ :root_cert => true
367
+ :root_cert_name => ''
368
+ :root_cert_path => '/'
369
+ :account_name => ''
370
+ :password => ''
371
+ :log_actions => false
372
+ :log_responses => false
373
+ :log_parser => false
374
+ :warn_on_redirect => true
375
+ :raise_on_401 => false
376
+ :timeout => 60
377
+
378
+ :use # use configuration subgroups, or filter configuration subgoups
379
+ :layout # specify the name of the layout to use
380
+ :parent => 'Rfm::Config' # the parent configuration object of the current configuration object, as string
381
+ :file_name => 'rfm.yml # name of configuration file to load yaml from
382
+ :file_path => ['', 'config/'] # array of additional file paths to look for configuration file
383
+ :parser => ActiveSupport::XmlMini_REXML # XmlParser to use if no other is specified or can be found
384
+
275
385
 
276
- ### With models
386
+ ### Using Models
277
387
 
278
- Rfm models provide easy access to the record-finder functions of Rfm layouts, and they give us a way to easily persist objects to the database.
388
+ Rfm models provide easy access, modeling, and persistence of your Filemaker data.h
279
389
 
280
390
  class User < Rfm::Base
281
- config :layout => 'my_layout_name'
391
+ config :layout => 'my_user_layout'
392
+ attr_accessor :password
282
393
  end
283
394
 
284
395
  @user = User.new(:login => 'bill', :password => 'xxxxxxxx', :email => 'my@email.com')
396
+ @user.encrypt_password
285
397
  @user.save!
286
398
 
287
- @user.login
288
- # => 'bill'
399
+ @user.record_id
400
+ # => '12345'
289
401
 
290
402
  @user.field_names
291
403
  # => ['login', 'encryptedPassword', 'email', 'groups', 'lastLogin' ]
292
404
 
293
- User.field_names
294
- # => ['login', 'encryptedPassword', 'email', 'groups', 'lastLogin' ]
405
+ User.total_count
406
+ # => 35467
407
+
408
+ @user = User.find 12345
409
+ @user.update_attributes(:login => 'william', :email => 'myother@email.com')
410
+ @user.save!
411
+
412
+ Put your model code anywhere at the top level of your script/application. In Rails, this could be your initialization file(s), your environment file(s), or in a file in your Models directory called something like `rfm_models.rb`. Then require 'rfm_models' in your initialization or environment.
413
+
414
+ rfm_models.rb
415
+
416
+ require 'rfm'
417
+
418
+ class User < Rfm::Base
419
+ config :layout => 'user_layout'
420
+ end
421
+
422
+ class Order < Rfm::Base
423
+ config :layout => 'order_layout'
424
+ end
425
+
426
+ main_initializer.rb
427
+
428
+ require 'rfm_models'
429
+
430
+
431
+ If you prefer, you can create models on-the-fly from any layout.
432
+
433
+ my_rfm_layout_object.modelize
434
+
435
+ # => MyLayoutName (subclassed from Rfm::Base, represented by your layout's name)
436
+
437
+ Or create models for an entire database, all at once.
438
+
439
+ Rfm.modelize /_xml/i, 'my_database', :my_config_group
440
+
441
+ # => [MyLayoutXml, AnotherLayoutXml, ThirdLayoutXml, AndSoOnXml, ...]
442
+ # The regex in the first parameter is optional and filters the layout names in the specified database.
443
+ # Omit the regex parameter to modelize all possible layouts in the specified database.
444
+
445
+ With ActiveModel loaded, you get callbacks, validations, errors, serialization, and a handful of other features extracted from Rails ActiveRecord.
446
+
447
+ In your Gemfile
448
+
449
+ gem 'activemodel'
450
+
451
+ Or without Bundler
452
+
453
+ require 'active_model'
454
+
455
+ Then use ActiveModel features in your Rfm models
456
+
457
+ class MyModel < Rfm::Base
458
+ before_create :encrypt_password
459
+ after_validate "puts 'yay!'"
460
+ validates :email, :presence => true
461
+ end
462
+
463
+ @my_model = MyModel.new
464
+ @my_model.valid?
465
+ @my_model.save!
466
+ @my_model.errors
467
+
468
+ To learn more about ActiveModel, see the ActiveModel or RubyOnRails documentation:
469
+
470
+ * <http://rubydoc.info/gems/activemodel/frames>
471
+ * <http://api.rubyonrails.org/>
472
+ * <http://guides.rubyonrails.org/active_record_validations_callbacks.html>
473
+
474
+ Once you have an Rfm model or layout, you can use any of the standard Rfm commands to create, search, edit, and delete records. To learn more about these commands, see below for Databases, Layouts, Resultsets, and Records. Or checkout the API documentation for Rfm::Server, Rfm::Database, Rfm::Layout, Rfm::Record, and Rfm::Base.
475
+
476
+ #### Two Small Changes in Rfm Return Values
295
477
 
296
- ### Manually
478
+ When using Models to retrieve records using the `any` method or the `find(record_id)` method, the return values will be single Rfm::Record objects. This differs from the traditional Rfm behavior of these methods when accessed directly from the the Rfm::Layout instance, where the return value is always a Rfm::Resultset.
479
+
480
+ MyModel.find(record_id) == my_layout.find(record_id)[0]
481
+ MyModel.any == my_layout.any[0]
482
+
483
+
484
+ ### Getting Rfm Server, Database, and Layout Objects Manually
485
+
486
+ Well... not entirely manually. To get server, db, and layout objects as in previous versions of Rfm, see the section "Working with classic Rfm features". Ginjo-rfm 2.0 has some new methods to create/locate Filemaker objects and meta data. Many of these new methods are configuration-aware.
297
487
 
298
488
  Create a layout object using default configuration settings.
299
489
 
@@ -305,18 +495,76 @@ Create a layout object using a subgroup of configuration settings.
305
495
 
306
496
  Create a layout object passing in a layout name, multiple config subgroups to merge, and specific settings.
307
497
 
308
- my_layout = Rfm.layout 'layout_name', :second_server, :log_actions => true
498
+ my_layout = Rfm.layout 'layout_name', :other_server, :log_actions => true
499
+
500
+ The same can be done for servers and databases.
501
+
502
+ my_server = Rfm.server 'my.host.com'
503
+ my_database = Rfm.database :development, :ssl => false, :root_cert => false
504
+ my_database = Rfm.db :production
505
+ # db and database are interchangeable aliases in Ginjo-rfm 2.0
506
+
507
+ You can query your Filemaker objects for the familiar meta-data.
508
+
509
+ my_server.databases.all.names
510
+ my_server.databases['MyFmDb']
511
+ my_database.layouts
512
+ my_layout.value_lists
513
+ my_layout.field_names
514
+ my_layout.portal_meta
309
515
 
516
+ Here are two new fun Layout methods:
310
517
 
311
- Once you have an Rfm model or layout, you can use any of the standard Rfm commands to create, search, edit, and delete records. To learn more about these commands, see below for Databases, Layouts, Resultsets, and Records. Or checkout the documentation for Rfm::Layout, Rfm::Record, and Rfm::Base.
518
+ my_layout.total_count # => total records in table
519
+ my_layout.count(:some_field => 'search criteria', ...) # Returns foundset_count only, no records.
312
520
 
521
+ See the API documentation for the lowdown on new methods in Rfm Server, Database, and Layout objects.
522
+
523
+ ### Shortcuts, Tips & Tricks
524
+
525
+ All Rfm methods that take a configuration hash have two possible shortcuts.
526
+
527
+ If you pass a symbol before the hash, it is interpreted as subgroup specification or subgroup filter
528
+
529
+ config :mygroup, :layout => 'mylayout'
530
+ # :use => :mygroup, :layout => 'mylayout'
531
+
532
+ get_config :othergroup
533
+ # :use => [:mygroup, :othergroup], :layout => 'mylayout'
534
+
535
+ If you pass a string before any symbols or hashes, it is interepreted as one of several possible configuration settings - usually a layout name, a database name, or a server hostname. The interpretation is dependent on the method being called. Not all methods will make use of a string parameter.
536
+
537
+ class MyModel < Rfm::Base
538
+ config 'MyLayoutName'
539
+ # :layout => 'MyLayoutName'
540
+ end
541
+
542
+ Rfm.database 'MyDatabaseName'
543
+ # :database => 'MyDatabaseName'
544
+
545
+ Rfm.modelize 'MyDatabaseName', :group1
546
+ # :database => 'MyDatabaseName', :use => :group1
547
+
548
+ Just about anything you can do with a Rfm layout, you can also do with a Rfm model.
549
+
550
+ MyModel.total_count
551
+ MyModel.field_names
552
+ MyModel.database.name
553
+
554
+ There are a number of methods within Rfm that have been made accessible from the top-level Rfm module. Note that the server/database/layout methods are new to Rfm and are not the same as Rfm::Server, Rfm::Database, and Rfm::Layout. See the above section on "Getting Rfm Server, Database, and Layout Objects Manually" for an overview of how to use the new server/database/layout methods.
555
+
556
+ # Any of these methods can be assed via Rfm.<method_name>
557
+
558
+ Rfm::Factory :servers, :server, :db, :database, :layout, :models, :modelize
559
+ Rfm::XmlParser :backend, :backend=
560
+ Rfm::Config :config, :get_config, :config_clear
313
561
 
314
- # Working with "classic" Rfm features
562
+ ## Working with "Classic" Rfm Features
315
563
 
316
- All of Rfm's original features and functions are available as they were before, though some low-level functionality has changed slightly.
564
+ All of Rfm's original features and functions are available as they were before, though some low-level functionality has changed slightly. See the documentation for each module & class for the specifics on low-level methods and functionality.
317
565
 
318
566
 
319
- ## Connecting
567
+ ### Connecting
320
568
 
321
569
  IMPORTANT:SSL and Certificate verification are on by default. Please see Server#new in rdocs for explanation and setup.
322
570
  You connect with the Rfm::Server object. This little buddy will be your window into FileMaker data.
@@ -341,7 +589,7 @@ if your web publishing engine runs on a port other than 80, you can provide the
341
589
  :root_cert => false
342
590
  )
343
591
 
344
- ## Databases and Layouts
592
+ ### Databases and Layouts
345
593
 
346
594
  All access to data in FileMaker's XML interface is done through layouts, and layouts live in databases. The Rfm::Server object has a collection of databases called 'db'. So to get ahold of a database called "My Database", you can do this:
347
595
 
@@ -371,7 +619,7 @@ Bringing it all together, you can do this to go straight from a server to a spec
371
619
 
372
620
  my_layout = my_server["My Database"]["My Layout"]
373
621
 
374
- ## Working with Layouts
622
+ ### Working with Layouts
375
623
 
376
624
  Once you have a layout object, you can start doing some real work. To get every record from the layout:
377
625
 
@@ -414,7 +662,7 @@ For a complete list of the available options, see the "expand_options" method in
414
662
  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.
415
663
 
416
664
 
417
- ## ResultSet and Record Objects
665
+ ### ResultSet and Record Objects
418
666
 
419
667
  Any method on the Layout object that returns data will return a ResultSet object. Rfm::Result::ResultSet is a subclass of Array, so first and foremost, you can use it like any other array:
420
668
 
@@ -486,7 +734,7 @@ Again, you can string things together with Ruby. This will calculate the total d
486
734
  total = 0.0
487
735
  my_order.portals["Line Items"].each {|line| total += line.quantity * line.price}
488
736
 
489
- ## Data Types
737
+ ### Data Types
490
738
 
491
739
  FileMaker's field types are coerced to Ruby types thusly:
492
740
 
@@ -509,7 +757,7 @@ Finally, container fields will come back as URI objects. You can:
509
757
 
510
758
  Specifically, the URI refers to the _contents_ of the container field. When accessed, the file, picture, or movie in the field will be downloaded.
511
759
 
512
- ## Troubleshooting
760
+ ### Troubleshooting
513
761
 
514
762
  There are two cheesy methods to help track down problems. When you create a server object, you can provide two additional optional parameters:
515
763
 
@@ -541,6 +789,4 @@ Other lead contributors:
541
789
  * Jesse Antunes helped ensure that Rfm is stable and functional.
542
790
  * Larry Sprock added ssl support, switched the xml parser to a much faster Nokogiri, added the rspec testing framework, and refined code architecture.
543
791
 
544
- ## Copyright
545
792
 
546
- Copyright (c) 2007 Six Fried Rice, LLC and Mufaddal Khumr. See LICENSE for details.