ginjo-rfm 1.4.2 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +40 -40
- data/lib/rfm.rb +17 -7
- data/lib/rfm/VERSION +1 -0
- data/lib/rfm/version.rb +10 -10
- metadata +5 -4
data/README.md
CHANGED
@@ -38,12 +38,12 @@ Rfm depends on Nokogiri gem, which installs executables requiring C compilation.
|
|
38
38
|
|
39
39
|
Terminal:
|
40
40
|
|
41
|
-
bash
|
41
|
+
#bash
|
42
42
|
gem install ginjo-rfm
|
43
43
|
|
44
44
|
Once the gem is installed, you can use rfm in your ruby scripts by requiring it:
|
45
45
|
|
46
|
-
ruby
|
46
|
+
#ruby
|
47
47
|
require 'rubygems'
|
48
48
|
require 'rfm'
|
49
49
|
|
@@ -51,13 +51,14 @@ Once the gem is installed, you can use rfm in your ruby scripts by requiring it:
|
|
51
51
|
|
52
52
|
In the Gemfile:
|
53
53
|
|
54
|
-
ruby
|
54
|
+
#ruby
|
55
55
|
gem 'ginjo-rfm'
|
56
56
|
|
57
|
-
### Edge
|
58
|
-
|
59
|
-
#### ActiveModel support.
|
57
|
+
### Edge - in an upcoming version of ginjo-rfm
|
60
58
|
|
59
|
+
ActiveModel support.
|
60
|
+
|
61
|
+
#ruby
|
61
62
|
class Account < Rfm::Base
|
62
63
|
config :layout=>'account_xml'
|
63
64
|
before_create :encrypt_password
|
@@ -65,20 +66,19 @@ In the Gemfile:
|
|
65
66
|
validates :username, :presence => true
|
66
67
|
attr_accessor :password
|
67
68
|
end
|
68
|
-
|
69
|
+
|
69
70
|
@account = Account.new(:username=>'bill', :password=>'pass')
|
70
71
|
@account.email = 'my@email.com'
|
71
72
|
@account.save!
|
72
73
|
|
73
|
-
|
74
|
+
Multiple backend xml parsers. Uses ActiveSupport::XmlMini to support Nokogiri, Libxml-ruby, or Rexml.
|
74
75
|
|
75
76
|
Rfm::Server.new(:backend => :nokogiri)
|
76
|
-
|
77
|
-
Rfm::Server.new(:backend => :rexml)
|
77
|
+
# Backend options => :libxml, :libxmlsax, :nokogiri, :nokogirisax, :rexml
|
78
78
|
|
79
79
|
Try it out:
|
80
80
|
|
81
|
-
gemfile
|
81
|
+
#gemfile
|
82
82
|
gem 'ginjo-rfm', :git=>'git://github.com/ginjo/rfm.git', :branch=>'edge'
|
83
83
|
|
84
84
|
## Connecting
|
@@ -86,7 +86,7 @@ Try it out:
|
|
86
86
|
IMPORTANT:SSL and Certificate verification are on by default. Please see Server#new in rdocs for explanation and setup.
|
87
87
|
You connect with the Rfm::Server object. This little buddy will be your window into FileMaker data.
|
88
88
|
|
89
|
-
ruby
|
89
|
+
#ruby
|
90
90
|
require 'rfm'
|
91
91
|
|
92
92
|
my_server = Rfm::Server.new(
|
@@ -98,7 +98,7 @@ You connect with the Rfm::Server object. This little buddy will be your window i
|
|
98
98
|
|
99
99
|
if your web publishing engine runs on a port other than 80, you can provide the port number as well:
|
100
100
|
|
101
|
-
ruby
|
101
|
+
#ruby
|
102
102
|
my_server = Rfm::Server.new(
|
103
103
|
:host => 'myservername',
|
104
104
|
:account_name => 'user',
|
@@ -112,44 +112,44 @@ if your web publishing engine runs on a port other than 80, you can provide the
|
|
112
112
|
|
113
113
|
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:
|
114
114
|
|
115
|
-
ruby
|
115
|
+
#ruby
|
116
116
|
my_db = my_server.db["My Database"]
|
117
117
|
|
118
118
|
As a convenience, you can do this too:
|
119
119
|
|
120
|
-
ruby
|
120
|
+
#ruby
|
121
121
|
my_db = my_server["My Database"]
|
122
122
|
|
123
123
|
Finally, if you want to introspect the server and find out what databases are available, you can do this:
|
124
124
|
|
125
|
-
ruby
|
125
|
+
#ruby
|
126
126
|
all_dbs = my_server.db.all
|
127
127
|
|
128
128
|
In any case, you get back Rfm::Database objects. A database object in turn has a property called "layout":
|
129
129
|
|
130
|
-
ruby
|
130
|
+
#ruby
|
131
131
|
my_layout = my_db.layout["My Layout"]
|
132
132
|
|
133
133
|
Again, for convenience:
|
134
134
|
|
135
|
-
ruby
|
135
|
+
#ruby
|
136
136
|
my_layout = my_db["My Layout"]
|
137
137
|
|
138
138
|
And to get them all:
|
139
139
|
|
140
|
-
ruby
|
140
|
+
#ruby
|
141
141
|
all_layouts = my_db.layout.all
|
142
142
|
|
143
143
|
Bringing it all together, you can do this to go straight from a server to a specific layout:
|
144
144
|
|
145
|
-
ruby
|
145
|
+
#ruby
|
146
146
|
my_layout = my_server["My Database"]["My Layout"]
|
147
147
|
|
148
148
|
## Working with Layouts
|
149
149
|
|
150
150
|
Once you have a layout object, you can start doing some real work. To get every record from the layout:
|
151
151
|
|
152
|
-
ruby
|
152
|
+
#ruby
|
153
153
|
my_layout.all # be careful with this
|
154
154
|
|
155
155
|
To get a random record:
|
@@ -159,12 +159,12 @@ To get a random record:
|
|
159
159
|
|
160
160
|
To find every record with "Arizona" in the "State" field:
|
161
161
|
|
162
|
-
ruby
|
162
|
+
#ruby
|
163
163
|
my_layout.find({"State" => "Arizona"})
|
164
164
|
|
165
165
|
To add a new record with my personal info:
|
166
166
|
|
167
|
-
ruby
|
167
|
+
#ruby
|
168
168
|
my_layout.create({
|
169
169
|
:first_name => "Geoff",
|
170
170
|
:last_name => "Coffey",
|
@@ -175,19 +175,19 @@ Notice that in this case I used symbols instead of strings for the hash keys. Th
|
|
175
175
|
|
176
176
|
To edit the record whos recid (filemaker internal record id) is 200:
|
177
177
|
|
178
|
-
ruby
|
178
|
+
#ruby
|
179
179
|
my_layout.edit(200, {:first_name => 'Mamie'})
|
180
180
|
|
181
181
|
Note: See the "Record Objects" section below for more on editing records.
|
182
182
|
|
183
183
|
To delete the record whose recid is 200:
|
184
184
|
|
185
|
-
ruby
|
185
|
+
#ruby
|
186
186
|
my_layout.delete(200)
|
187
187
|
|
188
188
|
All of these methods return an Rfm::Result::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:
|
189
189
|
|
190
|
-
ruby
|
190
|
+
#ruby
|
191
191
|
my_layout.find({:state => "AZ"}, {:max_records => 10, :skip_records => 100})
|
192
192
|
|
193
193
|
For a complete list of the available options, see the "expand_options" method in the Rfm::Server object in the file named rfm_command.rb.
|
@@ -199,19 +199,19 @@ Finally, if filemaker returns an error when executing any of these methods, an e
|
|
199
199
|
|
200
200
|
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:
|
201
201
|
|
202
|
-
ruby
|
202
|
+
#ruby
|
203
203
|
my_result = my_layout.any
|
204
204
|
my_result.size # returns '1'
|
205
205
|
my_result[0] # returns the first record (an Rfm::Result::Record object)
|
206
206
|
|
207
207
|
The ResultSet object also tells you information about the fields and portals in the result. ResultSet#fields and ResultSet#portals are both standard ruby hashes, with strings for keys. The fields hash has Rfm::Result::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:
|
208
208
|
|
209
|
-
ruby
|
209
|
+
#ruby
|
210
210
|
my_result.fields.each { |name, field| puts name }
|
211
211
|
|
212
212
|
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.
|
213
213
|
|
214
|
-
ruby
|
214
|
+
#ruby
|
215
215
|
my_result.portals.each { |table, fields|
|
216
216
|
puts "table: #{table}"
|
217
217
|
fields.each { |name, field| puts "\t#{name}"}
|
@@ -219,42 +219,42 @@ This would print out the tables each portal on the layout is associated with. Be
|
|
219
219
|
|
220
220
|
But most importantly, the ResultSet contains record objects. Rfm::Result::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:
|
221
221
|
|
222
|
-
ruby
|
222
|
+
#ruby
|
223
223
|
my_record = my_result[0]
|
224
224
|
puts my_record["first_name"]
|
225
225
|
|
226
226
|
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:
|
227
227
|
|
228
|
-
ruby
|
228
|
+
#ruby
|
229
229
|
puts my_record.first_name
|
230
230
|
|
231
231
|
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:
|
232
232
|
|
233
|
-
ruby
|
233
|
+
#ruby
|
234
234
|
my_layout.find(:state => 'CA').collect {|rec| "#{rec.first_name} #{rec.last_name}"}.join(", ")
|
235
235
|
|
236
236
|
Record objects can also be edited:
|
237
237
|
|
238
|
-
ruby
|
238
|
+
#ruby
|
239
239
|
my_record.first_name = 'Isabel'
|
240
240
|
|
241
241
|
Once you have made a series of edits, you can save them back to the database like this:
|
242
242
|
|
243
|
-
ruby
|
243
|
+
#ruby
|
244
244
|
my_record.save
|
245
245
|
|
246
246
|
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.
|
247
247
|
|
248
248
|
If you want to detect concurrent modification, you can do this instead:
|
249
249
|
|
250
|
-
ruby
|
250
|
+
#ruby
|
251
251
|
my_record.save_if_not_modified
|
252
252
|
|
253
253
|
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.
|
254
254
|
|
255
255
|
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:
|
256
256
|
|
257
|
-
ruby
|
257
|
+
#ruby
|
258
258
|
my_order = order_layout.any[0] # the [0] is important!
|
259
259
|
my_lines = my_order.portals["Line Items"]
|
260
260
|
|
@@ -262,13 +262,13 @@ At the end of the previous block of code, my_lines is an array of Record objects
|
|
262
262
|
|
263
263
|
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:
|
264
264
|
|
265
|
-
ruby
|
265
|
+
#ruby
|
266
266
|
my_lines[0]["Quantity"]
|
267
267
|
my_lines[0]["Price"]
|
268
268
|
|
269
269
|
You would NOT do this:
|
270
270
|
|
271
|
-
ruby
|
271
|
+
#ruby
|
272
272
|
my_lines[0]["Line Items::Quantity"]
|
273
273
|
my_lines[0]["Line Items::Quantity"]
|
274
274
|
|
@@ -276,7 +276,7 @@ My feeling is that the table name is redundant and cumbersome if it is the same
|
|
276
276
|
|
277
277
|
Again, you can string things together with Ruby. This will calculate the total dollar amount of the order:
|
278
278
|
|
279
|
-
ruby
|
279
|
+
#ruby
|
280
280
|
total = 0.0
|
281
281
|
my_order.portals["Line Items"].each {|line| total += line.quantity * line.price}
|
282
282
|
|
@@ -315,7 +315,7 @@ When this is 'true' your script will dump the actual response it got from FileMa
|
|
315
315
|
|
316
316
|
So, for an annoying, but detailed load of output, make a connection like this:
|
317
317
|
|
318
|
-
ruby
|
318
|
+
#ruby
|
319
319
|
my_server => Rfm::Server.new(
|
320
320
|
:host => 'myservername',
|
321
321
|
:account_name => 'user',
|
data/lib/rfm.rb
CHANGED
@@ -1,14 +1,23 @@
|
|
1
|
-
path = File.expand_path(File.dirname(__FILE__))
|
2
|
-
$:.unshift(path) unless $:.include?(path)
|
1
|
+
# path = File.expand_path(File.dirname(__FILE__))
|
2
|
+
# $:.unshift(path) unless $:.include?(path)
|
3
|
+
#
|
4
|
+
# require path + '/rfm/utilities/case_insensitive_hash'
|
5
|
+
# require path + '/rfm/utilities/factory'
|
6
|
+
# require path + '/rfm/version.rb'
|
7
|
+
|
8
|
+
Rfm = Module.new unless defined? Rfm
|
9
|
+
Rfm::PATH = File.expand_path(File.dirname(__FILE__))
|
10
|
+
$LOAD_PATH.unshift(Rfm::PATH) unless $LOAD_PATH.include?(Rfm::PATH)
|
11
|
+
|
12
|
+
require 'rfm/utilities/case_insensitive_hash'
|
13
|
+
require 'rfm/utilities/factory'
|
14
|
+
require 'rfm/version.rb'
|
3
15
|
|
4
|
-
require path + '/rfm/utilities/case_insensitive_hash'
|
5
|
-
require path + '/rfm/utilities/factory'
|
6
|
-
require path + '/rfm/version.rb'
|
7
16
|
|
8
17
|
module Rfm
|
9
18
|
|
10
19
|
if $0.to_s.match(/irb|rails|bundle/) # was ENV['_']
|
11
|
-
puts "Using gem ginjo-rfm version: #{VERSION}"
|
20
|
+
puts "Using gem ginjo-rfm version: #{::Rfm::VERSION}"
|
12
21
|
end
|
13
22
|
|
14
23
|
class CommunicationError < StandardError; end
|
@@ -29,4 +38,5 @@ module Rfm
|
|
29
38
|
autoload :ValueListItem, 'rfm/metadata/value_list_item'
|
30
39
|
end
|
31
40
|
|
32
|
-
end
|
41
|
+
end
|
42
|
+
|
data/lib/rfm/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.4.3
|
data/lib/rfm/version.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
module Rfm
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
2
|
+
|
3
|
+
VERSION_DEFAULT = 'none'
|
4
|
+
VERSION = File.read(PATH + '/rfm/VERSION').first.gsub(/\n|\r/,'') rescue VERSION_DEFAULT #File.read(File.join(File.expand_path(File.dirname(File.dirname(File.dirname(__FILE__)))), 'VERSION')) rescue VERSION_DEFAULT
|
5
|
+
|
6
|
+
VERSION.instance_eval do
|
7
|
+
def components; VERSION.split('.'); end
|
8
|
+
def major; components[0]; end
|
9
|
+
def minor; components[1]; end
|
10
|
+
def patch; components[2]; end
|
11
|
+
def build; components[3]; end
|
12
12
|
end
|
13
13
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ginjo-rfm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 1.4.
|
9
|
+
- 3
|
10
|
+
version: 1.4.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Geoff Coffey
|
@@ -19,7 +19,7 @@ autorequire:
|
|
19
19
|
bindir: bin
|
20
20
|
cert_chain: []
|
21
21
|
|
22
|
-
date: 2011-11-
|
22
|
+
date: 2011-11-22 00:00:00 Z
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
25
25
|
name: nokogiri
|
@@ -46,6 +46,7 @@ extra_rdoc_files:
|
|
46
46
|
- README.md
|
47
47
|
files:
|
48
48
|
- lib/rfm.rb
|
49
|
+
- lib/rfm/VERSION
|
49
50
|
- lib/rfm/database.rb
|
50
51
|
- lib/rfm/error.rb
|
51
52
|
- lib/rfm/layout.rb
|