ginjo-rfm 3.0.11 → 3.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/CHANGELOG.md +34 -23
- data/README.md +364 -364
- data/lib/rfm/VERSION +1 -1
- data/lib/rfm/metadata/field.rb +6 -1
- data/lib/rfm/utilities/config.rb +1 -0
- data/lib/rfm/utilities/sax/fmpxml_minimal.yml +27 -27
- metadata +32 -33
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
OGRkNjViNjkxNjQ5NWMzNWI3OGI3MzE4ZjQ2Zjk4MTYwZDU2N2ZmYw==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9764299badd35b9f4b648765216cc32493d00a0b
|
4
|
+
data.tar.gz: ba30aa950a0e9ff80832e605efbcb70da4575286
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
OWQzNmRiMDM5MjMzY2RhZjI2MTVkZWNiMTlkNjIyZWMzNTVjZmY5Y2QxODMx
|
11
|
-
NWRhZjI0OTQyYzhhODI5MzMzNmY3MjIyODI4NmU1NzM2ZjI3ODI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MGEyMzYxYmM2MjYyN2MyMjdmNzMxZmQzZDEzMDNiNjRhNzhiNTM0NjE0ZDMz
|
14
|
-
YjMyNDFkMTBhMTVmNWVhM2U4ZmIzMWZmZDZhODFjYjA3ZjVhMTYzMWJiNjlm
|
15
|
-
NTFhN2M3NjAwZjI4NGJmMjc4ZGZhNmUzNDQyOTViNjZiZmZkYTA=
|
6
|
+
metadata.gz: fceed96b77df4acb9d368ae7f406cce69f3236009fc8ccbe58d6fe9ce1b52b6a4534935827604dcb45a0fe9e1e77952e5162d363f4178127a0167f7150dfdd2d
|
7
|
+
data.tar.gz: 1d0dcc307977a810fa9f11e381ebe0981c74c9916f25697e437bf85dceaee6a5e3ffee8f54d5c7de9484d497bbae28e5d2aef63cf8318066116fe7a839331c80
|
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## Ginjo-Rfm 3.0.12
|
4
|
+
|
5
|
+
* Make decimal separator configurable, as FM-Server uses local number settings in result set.
|
6
|
+
Use configuration option `:decimal_separator`.
|
7
|
+
|
8
|
+
* Fix broken spec for Ox sax parser.
|
9
|
+
|
10
|
+
* Change dependency constraint for rspec to >= v2.
|
11
|
+
|
12
|
+
|
3
13
|
## Ginjo-Rfm 3.0.11
|
4
14
|
|
5
15
|
* Scoping fixes, changes, additions:
|
6
16
|
|
7
17
|
Now takes proc or array of hashes or hash.
|
8
|
-
|
18
|
+
|
9
19
|
Scope_args for scope proc now defaults to model instance.
|
10
20
|
|
11
21
|
Now handles omits - puts them at end of request array.
|
@@ -13,7 +23,7 @@
|
|
13
23
|
* Support for rom-fmp 0.0.4 - query chaining with compound fm queries.
|
14
24
|
|
15
25
|
* Basic support for portal field writes.
|
16
|
-
|
26
|
+
|
17
27
|
record['my_relationship::my_field.0'] = 'Adds a new portal record with data for my_field, if auto-create enabled'
|
18
28
|
record.update_attributes! 'my_relationship::my_field.3' => 'Updates my_field in 3rd portal record, if exists'
|
19
29
|
|
@@ -21,6 +31,7 @@
|
|
21
31
|
|
22
32
|
* Fix CompoundQuery to handle nil values in query params.
|
23
33
|
|
34
|
+
|
24
35
|
## Ginjo-Rfm 3.0.10
|
25
36
|
|
26
37
|
* Fixed bug where missing metadata would cause errors when creating/editing records.
|
@@ -29,7 +40,7 @@
|
|
29
40
|
|
30
41
|
scope = {:person_id => current_user.person_id}
|
31
42
|
Order.find([{:status => ['open', 'processing']}, {:omit => true, :item_count => "<1"}], :scope => scope)
|
32
|
-
|
43
|
+
|
33
44
|
class Orders < Rfm::Base
|
34
45
|
SCOPE = Proc.new { {:expired => "=" } }
|
35
46
|
end
|
@@ -56,20 +67,20 @@
|
|
56
67
|
|
57
68
|
* Implemented proxy option for database connections thru a proxy server.
|
58
69
|
|
59
|
-
|
60
|
-
|
70
|
+
config :proxy=>['my.proxy.com', 8888]
|
71
|
+
|
61
72
|
* Implemented erb parsing of config.yml
|
62
|
-
|
73
|
+
|
63
74
|
* Disabled ```:grammar => :auto``` option. The current xml parser cannot yet use the FMPXMLRESULT grammar for general queries.
|
64
75
|
|
65
76
|
|
66
77
|
## Ginjo-Rfm 3.0.7
|
67
78
|
|
68
79
|
* 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.
|
69
|
-
|
80
|
+
|
70
81
|
my_layout.find(12345).class == Rfm::Record
|
71
82
|
MyModel.find(12345).class == MyModel
|
72
|
-
|
83
|
+
|
73
84
|
|
74
85
|
## Ginjo-Rfm 3.0.6
|
75
86
|
|
@@ -181,9 +192,9 @@
|
|
181
192
|
|
182
193
|
* Added grammar translation layer between xml parser and Rfm, allowing all supported xml grammars to be used with Rfm.
|
183
194
|
This will also streamline changes/additions to Filemaker's xml grammar(s).
|
184
|
-
|
195
|
+
|
185
196
|
* Fixed case statement for ruby 1.9
|
186
|
-
|
197
|
+
|
187
198
|
* Configuration ```:use``` option now works for all Rfm objects that respond to ```config```.
|
188
199
|
|
189
200
|
## Ginjo-Rfm 2.0.2
|
@@ -233,11 +244,11 @@
|
|
233
244
|
## Ginjo-Rfm 1.4.2
|
234
245
|
|
235
246
|
* Re-implemented:
|
236
|
-
|
247
|
+
|
237
248
|
Layout#field\_controls
|
238
249
|
|
239
250
|
Layout#value\_lists
|
240
|
-
|
251
|
+
|
241
252
|
* Enhanced:
|
242
253
|
|
243
254
|
ValueListItem handles both display & data items now.
|
@@ -245,7 +256,7 @@
|
|
245
256
|
Timeout feature from timting (github/timting/rfm).
|
246
257
|
|
247
258
|
Added specs for Record#save.
|
248
|
-
|
259
|
+
|
249
260
|
* Fixed:
|
250
261
|
|
251
262
|
[Bug] Getting & setting fields with symbol-based keys was producing error.
|
@@ -259,23 +270,23 @@
|
|
259
270
|
server.db.all
|
260
271
|
db.layout.all
|
261
272
|
db.script.all
|
262
|
-
|
273
|
+
|
263
274
|
Note: the "#all" method returns object names (as keys) only. The receiver of the method maintains the full object collection.
|
264
275
|
|
265
276
|
Example:
|
266
|
-
|
267
|
-
|
268
|
-
|
277
|
+
|
278
|
+
server.db.all #=> ['dbname1', 'dbname2', ...]
|
279
|
+
server.db #=> a DbFactory object (descendant of Hash), containing 0 or more Database objects
|
269
280
|
|
270
281
|
## Lardawge-Rfm 1.4.2 (unreleased)
|
271
|
-
|
282
|
+
|
272
283
|
* Made nil default on fields with no value.
|
273
|
-
|
284
|
+
|
274
285
|
Example:
|
275
286
|
|
276
287
|
Old: record.john #=> ""
|
277
288
|
New: record.john #=> nil
|
278
|
-
|
289
|
+
|
279
290
|
## Lardawge-Rfm 1.4.1.2
|
280
291
|
|
281
292
|
* [Bug] Pointing out why testing is soooooo important when refactoring... Found a bug in getter/setter method in Rfm::Record (yes, added spec for it).
|
@@ -295,13 +306,13 @@
|
|
295
306
|
* Added an option to load portal records which defaults to false. This significantly speeds up load time when portals are present on the layout.
|
296
307
|
|
297
308
|
Example:
|
298
|
-
|
309
|
+
|
299
310
|
result = fm_server('layout').find({:username => "==#{username}"}, {:include_portals => true})
|
300
311
|
# => This will fetch all records with portal records attached.
|
301
|
-
|
312
|
+
|
302
313
|
result.first.portals
|
303
314
|
# => would return an empty hash by default.
|
304
|
-
|
315
|
+
|
305
316
|
* 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.
|
306
317
|
|
307
318
|
* Removed Layout#value\_lists && Layout#field\_controls. Will put back in if the demand is high. Needs a major refactor and different placement if it goes back in. Was broken so it didn't seem to be used by many devs.
|
data/README.md
CHANGED
@@ -1,26 +1,24 @@
|
|
1
1
|
<!--
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
2
|
+
See YARD documentation - https://github.com/lsegal/yard/wiki/GettingStarted
|
3
|
+
|
4
|
+
Yard is not the same as markdown - Yard is for ruby and can use any markup language,
|
5
|
+
whereas Markdown is just another markup language.
|
6
|
+
|
7
|
+
Rubydoc.info uses yard and can use markdown and other markup languages.
|
8
|
+
To update ginjo-rfm's yard documentation from github's master branch,
|
9
|
+
first find 'rfm' on rubydoc.info, then in list-view click the update button
|
10
|
+
on the right of the screen.
|
11
|
+
To preview this file in yard, run 'rake yard'
|
12
|
+
|
13
|
+
Github uses markdown or rdoc (maybe others?).
|
14
|
+
To preview this file in plain markdown, edit in TextMate and
|
15
|
+
choose Bundles/Markdown/Preview menu option.
|
16
16
|
-->
|
17
17
|
|
18
18
|
# ginjo-rfm
|
19
19
|
|
20
20
|
Rfm is a Ruby-Filemaker adapter, a gem that provides an interface between Filemaker Server and Ruby. Query your Filemaker database, browse result records as persistent objects, and create/update/delete records with a syntax similar to ActiveRecord. Ginjo-rfm picks up from the lardawge-rfm gem and continues to refine code and fix bugs. Version 3 removes the dependency on ActiveSupport and is now a completely independent Gem, able to run most of its core features without requiring any other supporting Gems. ActiveModel features can be activated by adding activemodel to your Gemfile (or requiring activemodel manually).
|
21
21
|
|
22
|
-
Ginjo-rfm version 3 has been tested successfully on Ruby 1.8.7 thru 2.1.3.
|
23
|
-
|
24
22
|
|
25
23
|
## Documentation & Links
|
26
24
|
|
@@ -72,22 +70,22 @@ The first step in getting connected to your Filemaker databases with Rfm (assumi
|
|
72
70
|
|
73
71
|
config/rfm.yml
|
74
72
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
73
|
+
:host: my.host.com
|
74
|
+
:account_name: myname
|
75
|
+
:password: somepass
|
76
|
+
:database: MyFmDb
|
77
|
+
|
80
78
|
app/models/order\_item.rb
|
81
79
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
80
|
+
class OrderItem < Rfm::Base
|
81
|
+
config :layout => 'order_item_layout'
|
82
|
+
end
|
83
|
+
|
86
84
|
app/controllers/order\_item\_controller.rb
|
87
85
|
|
88
|
-
|
89
|
-
|
90
|
-
|
86
|
+
def show
|
87
|
+
@record = OrderItem.find params[:id]
|
88
|
+
end
|
91
89
|
|
92
90
|
|
93
91
|
### Configuration
|
@@ -96,42 +94,42 @@ In previous versions of Rfm, you may have stored your configuration settings in
|
|
96
94
|
|
97
95
|
rfm.yml
|
98
96
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
97
|
+
:ssl: true
|
98
|
+
:timeout: 10
|
99
|
+
:port: 443
|
100
|
+
:host: my.host.com
|
101
|
+
:account_name: myname
|
102
|
+
:password: somepass
|
103
|
+
:database: MyFmDb
|
106
104
|
|
107
105
|
Or put your configuration settings in a hash called RFM_CONFIG. Rfm will pick those up just as with the yaml file.
|
108
106
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
107
|
+
RFM_CONFIG = {
|
108
|
+
:host => 'my.host.com',
|
109
|
+
:database => 'MyFmDb',
|
110
|
+
:account_name => 'myname',
|
111
|
+
:password => 'somepass',
|
112
|
+
:ssl => true,
|
113
|
+
:port => 443,
|
114
|
+
:timeout => 10
|
115
|
+
}
|
118
116
|
|
119
117
|
You can use configuration subgroups to separate global settings from environment-specific settings.
|
120
118
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
119
|
+
:ssl: true
|
120
|
+
:root_cert: false
|
121
|
+
:timeout: 10
|
122
|
+
:port: 443
|
123
|
+
:development:
|
124
|
+
:host: dev.mydomain.com
|
125
|
+
:account_name: admin
|
126
|
+
:password: pass
|
127
|
+
:database: DevFmDb
|
128
|
+
:production:
|
129
|
+
:host: live.mydomain.com
|
130
|
+
:account_name: admin
|
131
|
+
:password: pass
|
132
|
+
:database: LiveFmDb
|
135
133
|
|
136
134
|
Then in your environment files (or wherever you put environment-specific configuration in your Ruby project),
|
137
135
|
specifiy which subgroup to use.
|
@@ -140,27 +138,27 @@ specifiy which subgroup to use.
|
|
140
138
|
|
141
139
|
You can use configuration subgroups to contain any arbitrary groups of settings.
|
142
140
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
141
|
+
:ssl: true
|
142
|
+
:root_cert: false
|
143
|
+
:timeout: 10
|
144
|
+
:port: 443
|
145
|
+
:customer1:
|
146
|
+
:host: customer1.com
|
147
|
+
:account_name: cust1
|
148
|
+
:password: pass
|
149
|
+
:database: custOneFmDb
|
150
|
+
:customer2:
|
151
|
+
:host: customer2.com
|
152
|
+
:account_name: cust2
|
153
|
+
:password: pass
|
154
|
+
:database: custTwoFmDb
|
157
155
|
|
158
156
|
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 (on top of any existing upstream configuration).
|
159
157
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
158
|
+
class MyModel < Rfm::Base
|
159
|
+
config :use => :customer1, :layout => 'some_layout'
|
160
|
+
end
|
161
|
+
|
164
162
|
The current hierarchy of configurable objects in Rfm, starting at the top, is:
|
165
163
|
|
166
164
|
* rfm.yml # file of settings in yaml format
|
@@ -172,132 +170,134 @@ The current hierarchy of configurable objects in Rfm, starting at the top, is:
|
|
172
170
|
|
173
171
|
You can also include or extend the Rfm::Config module in any object in your project to gain Rfm configuration abilities for that object.
|
174
172
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
173
|
+
module MyModule
|
174
|
+
include Rfm::Config
|
175
|
+
config :host => 'myhost.com', :database => 'mydb', :account_name => 'name', :password => 'pass'
|
176
|
+
# inherits settings from Rfm::Config by default
|
177
|
+
end
|
180
178
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
179
|
+
class Person < Rfm::Base
|
180
|
+
config :parent => MyModule, :layout => 'some_layout'
|
181
|
+
# using :parent to set where this object inherits config settings from
|
182
|
+
end
|
185
183
|
|
186
184
|
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
185
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
186
|
+
Person.get_config
|
187
|
+
|
188
|
+
# => {:ssl => true, :timeout => 10, :root_cert => false, :port => 443,
|
189
|
+
:host => 'myhost', :database => 'mydb', :layout => 'some_layout',
|
190
|
+
:account_name => 'name', :password => 'pass'
|
191
|
+
}
|
192
|
+
|
195
193
|
#### Configuration Options
|
196
194
|
|
197
195
|
Following are all of the recognized configuration options, including defaults if applicable.
|
198
196
|
See `Rfm::Config::CONFIG_KEYS` for a list of currently allowed configuration options.
|
199
197
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
198
|
+
:host => 'localhost'
|
199
|
+
:port
|
200
|
+
:ssl => true
|
201
|
+
:root_cert => true
|
202
|
+
:root_cert_name => ''
|
203
|
+
:root_cert_path => '/'
|
204
|
+
:account_name => ''
|
205
|
+
:password => ''
|
206
|
+
:proxy => false # Pass an array of Net::HTTP::Proxy options (p_addr, p_port = nil, p_user = nil, p_pass = nil).
|
207
|
+
:log_actions => false
|
208
|
+
:log_responses => false
|
209
|
+
:log_parser => false
|
210
|
+
:warn_on_redirect => true
|
211
|
+
:raise_on_401 => false
|
212
|
+
:timeout => 60
|
213
|
+
|
214
|
+
:use # Use configuration subgroups, or filter configuration subgoups.
|
215
|
+
:layout # Specify the name of the layout to use.
|
216
|
+
:parent => 'Rfm::Config' # The parent configuration object of the current configuration object, as string.
|
217
|
+
:file_name => 'rfm.yml # Name of configuration file to load yaml from.
|
218
|
+
:file_path => ['', 'config/'] # Array of additional file paths to look for configuration file.
|
219
|
+
:parser # Prefferred XML parser. Can be :libxml, :nokogiri, :ox, :rexml.
|
220
|
+
# You must also require the parsing gem or specify it in your gemfile,
|
221
|
+
# if not using the built-in Ruby XML parser REXML.
|
222
|
+
# You only need to use this option if you have multiple
|
223
|
+
# parsing gems loaded and want to use a specfic one.
|
224
|
+
# Otherwise, Rfm will use the best parser it can find amongst your currently loaded parsing gems.
|
225
|
+
:ignore_bad_data => nil # Instruct Rfm to ignore data mismatch errors when loading a resultset.
|
226
|
+
:decimal_separator => '.' # FileMaker uses local number format of the server. It stores input as text.
|
227
|
+
# So on european servers a number value of '1.200,50' is considered valid and interpreted as 1200.5
|
228
|
+
# To support this, :decimal_separator can be configured and any other characters than digits and the separator are ignored
|
229
229
|
|
230
230
|
### Using Models
|
231
231
|
|
232
232
|
Rfm models provide easy access, modeling, and persistence of your Filemaker data. A ginjo-rfm model is basically an alias to a specific layout in your Filemaker database and provides all of the query options found in a classic rfm layout object. The model and/or the layout object is where you do most of your work with rfm. For more details about what methods and options are available to a model or layout object, see the documentation for the {Rfm::Layout} and {Rfm::Base} classes.
|
233
233
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
234
|
+
class User < Rfm::Base
|
235
|
+
config :layout => 'my_user_layout'
|
236
|
+
attr_accessor :password
|
237
|
+
end
|
238
|
+
|
239
|
+
@user = User.new(:login => 'bill', :password => 'xxxxxxxx', :email => 'my@email.com')
|
240
|
+
@user.encrypt_password
|
241
|
+
@user.save!
|
242
|
+
|
243
|
+
@user.record_id
|
244
|
+
# => '12345'
|
245
|
+
|
246
|
+
@user.field_names
|
247
|
+
# => ['login', 'encryptedPassword', 'email', 'groups', 'lastLogin' ]
|
248
|
+
|
249
|
+
User.total_count
|
250
|
+
# => 35467
|
251
|
+
|
252
|
+
@user = User.find 12345
|
253
|
+
@user.update_attributes(:login => 'william', :email => 'myother@email.com')
|
254
|
+
@user.save!
|
255
|
+
|
256
256
|
If using Rails, put your model code in files within your models/ directory.
|
257
257
|
|
258
258
|
app/models/user.rb
|
259
259
|
|
260
|
-
|
261
|
-
|
262
|
-
|
260
|
+
class User < Rfm::Base
|
261
|
+
config :layout => 'user_layout'
|
262
|
+
end
|
263
263
|
|
264
264
|
If you prefer, you can create models on-the-fly from any layout.
|
265
265
|
|
266
|
-
|
267
|
-
|
268
|
-
|
266
|
+
my_rfm_layout_object.modelize
|
267
|
+
|
268
|
+
# => MyLayoutName (subclassed from Rfm::Base, represented by your layout's name)
|
269
269
|
|
270
270
|
Or create models for an entire database, all at once.
|
271
271
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
272
|
+
Rfm.modelize /_xml/i, 'my_database', :my_config_group
|
273
|
+
|
274
|
+
# => [MyLayoutXml, AnotherLayoutXml, ThirdLayoutXml, AndSoOnXml, ...]
|
275
|
+
# The regex in the first parameter is optional and filters the layout names in the specified database.
|
276
|
+
# Omit the regex parameter to modelize all possible layouts in the specified database (careful with this one!).
|
277
277
|
|
278
278
|
With ActiveModel loaded, you get callbacks, validations, errors, serialization, and a handful of other features extracted from Rails ActiveRecord. Not all ActiveModel features are supported (yet) in ginjo-rfm, but adapters can be hand-rolled in the meantime.
|
279
279
|
|
280
280
|
In your Gemfile
|
281
281
|
|
282
|
-
|
283
|
-
|
282
|
+
gem 'activemodel'
|
283
|
+
|
284
284
|
Or without Bundler
|
285
285
|
|
286
|
-
|
287
|
-
|
286
|
+
require 'active_model'
|
287
|
+
|
288
288
|
Then use ActiveModel features in your Rfm models
|
289
289
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
290
|
+
class MyModel < Rfm::Base
|
291
|
+
before_create :encrypt_password
|
292
|
+
after_validate "puts 'yay!'"
|
293
|
+
validates :email, :presence => true
|
294
|
+
end
|
295
|
+
|
296
|
+
@my_model = MyModel.new
|
297
|
+
@my_model.valid?
|
298
|
+
@my_model.save!
|
299
|
+
@my_model.errors
|
300
|
+
|
301
301
|
To learn more about ActiveModel, see the ActiveModel or RubyOnRails documentation:
|
302
302
|
|
303
303
|
* <http://rubydoc.info/gems/activemodel/frames>
|
@@ -310,8 +310,8 @@ Once you have an Rfm model or layout, you can use any of the standard Rfm comman
|
|
310
310
|
|
311
311
|
(From Rfm v2 onward) 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 original Rfm behavior of these methods when accessed directly from the the Rfm::Layout instance, where the return value is always a Rfm::Resultset.
|
312
312
|
|
313
|
-
|
314
|
-
|
313
|
+
MyModel.find(record_id) == my_layout.find(record_id)[0]
|
314
|
+
MyModel.any == my_layout.any[0]
|
315
315
|
|
316
316
|
|
317
317
|
### Getting Rfm Server, Database, and Layout Objects Manually
|
@@ -320,36 +320,36 @@ Well... not entirely manually. To get server, db, and layout objects as in previ
|
|
320
320
|
|
321
321
|
Create a layout object using default configuration settings.
|
322
322
|
|
323
|
-
|
324
|
-
|
323
|
+
my_layout = Rfm.layout 'layout_name'
|
324
|
+
|
325
325
|
Create a layout object using a subgroup of configuration settings.
|
326
326
|
|
327
|
-
|
328
|
-
|
327
|
+
my_layout = Rfm.layout :subgroup_name
|
328
|
+
|
329
329
|
Create a layout object passing in a layout name, multiple config subgroups to merge, and specific settings.
|
330
330
|
|
331
|
-
|
332
|
-
|
331
|
+
my_layout = Rfm.layout 'layout_name', :other_server, :log_actions => true
|
332
|
+
|
333
333
|
The same can be done for servers and databases.
|
334
334
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
335
|
+
my_server = Rfm.server 'my.host.com'
|
336
|
+
my_database = Rfm.database :development, :ssl => false, :root_cert => false
|
337
|
+
my_database = Rfm.db :production
|
338
|
+
# db and database are interchangeable aliases in Ginjo-rfm 2.0
|
339
|
+
|
340
340
|
You can query your Filemaker objects for the familiar meta-data.
|
341
341
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
342
|
+
my_server.databases.all.names
|
343
|
+
my_server.databases['MyFmDb']
|
344
|
+
my_database.layouts
|
345
|
+
my_layout.value_lists
|
346
|
+
my_layout.field_names
|
347
|
+
my_layout.portal_meta
|
348
348
|
|
349
349
|
Here are two new fun Layout methods:
|
350
350
|
|
351
|
-
|
352
|
-
|
351
|
+
my_layout.total_count # => total records in table
|
352
|
+
my_layout.count(:some_field => 'search criteria', ...) # Returns foundset_count only, no records.
|
353
353
|
|
354
354
|
See the API documentation for the lowdown on new methods in Rfm Server, Database, and Layout objects.
|
355
355
|
|
@@ -359,60 +359,60 @@ All Rfm methods that take a configuration hash have two possible shortcuts.
|
|
359
359
|
|
360
360
|
(1) If you pass a symbol before the hash, it is interpreted as subgroup specification or subgroup filter
|
361
361
|
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
362
|
+
config :mygroup, :layout => 'mylayout'
|
363
|
+
# This will add the following configuration options to the object you called 'config' on.
|
364
|
+
# :use => :mygroup, :layout => 'mylayout'
|
365
|
+
|
366
|
+
get_config :othergroup
|
367
|
+
# This will return global configuration options merged with configuration options from :othergroup.
|
368
|
+
# :use => [:mygroup, :othergroup], :layout => 'mylayout'
|
369
369
|
|
370
370
|
(2) If you pass a string before any symbols or hashes, it is interpreted 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.
|
371
371
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
372
|
+
class MyModel < Rfm::Base
|
373
|
+
config 'MyLayoutName'
|
374
|
+
# In this context, this is the same as
|
375
|
+
# config :layout => 'MyLayoutName'
|
376
|
+
end
|
377
|
+
|
378
|
+
Rfm.database 'MyDatabaseName'
|
379
|
+
# In this context, this is the same as
|
380
|
+
# Rfm.database :database => 'MyDatabaseName'
|
381
|
+
|
382
|
+
Rfm.modelize 'MyDatabaseName', :group1
|
383
|
+
# In this context, this is the same as
|
384
|
+
# Rfm.modelize :database => 'MyDatabaseName', :use => :group1
|
385
385
|
|
386
386
|
Just about anything you can do with a Rfm layout, you can also do with a Rfm model.
|
387
387
|
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
388
|
+
MyModel.total_count
|
389
|
+
MyModel.field_names
|
390
|
+
MyModel.database.name
|
391
|
+
|
392
392
|
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.
|
393
393
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
394
|
+
# Any of these methods can be accessed via Rfm.<method_name>
|
395
|
+
|
396
|
+
Rfm::Factory :servers, :server, :db, :database, :layout, :models, :modelize
|
397
|
+
Rfm::Config :config, :get_config, :config_clear
|
398
|
+
Rfm::Resultset :ignore_bad_data
|
399
|
+
Rfm::SaxParser :backend
|
400
|
+
|
401
401
|
If you are working with a Filemaker database that returns codes like '?' for a missing value in a date field, Rfm will throw an error. Set your main configuration, your server, or your layout to `ignore_bad_data true`, if you want Rfm to silently ignore data mismatch errors when loading resultset data. If ActiveRecord is loaded, and your resultset is loaded into a Rfm model, your model records will log these errors in the @errors attribute.
|
402
402
|
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
403
|
+
Rfm.config :ignore_bad_data => true
|
404
|
+
|
405
|
+
class MyModel < Rfm::Base
|
406
|
+
config 'my_layout'
|
407
|
+
end
|
408
|
+
|
409
|
+
result = MyModel.find(:name => 'mike')
|
410
|
+
# Assuming the Filemaker field 'some_date_field' contains a bad date value '?'
|
411
|
+
result[0].errors.full_messages
|
412
|
+
# ['some_date_field invalid date']
|
413
|
+
|
414
|
+
# To be more specific about what objects you want to ignore data errors
|
415
|
+
MyModel.layout.ignore_bad_data true
|
416
416
|
|
417
417
|
## Working with "Classic" Rfm Features
|
418
418
|
|
@@ -424,93 +424,93 @@ All of Rfm's original features and functions are available as they were before,
|
|
424
424
|
IMPORTANT:SSL and Certificate verification are on by default. Please see Server#new in rdocs for explanation and setup.
|
425
425
|
You connect with the Rfm::Server object. This little buddy will be your window into FileMaker data.
|
426
426
|
|
427
|
-
|
427
|
+
require 'rfm'
|
428
428
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
429
|
+
my_server = Rfm::Server.new(
|
430
|
+
:host => 'myservername',
|
431
|
+
:account_name => 'user',
|
432
|
+
:password => 'pw',
|
433
|
+
:ssl => false
|
434
|
+
)
|
435
435
|
|
436
436
|
if your web publishing engine runs on a port other than 80, you can provide the port number as well:
|
437
437
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
438
|
+
my_server = Rfm::Server.new(
|
439
|
+
:host => 'myservername',
|
440
|
+
:account_name => 'user',
|
441
|
+
:password => 'pw',
|
442
|
+
:port => 8080,
|
443
|
+
:ssl => false,
|
444
|
+
:root_cert => false
|
445
|
+
)
|
446
446
|
|
447
447
|
### Databases and Layouts
|
448
448
|
|
449
449
|
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:
|
450
450
|
|
451
|
-
|
451
|
+
my_db = my_server.db["My Database"]
|
452
452
|
|
453
453
|
As a convenience, you can do this too:
|
454
454
|
|
455
|
-
|
455
|
+
my_db = my_server["My Database"]
|
456
456
|
|
457
457
|
Finally, if you want to introspect the server and find out what databases are available, you can do this:
|
458
458
|
|
459
|
-
|
459
|
+
all_dbs = my_server.db.all
|
460
460
|
|
461
461
|
In any case, you get back Rfm::Database objects. A database object in turn has a property called "layout":
|
462
462
|
|
463
|
-
|
463
|
+
my_layout = my_db.layout["My Layout"]
|
464
464
|
|
465
465
|
Again, for convenience:
|
466
466
|
|
467
|
-
|
467
|
+
my_layout = my_db["My Layout"]
|
468
468
|
|
469
469
|
And to get them all:
|
470
470
|
|
471
|
-
|
471
|
+
all_layouts = my_db.layout.all
|
472
472
|
|
473
473
|
Bringing it all together, you can do this to go straight from a server to a specific layout:
|
474
474
|
|
475
|
-
|
475
|
+
my_layout = my_server["My Database"]["My Layout"]
|
476
476
|
|
477
477
|
### Working with Layouts
|
478
478
|
|
479
479
|
Once you have a layout object, you can start doing some real work. To get every record from the layout:
|
480
480
|
|
481
|
-
|
481
|
+
my_layout.all # be careful with this
|
482
482
|
|
483
483
|
To get a random record:
|
484
484
|
|
485
|
-
|
485
|
+
my_layout.any
|
486
486
|
|
487
487
|
To find every record with "Arizona" in the "State" field:
|
488
488
|
|
489
|
-
|
489
|
+
my_layout.find({"State" => "Arizona"})
|
490
490
|
|
491
491
|
To add a new record with my personal info:
|
492
492
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
493
|
+
my_layout.create({
|
494
|
+
:first_name => "Geoff",
|
495
|
+
:last_name => "Coffey",
|
496
|
+
:email => "gwcoffey@gmail.com"}
|
497
|
+
)
|
498
498
|
|
499
499
|
Notice that in this case I used symbols instead of strings for the hash keys. The API will accept either form, so if your field names don't have whitespace or punctuation, you might prefer the symbol notation.
|
500
500
|
|
501
501
|
To edit the record whose recid (filemaker internal record id) is 200:
|
502
502
|
|
503
|
-
|
503
|
+
my_layout.edit(200, {:first_name => 'Mamie'})
|
504
504
|
|
505
505
|
Note: See the "Record Objects" section below for more on editing records.
|
506
506
|
|
507
507
|
To delete the record whose recid is 200:
|
508
508
|
|
509
|
-
|
509
|
+
my_layout.delete(200)
|
510
510
|
|
511
511
|
All of these methods return an Rfm::Resultset object (see below), and every one of them takes an optional parameter (the very last one) with additional options. For example, to find just a page full of records, you can do this:
|
512
512
|
|
513
|
-
|
513
|
+
my_layout.find({:state => "AZ"}, {:max_records => 10, :skip_records => 100})
|
514
514
|
|
515
515
|
For a complete list of the available options, see the "Common Options" section in the layout.rb file.
|
516
516
|
|
@@ -521,24 +521,24 @@ Finally, if filemaker returns an error when executing any of these methods, an e
|
|
521
521
|
|
522
522
|
Any method on the Layout object that returns data will return a Resultset object. Rfm::Resultset is a subclass of Array, so first and foremost, you can use it like any other array:
|
523
523
|
|
524
|
-
|
525
|
-
|
526
|
-
|
524
|
+
my_result = my_layout.any
|
525
|
+
my_result.size # returns '1'
|
526
|
+
my_result[0] # returns the first record (an Rfm::Record object)
|
527
527
|
|
528
528
|
The Resultset object also tells you information about the fields and portals in the result. Resultset#field\_meta and Resultset#portal\_meta are both standard Ruby hashes, with strings for keys. The fields hash has Rfm::Metadata::Field objects for values. The portals hash has another hash for its values. This nested hash is the fields on the portal. This would print out all the field names:
|
529
529
|
|
530
|
-
|
531
|
-
|
530
|
+
my_result.field_meta.each { |name, field| puts name }
|
531
|
+
|
532
532
|
Or, as a convenience, you can do this:
|
533
533
|
|
534
534
|
my_result.field_names
|
535
535
|
|
536
536
|
This would print out the tables each portal on the layout is associated with. Below each table name, and indented, it will print the names of all the fields on each portal.
|
537
537
|
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
538
|
+
my_result.portals.each { |table, fields|
|
539
|
+
puts "table: #{table}"
|
540
|
+
fields.each { |name, field| puts "\t#{name}"}
|
541
|
+
}
|
542
542
|
|
543
543
|
Also as a convenience, you can do this:
|
544
544
|
|
@@ -546,67 +546,67 @@ Also as a convenience, you can do this:
|
|
546
546
|
|
547
547
|
But most importantly, the Resultset contains record objects. Rfm::Record is a subclass of Hash, so it can be used in many standard ways. This code would print the value in the 'first_name' field in the first record of the Resultset:
|
548
548
|
|
549
|
-
|
550
|
-
|
549
|
+
my_record = my_result[0]
|
550
|
+
puts my_record["first_name"]
|
551
551
|
|
552
552
|
As a convenience, if your field names are valid Ruby method names (ie, they don't have spaces or odd punctuation in them), you can do this instead:
|
553
553
|
|
554
|
-
|
554
|
+
puts my_record.first_name
|
555
555
|
|
556
556
|
Since Resultsets are arrays and Records are hashes, you can take advantage of Ruby's wonderful expressiveness. For example, to get a comma-separated list of the full names of all the people in California, you could do this:
|
557
557
|
|
558
|
-
|
558
|
+
my_layout.find(:state => 'CA').collect {|rec| "#{rec.first_name} #{rec.last_name}"}.join(", ")
|
559
559
|
|
560
560
|
Record objects can also be edited:
|
561
561
|
|
562
|
-
|
562
|
+
my_record.first_name = 'Isabel'
|
563
563
|
|
564
564
|
Once you have made a series of edits, you can save them back to the database like this:
|
565
565
|
|
566
|
-
|
566
|
+
my_record.save
|
567
567
|
|
568
568
|
The save operation causes the record to be reloaded from the database, so any changes that have been made outside your script will also be picked up after the save.
|
569
569
|
|
570
570
|
If you want to detect concurrent modification, you can do this instead:
|
571
571
|
|
572
|
-
|
572
|
+
my_record.save_if_not_modified
|
573
573
|
|
574
574
|
This version will refuse to update the database and raise an error if the record was modified after it was loaded but before it was saved.
|
575
575
|
|
576
576
|
Record objects also have portals. While the portals in a Resultset tell you about the tables and fields the portals show, the portals in a Record have the actual data. For example, if an Order record has Line Item records, you could do this:
|
577
577
|
|
578
|
-
|
579
|
-
|
578
|
+
my_order = order_layout.any[0] # the [0] is important!
|
579
|
+
my_lines = my_order.portals["Line Items"]
|
580
580
|
|
581
581
|
At the end of the previous block of code, my_lines is an array of Record objects. In this case, they are the records in the "Line Items" portal for the particular order record. You can then operate on them as you would any other record.
|
582
582
|
|
583
583
|
NOTE: Fields on a portal have the table name and the "::" stripped off of their names if they belong to the table the portal is tied to. In other words, if our "Line Items" portal includes a quantity field and a price field, you would do this:
|
584
584
|
|
585
|
-
|
586
|
-
|
585
|
+
my_lines[0]["Quantity"]
|
586
|
+
my_lines[0]["Price"]
|
587
587
|
|
588
588
|
You would NOT do this:
|
589
589
|
|
590
|
-
|
591
|
-
|
590
|
+
my_lines[0]["Line Items::Quantity"]
|
591
|
+
my_lines[0]["Line Items::Quantity"]
|
592
592
|
|
593
593
|
My feeling is that the table name is redundant and cumbersome if it is the same as the portal's table. This is also up for debate.
|
594
594
|
|
595
595
|
Again, you can string things together with Ruby. This will calculate the total dollar amount of the order:
|
596
596
|
|
597
|
-
|
598
|
-
|
597
|
+
total = 0.0
|
598
|
+
my_order.portals["Line Items"].each {|line| total += line.quantity * line.price}
|
599
599
|
|
600
600
|
### Data Types
|
601
601
|
|
602
602
|
FileMaker's field types are coerced to Ruby types thusly:
|
603
603
|
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
604
|
+
Text Field -> String object
|
605
|
+
Number Field -> BigDecimal object # see below
|
606
|
+
Date Field -> Date object
|
607
|
+
Time Field -> DateTime object # see below
|
608
|
+
TimeStamp Field -> DateTime object
|
609
|
+
Container Field -> URI object
|
610
610
|
|
611
611
|
FileMaker's number field is insanely robust. The only data type in Ruby that can handle the same magnitude and precision of a FileMaker number is Ruby's BigDecimal. (This is an extension class, so you have to require 'bigdecimal' to use it yourself). Unfortuantely, BigDecimal is not a "normal" Ruby numeric class, so it might be really annoying that your tiny filemaker numbers have to go this route. This is a great topic for debate.
|
612
612
|
|
@@ -614,9 +614,9 @@ Also, Ruby doesn't have a Time type that stores just a normal time (with no date
|
|
614
614
|
|
615
615
|
Finally, container fields will come back as URI objects. You can:
|
616
616
|
|
617
|
-
|
618
|
-
|
619
|
-
|
617
|
+
- use Net::HTTP to download the contents of the container field using this URI
|
618
|
+
- to_s the URI and use it as the src attribute of an HTML image tag
|
619
|
+
- etc...
|
620
620
|
|
621
621
|
Specifically, the URI refers to the _contents_ of the container field. When accessed, the file, picture, or movie in the field will be downloaded.
|
622
622
|
|
@@ -632,13 +632,13 @@ When this is 'true' your script will dump the actual response it got from FileMa
|
|
632
632
|
|
633
633
|
So, for an annoying, but detailed load of output, make a connection like this:
|
634
634
|
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
635
|
+
my_server => Rfm::Server.new(
|
636
|
+
:host => 'myservername',
|
637
|
+
:account_name => 'user',
|
638
|
+
:password => 'pw',
|
639
|
+
:log_actions => true,
|
640
|
+
:log_responses => true
|
641
|
+
)
|
642
642
|
|
643
643
|
### Source Code
|
644
644
|
|
@@ -678,8 +678,8 @@ See the changelog or the commit history for more details on changes in ginjo-rfm
|
|
678
678
|
### Version 2.1
|
679
679
|
|
680
680
|
* Portals are now included by default.
|
681
|
-
|
682
|
-
|
681
|
+
Removed `:include_portals` query option in favor of `:ignore_portals`.
|
682
|
+
Added `:max_portal_rows` query option.
|
683
683
|
* Added field-remapping framework to allow model fields with different names than Filemaker fields.
|
684
684
|
|
685
685
|
class User < Rfm::Base
|
@@ -716,21 +716,21 @@ See the changelog or the commit history for more details on changes in ginjo-rfm
|
|
716
716
|
|
717
717
|
|
718
718
|
#### Data Modeling with ActiveModel
|
719
|
-
|
719
|
+
|
720
720
|
If you can load ActiveModel in your project, you can have model callbacks, validations, and other ActiveModel features.
|
721
721
|
If you can't load ActiveModel (because you're using something incompatible, like Rails 2),
|
722
722
|
you can still use Rfm models... minus the ActiveModel-specific features like callbacks and validations. Rfm models give you basic
|
723
723
|
data modeling with easy configuration and CRUD features.
|
724
724
|
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
725
|
+
class User < Rfm::Base
|
726
|
+
config :layout=>'user_layout'
|
727
|
+
before_save :encrypt_password
|
728
|
+
validate :valid_email_address
|
729
|
+
end
|
730
|
+
|
731
|
+
@user = User.new :username => 'bill', :password => 'pass'
|
732
|
+
@user.email = 'my@email.com'
|
733
|
+
@user.save!
|
734
734
|
|
735
735
|
|
736
736
|
#### Choice of XML Parsers
|
@@ -741,31 +741,31 @@ Ginjo-rfm 2.0 uses ActiveSupport's XmlMini parsing interface, which has built-in
|
|
741
741
|
LibXML, Nokogiri, and REXML. Additionally, ginjo-rfm includes adapters for Ox and Hpricot parsing.
|
742
742
|
You can specifiy which parser to use or let Rfm decide.
|
743
743
|
|
744
|
-
|
744
|
+
Rfm.config :parser => :libxml
|
745
745
|
|
746
746
|
If you're not able to install one of the faster parsers, ginjo-rfm will fall back to
|
747
747
|
Ruby's built-in REXML. Want to roll your own XML adapter? Just pass it to Rfm as a module.
|
748
748
|
|
749
|
-
|
749
|
+
Rfm.config :parser => MyHomeGrownAdapter
|
750
750
|
|
751
751
|
Choose your preferred parser globaly, as in the above example, or set a different parser for each model.
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
752
|
+
|
753
|
+
class Order < Rfm::Base
|
754
|
+
config :parser => :hpricot
|
755
|
+
end
|
756
|
+
|
757
757
|
The current parsing options are
|
758
758
|
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
759
|
+
:jdom -> JDOM (for JRuby)
|
760
|
+
:oxsax -> Ox SAX
|
761
|
+
:libxml -> LibXML Tree
|
762
|
+
:libxmlsax -> LibXML SAX
|
763
|
+
:nokogirisax -> Nokogiri SAX
|
764
|
+
:nokogiri -> Nokogiri Tree
|
765
|
+
:hpricot -> Hpricot Tree
|
766
|
+
:rexml -> REXML Tree
|
767
|
+
:rexmlsax -> REXML SAX
|
768
|
+
|
769
769
|
|
770
770
|
#### Configuration API
|
771
771
|
|
@@ -773,39 +773,39 @@ The ginjo-rfm configuration module lets you store your settings in several diffe
|
|
773
773
|
|
774
774
|
rfm.yml
|
775
775
|
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
776
|
+
:ssl: true
|
777
|
+
:root_cert: false
|
778
|
+
:timeout: 10
|
779
|
+
:port: 443
|
780
|
+
:host: live.mydomain.com
|
781
|
+
:account_name: admin
|
782
|
+
:password: pass
|
783
|
+
:database: MyFmDb
|
784
784
|
|
785
785
|
Set a model's configuration.
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
786
|
+
|
787
|
+
class MyModel < Rfm::Base
|
788
|
+
config :layout => 'mylayout'
|
789
|
+
end
|
790
790
|
|
791
791
|
|
792
792
|
#### Compound Filemaker Queries, with Omitable FMP Find Requests
|
793
793
|
|
794
794
|
Create a Filemaker 'omit' request by including an :omit key with a value of true.
|
795
795
|
|
796
|
-
|
796
|
+
my_layout.find :field1 => 'val1', :field2 => 'val2', :omit => true
|
797
797
|
|
798
798
|
Create multiple Filemaker find requests by passing an array of hashes to the #find method.
|
799
799
|
|
800
|
-
|
800
|
+
my_layout.find [{:field1 => 'bill', :field2 => 'admin'}, {:field2 => 'staff', :field3 => 'inactive', :omit => true}, ...]
|
801
801
|
|
802
802
|
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.
|
803
803
|
|
804
|
-
|
804
|
+
my_layout.find :fieldOne => ['bill','mike','bob'], :fieldTwo =>'staff'
|
805
805
|
|
806
806
|
|
807
807
|
#### Full Metadata Support
|
808
|
-
|
808
|
+
|
809
809
|
* Server databases
|
810
810
|
* Database layouts
|
811
811
|
* Database scripts
|
@@ -819,38 +819,38 @@ There are also many enhancements to make it easier to get the objects or data yo
|
|
819
819
|
|
820
820
|
Get a database object using default config
|
821
821
|
|
822
|
-
|
822
|
+
Rfm.db 'my_db'
|
823
823
|
|
824
824
|
Get a layout object using config grouping :my_group
|
825
|
-
|
826
|
-
|
825
|
+
|
826
|
+
Rfm.layout :my_group
|
827
827
|
|
828
828
|
Get the total count of all records in the table
|
829
829
|
|
830
|
-
|
830
|
+
MyModel.total_count
|
831
831
|
|
832
832
|
Get the portal names (table-occurrence names) on the current layout
|
833
833
|
|
834
|
-
|
834
|
+
MyModel.portal_names
|
835
835
|
|
836
836
|
Get the names of fields on the current layout
|
837
837
|
|
838
|
-
|
839
|
-
|
840
|
-
|
838
|
+
my_record.field_names
|
839
|
+
|
840
|
+
|
841
841
|
### From Version 1.4.x
|
842
842
|
|
843
843
|
From ginjo-rfm 1.4.x, the following features are also included.
|
844
844
|
|
845
845
|
Connection timeout settings
|
846
846
|
|
847
|
-
|
847
|
+
Rfm.config :timeout => 10
|
848
848
|
|
849
849
|
Value-list alternate display
|
850
850
|
|
851
|
-
|
852
|
-
|
853
|
-
|
851
|
+
i = array_of_value_list_items[3] # => '8765'
|
852
|
+
i.value # => '8765'
|
853
|
+
i.display # => '8765 Amy'
|
854
854
|
|
855
855
|
|
856
856
|
|