lardawge-rfm 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +233 -0
- data/lib/rfm.rb +232 -0
- data/lib/rfm_command.rb +713 -0
- data/lib/rfm_error.rb +252 -0
- data/lib/rfm_factory.rb +82 -0
- data/lib/rfm_result.rb +430 -0
- data/lib/rfm_utility.rb +10 -0
- data/test/rfm_test_errors.rb +52 -0
- data/test/rfm_tester.rb +2 -0
- metadata +72 -0
data/README.rdoc
ADDED
@@ -0,0 +1,233 @@
|
|
1
|
+
= Rfm
|
2
|
+
|
3
|
+
== Installation
|
4
|
+
|
5
|
+
Run the following if you haven't already:
|
6
|
+
|
7
|
+
gem sources -a http://gems.github.com
|
8
|
+
|
9
|
+
Followed by:
|
10
|
+
|
11
|
+
gem install lardawge-rfm
|
12
|
+
|
13
|
+
Once the gem is installed, you can use rfm in your ruby scripts by requiring it:
|
14
|
+
|
15
|
+
require 'rubygems'
|
16
|
+
require 'rfm'
|
17
|
+
|
18
|
+
== Connecting
|
19
|
+
|
20
|
+
You connect with the Rfm::Server object. This little buddy will be your window into FileMaker data.
|
21
|
+
|
22
|
+
require 'rfm/rfm'
|
23
|
+
|
24
|
+
my_server = Rfm::Server.new(
|
25
|
+
:host => 'myservername',
|
26
|
+
:username => 'user',
|
27
|
+
:password => 'pw'
|
28
|
+
)
|
29
|
+
|
30
|
+
if your web publishing engine runs on a port other than 80, you can provide the port number as well:
|
31
|
+
|
32
|
+
my_server = Rfm::Server.new(
|
33
|
+
:host => 'myservername',
|
34
|
+
:username => 'user',
|
35
|
+
:password => 'pw',
|
36
|
+
:port => 8080
|
37
|
+
)
|
38
|
+
|
39
|
+
== Databases and Layouts
|
40
|
+
|
41
|
+
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:
|
42
|
+
|
43
|
+
my_db = my_server.db["My Database"]
|
44
|
+
|
45
|
+
As a convenience, you can do this too:
|
46
|
+
|
47
|
+
my_db = my_server["My Database"]
|
48
|
+
|
49
|
+
Finally, if you want to introspect the server and find out what databases are available, you can do this:
|
50
|
+
|
51
|
+
all_dbs = my_server.db.all
|
52
|
+
|
53
|
+
In any case, you get back Rfm::Database objects. A database object in turn has a property called "layout":
|
54
|
+
|
55
|
+
my_layout = my_db.layout["My Layout"]
|
56
|
+
|
57
|
+
Again, for convenience:
|
58
|
+
|
59
|
+
my_layout = my_db["My Layout"]
|
60
|
+
|
61
|
+
And to get them all:
|
62
|
+
|
63
|
+
all_layouts = my_db.layout.all
|
64
|
+
|
65
|
+
Bringing it all together, you can do this to go straight from a server to a specific layout:
|
66
|
+
|
67
|
+
my_layout = my_server["My Database"]["My Layout"]
|
68
|
+
|
69
|
+
NOTE: for the ruby experts, Rfm::Server#db is an Rfm::Factory::DatabaseFactory object, which is just a fancied up Hash. So anything you can do with a hash, you can also do with my_server.db. The same goes for my_db.layouts, which is an Rfm::Factory::LayoutFactory.
|
70
|
+
|
71
|
+
|
72
|
+
== Working with Layouts
|
73
|
+
|
74
|
+
Once you have a layout object, you can start doing some real work. To get every record from the layout:
|
75
|
+
|
76
|
+
my_layout.all # be careful with this
|
77
|
+
|
78
|
+
To get a random record:
|
79
|
+
|
80
|
+
my_layout.any
|
81
|
+
|
82
|
+
To find every record with "Arizona" in the "State" field:
|
83
|
+
|
84
|
+
my_layout.find({"State" => "Arizona"})
|
85
|
+
|
86
|
+
To add a new record with my personal info:
|
87
|
+
|
88
|
+
my_layout.create({
|
89
|
+
:first_name => "Geoff",
|
90
|
+
:last_name => "Coffey",
|
91
|
+
:email => "gwcoffey@gmail.com"}
|
92
|
+
)
|
93
|
+
|
94
|
+
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.
|
95
|
+
|
96
|
+
To edit the record whos recid (filemaker internal record id) is 200:
|
97
|
+
|
98
|
+
my_layout.edit(200, {:first_name => 'Mamie'})
|
99
|
+
|
100
|
+
Note: See the "Record Objects" section below for more on editing records.
|
101
|
+
|
102
|
+
To delete the record whose recid is 200:
|
103
|
+
|
104
|
+
my_layout.delete(200)
|
105
|
+
|
106
|
+
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:
|
107
|
+
|
108
|
+
my_layout.find({:state => "AZ"}, {:max_records => 10, :skip_records => 100})
|
109
|
+
|
110
|
+
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.
|
111
|
+
|
112
|
+
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.
|
113
|
+
|
114
|
+
|
115
|
+
== ResultSet and Record Objects
|
116
|
+
|
117
|
+
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:
|
118
|
+
|
119
|
+
my_result = my_layout.any
|
120
|
+
my_result.size # returns '1'
|
121
|
+
my_result[0] # returns the first record (an Rfm::Result::Record object)
|
122
|
+
|
123
|
+
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:
|
124
|
+
|
125
|
+
my_result.fields.each { |name, field| puts name }
|
126
|
+
|
127
|
+
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.
|
128
|
+
|
129
|
+
my_result.portals.each { |table, fields|
|
130
|
+
puts "table: #{table}"
|
131
|
+
fields.each { |name, field| puts "\t#{name}"}
|
132
|
+
}
|
133
|
+
|
134
|
+
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:
|
135
|
+
|
136
|
+
my_record = my_result[0]
|
137
|
+
puts my_record["first_name"]
|
138
|
+
|
139
|
+
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:
|
140
|
+
|
141
|
+
puts my_record.first_name
|
142
|
+
|
143
|
+
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:
|
144
|
+
|
145
|
+
my_layout.find({:state => 'CA'}).collect {|rec| "#{rec.first_name} #{rec.last_name}"}.join(", ")
|
146
|
+
|
147
|
+
Record objects can also be edited:
|
148
|
+
|
149
|
+
my_record.first_name = 'Isabel'
|
150
|
+
|
151
|
+
Once you have made a series of edits, you can save them back to the database like this:
|
152
|
+
|
153
|
+
my_record.save
|
154
|
+
|
155
|
+
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.
|
156
|
+
|
157
|
+
If you want to detect concurrent modification, you can do this instead:
|
158
|
+
|
159
|
+
my_record.save_if_not_modified
|
160
|
+
|
161
|
+
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.
|
162
|
+
|
163
|
+
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:
|
164
|
+
|
165
|
+
my_order = order_layout.any[0] # the [0] is important!
|
166
|
+
my_lines = my_order.portals["Line Items"]
|
167
|
+
|
168
|
+
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.
|
169
|
+
|
170
|
+
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:
|
171
|
+
|
172
|
+
my_lines[0]["Quantity"]
|
173
|
+
my_lines[0]["Price"]
|
174
|
+
|
175
|
+
You would NOT do this:
|
176
|
+
|
177
|
+
my_lines[0]["Line Items::Quantity"]
|
178
|
+
my_lines[0]["Line Items::Quantity"]
|
179
|
+
|
180
|
+
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.
|
181
|
+
|
182
|
+
Again, you can string things together with Ruby. This will calculate the total dollar amount of the order:
|
183
|
+
|
184
|
+
total = 0.0
|
185
|
+
my_order.portals["Line Items"].each {|line| total += line.quantity * line.price}
|
186
|
+
|
187
|
+
I intend to add a 'delete' method to the Record class as well, but I haven't done this yet. Finally, should you be able to create new records using the Record class? I'm not sure...lots of points to consider on this.
|
188
|
+
|
189
|
+
|
190
|
+
== Data Types
|
191
|
+
|
192
|
+
FileMaker's field types are coerced to Ruby types thusly:
|
193
|
+
|
194
|
+
Text Field -> String object
|
195
|
+
Number Field -> BigDecimal object # see below
|
196
|
+
Date Field -> Date object
|
197
|
+
Time Field -> DateTime object # see below
|
198
|
+
TimeStamp Field -> DateTime object
|
199
|
+
Container Field -> URI object
|
200
|
+
|
201
|
+
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.
|
202
|
+
|
203
|
+
Also, Ruby doesn't have a Time type that stores just a normal time (with no date attached). The Time class in ruby is a lot like DateTime, or a Timestamp in FileMaker. When I get a Time field from FileMaker, I turn it into a DateTime object, and set its date to the oldest date Ruby supports. You can still compare these in all the normal ways, so this should be fine, but it will look weird if you, ie, to_s one and see an odd date attached to your time.
|
204
|
+
|
205
|
+
Finally, container fields will come back as URI objects. You can:
|
206
|
+
|
207
|
+
- use Net::HTTP to download the contents of the container field using this URI
|
208
|
+
- to_s the URI and use it as the src attribute of an HTML image tag
|
209
|
+
- etc...
|
210
|
+
|
211
|
+
Specifically, the URI refers to the _contents_ of the container field. When accessed, the file, picture, or movie in the field will be downloaded.
|
212
|
+
|
213
|
+
== Troubleshooting
|
214
|
+
|
215
|
+
There are two cheesy methods to help track down problems. When you create a server object, you can provide two additional optional parameters:
|
216
|
+
|
217
|
+
:log_actions
|
218
|
+
When this is 'true' your script will write every URL it sends to the web publishing engine to standard out. For the rails users, this means the action url will wind up in your WEBrick or Mongrel log. If you can't make sense of what you're getting, you might try copying the URL into your browser to see what is actually coming back from FileMaker.
|
219
|
+
|
220
|
+
:log_responses
|
221
|
+
When this is 'true' your script will dump the actual response it got from FileMaker to standard out (again, in rails, check your logs).
|
222
|
+
|
223
|
+
So, for an annoying, but detailed load of output, make a connection like this:
|
224
|
+
|
225
|
+
my_server = Rfm::Server.new(
|
226
|
+
:host => 'myservername',
|
227
|
+
:username => 'user',
|
228
|
+
:password => 'pw',
|
229
|
+
:log_actions => true,
|
230
|
+
:log_responses => true
|
231
|
+
)
|
232
|
+
|
233
|
+
These options will change in the future. They're only there now as a quick-easy way for me to track down problems. I'm open to suggestions for what kind of login options will make sense in the final release.
|
data/lib/rfm.rb
ADDED
@@ -0,0 +1,232 @@
|
|
1
|
+
# RFM provides easy access to FileMaker Pro data. With it, Ruby scripts can
|
2
|
+
# perform finds, read records and fields, update data, and perform scripts using
|
3
|
+
# a simple ruby-like syntax.
|
4
|
+
#
|
5
|
+
# Author:: Geoff Coffey (mailto:gwcoffey@gmail.com)
|
6
|
+
# Copyright:: Copyright (c) 2007 Six Fried Rice, LLC and Mufaddal Khumri
|
7
|
+
# License:: See MIT-LICENSE for details
|
8
|
+
#
|
9
|
+
# RFM uses the FileMaker XML API, so it requires:
|
10
|
+
# - FileMaker Server 9.0 or later
|
11
|
+
# - or FileMaker Server Advanced 7.0 or later
|
12
|
+
#
|
13
|
+
# This documentation serves as a reference to the classes in the API. For more complete
|
14
|
+
# usage documentation, see the RFM home page at http://sixfriedrice.com/wp/products/rfm/
|
15
|
+
#
|
16
|
+
# = Quick Start
|
17
|
+
#
|
18
|
+
# Rfm is a Gem. As such, any ruby file that uses it, needs to have these two lines on top:
|
19
|
+
#
|
20
|
+
# require "rubygems"
|
21
|
+
# require "rfm"
|
22
|
+
#
|
23
|
+
# (If you don't have Rfm installed, use the +gem install rfm+ command to get it.)
|
24
|
+
#
|
25
|
+
# === Get a Server
|
26
|
+
#
|
27
|
+
# Everything in Rfm starts with the Server object. You create a Server object like this:
|
28
|
+
#
|
29
|
+
# myServer = Rfm::Server.new(
|
30
|
+
# :host => "yourhost",
|
31
|
+
# :account_name => "someone",
|
32
|
+
# :pasword => "secret"
|
33
|
+
# )
|
34
|
+
#
|
35
|
+
# The Server object supports many other options, which you'll find explained in its
|
36
|
+
# documentation.
|
37
|
+
#
|
38
|
+
# Note: The account name and password are optional. You can instead provide them on
|
39
|
+
# a per-database basis (using Database::account_name and Database::password). But
|
40
|
+
# it is convenient to do it here because you often have one set of credentials
|
41
|
+
# across all databases. Also, you must provide an account_name and password if you
|
42
|
+
# want to ask the server for a list of available databases.
|
43
|
+
#
|
44
|
+
# === Get a Database
|
45
|
+
#
|
46
|
+
# Once you have a Server object, you can use it to get a Database. For example, if your
|
47
|
+
# database is called "Customers", you get it like this:
|
48
|
+
#
|
49
|
+
# myDatabase = myServer["Customers"]
|
50
|
+
#
|
51
|
+
# If you need to supply account and password info specifically for this database
|
52
|
+
# (rather than doing it at the Server level), do this:
|
53
|
+
#
|
54
|
+
# myDatabase.account_name = "someone"
|
55
|
+
# myDatabase.password = "secret"
|
56
|
+
#
|
57
|
+
# *IMPORTANT NOTE:* The account name you use to access FileMaker must have the
|
58
|
+
# +fmxml+ extended privilege. In other words, edit its privilege set and turn on
|
59
|
+
# "Access via XML Web Publishing (fmxml)" in the Extended Privileges section
|
60
|
+
# at the bottom-left of the Edit Privilege Set window. If you don't do this,
|
61
|
+
# Rfm will report that it can't log in.
|
62
|
+
#
|
63
|
+
# === Get a Layout
|
64
|
+
#
|
65
|
+
# Every action you send to FileMaker always goes through a layout. This is how Rfm knows
|
66
|
+
# which table you want to work with, and which fields on that table you care about. This
|
67
|
+
# should feel pretty familiar now:
|
68
|
+
#
|
69
|
+
# myLayout = myDatabase["Details"]
|
70
|
+
#
|
71
|
+
# You might use layouts you already have, or make new layout just for Rfm. Just remember that
|
72
|
+
# if you delete a layout, or remove a field from a layout that your Rfm code uses, the
|
73
|
+
# code will stop working.
|
74
|
+
#
|
75
|
+
# === Putting it Together
|
76
|
+
#
|
77
|
+
# Usually you don't care much about the intermediate Database object (it's a gateway object,
|
78
|
+
# if you will). So it is often easiest to combine all the above steps like this:
|
79
|
+
#
|
80
|
+
# myLayout = myServer["Customers"]["Details"]
|
81
|
+
#
|
82
|
+
# === Performing Actions
|
83
|
+
#
|
84
|
+
# The Layout object can do a lot of things (see its documentation for a full list). But
|
85
|
+
# in general, it involves records. For instance, you can find records:
|
86
|
+
#
|
87
|
+
# result = myLayout.find({"First Name" => "Bill"})
|
88
|
+
#
|
89
|
+
# That code finds everybody whose first name in Bill. All the Layout methods return an
|
90
|
+
# ResultSet object. It contains the records, as well as metadata about the fields and
|
91
|
+
# portals on the layout. Usually you'll only concern yourself with the records (and you
|
92
|
+
# can read about the others in the ResultSet documentation).
|
93
|
+
#
|
94
|
+
# ResultSet is a subclass of Array, Ruby's built in array type. So you can treate it just
|
95
|
+
# like any other array:
|
96
|
+
#
|
97
|
+
# first_record = result[0]
|
98
|
+
# a_few_records = result[3,7]
|
99
|
+
# record_count = result.size
|
100
|
+
#
|
101
|
+
# But usually you'll want to loop through them all. Because this is an array, you can use
|
102
|
+
# code that is familiar to any Ruby whiz:
|
103
|
+
#
|
104
|
+
# result.each { |record|
|
105
|
+
# # do something with record here
|
106
|
+
# }
|
107
|
+
#
|
108
|
+
# === Working with Records
|
109
|
+
#
|
110
|
+
# The records in a ResultSet are actually Record objects. They hold the actual data from
|
111
|
+
# FileMaker. Record subclasses Hash, another built in Ruby type, so you can use them like
|
112
|
+
# this:
|
113
|
+
#
|
114
|
+
# full_name = record["First Name"] + ' ' + record["Last Name"]
|
115
|
+
# info.merge(record)
|
116
|
+
# record.each_value { |value| puts value }
|
117
|
+
# if record.value?("Bill") then puts "Bill is in there somewhere"
|
118
|
+
#
|
119
|
+
# The field name serves as the hash key, so these examples get fields called First Name and
|
120
|
+
# Last Name. (Note: Unlike a typical Ruby hash, Record objects are not case sensitive. You
|
121
|
+
# can say +record["first name"]+ or +record["FIRST NAME"]+ and it will still work.)
|
122
|
+
#
|
123
|
+
# A record object has the power to save changes to itself back to the database. For example:
|
124
|
+
#
|
125
|
+
# records.each { |record|
|
126
|
+
# record["First Name"] = record["First Name"].upcase
|
127
|
+
# record.save
|
128
|
+
# }
|
129
|
+
#
|
130
|
+
# That concise code converts the First Name field to all uppercase in every record in the
|
131
|
+
# ResultSet. Note that each time you call Record::save, if the record has been modified,
|
132
|
+
# Rfm has to send an action to FileMaker. A loop like the one above will be quite slow
|
133
|
+
# across many records. There is not fast way to update lots of records at once right now,
|
134
|
+
# although you might be able to accomplish it with a FileMaker script by passing a
|
135
|
+
# parameter).
|
136
|
+
#
|
137
|
+
# === Editing and Deleting Records
|
138
|
+
#
|
139
|
+
# Any time you edit or delete a record, you *must* provide the record's internal record
|
140
|
+
# if. This is not the value in any field. Rather, it is the ID FileMaker assigns to the
|
141
|
+
# record internally. So an edit or delete is almost always a two-step process:
|
142
|
+
#
|
143
|
+
# record = myLayout.find({"Customer ID" => "1234"})[0]
|
144
|
+
# myLayout.edit(record.record_id, {"First Name" => "Steve"})
|
145
|
+
#
|
146
|
+
# The code above first finds a Customer record. It then uses the Record::record_id method
|
147
|
+
# to discover that record's internal id. That id is passed to the Layout::edit method.
|
148
|
+
# The edit method also accepts a hash of record changes. In this case, we're changing
|
149
|
+
# the value in the First Name field to "Steve".
|
150
|
+
#
|
151
|
+
# Also, note the [0] on the end of the first line. A find _always_ returns a ResultSet.
|
152
|
+
# If there's only one record, it is still in an array. This array just happens to have only
|
153
|
+
# one element. The [0] pulls out that single record.
|
154
|
+
#
|
155
|
+
# To delete a record, you would do this instead:
|
156
|
+
#
|
157
|
+
# record = myLayout.find({"Customer ID" => "1234"})[0]
|
158
|
+
# myLayout.delete(record.record_id)
|
159
|
+
#
|
160
|
+
# Finally, the Layout::find method can also find a record using its internal id:
|
161
|
+
#
|
162
|
+
# record = myLayout.find(some_id)
|
163
|
+
#
|
164
|
+
# If the parameter you pass to Layout::find is not a hash, it is converted to a string
|
165
|
+
# and assumed to be a record id.
|
166
|
+
#
|
167
|
+
# === Performing Scripts
|
168
|
+
#
|
169
|
+
# Rfm can run a script in conjunction with any other action. For example, you might want
|
170
|
+
# to find a set of records, then run a script on them all. Or you may want to run a script
|
171
|
+
# when you delete a record. Here's how:
|
172
|
+
#
|
173
|
+
# myLayout.find({"First Name" => "Bill"}, {:post_script => "Process Sales"})
|
174
|
+
#
|
175
|
+
# This code finds every record with "Bill" in the First Name field, then runs the script
|
176
|
+
# called "Process Sales." You can control when the script actually runs, as explained in
|
177
|
+
# the documentation for Common Options for the Layout class.
|
178
|
+
#
|
179
|
+
# You can also pass a parameter to the script when it runs. Here's the deal:
|
180
|
+
#
|
181
|
+
# myLayout.find(
|
182
|
+
# {"First Name" => "Bill"},
|
183
|
+
# {:post_script => ["Process Sales", "all"]}
|
184
|
+
# )
|
185
|
+
#
|
186
|
+
# This time, the text value "all" is passed to the script as a script parameter.
|
187
|
+
#
|
188
|
+
# =Notes on Rfm with Ruby on Rails
|
189
|
+
#
|
190
|
+
# Rfm is a great fit for Rails. But it isn't ActiveRecord, so you need to do things
|
191
|
+
# a little differently.
|
192
|
+
#
|
193
|
+
# === Configuration
|
194
|
+
#
|
195
|
+
# To avoid having to reconfigure your Server object in every Rails action, you
|
196
|
+
# might add a configuration hash to the environment.rb. It can include all the
|
197
|
+
# options you need to connecto to your server:
|
198
|
+
#
|
199
|
+
# RFM_CONFIG = {
|
200
|
+
# :host => "yourhost",
|
201
|
+
# :account_name => "someone",
|
202
|
+
# :password => "secret",
|
203
|
+
# :db => "Customers"
|
204
|
+
# }
|
205
|
+
#
|
206
|
+
# Then you can get a server concisely:
|
207
|
+
#
|
208
|
+
# myServer = Server.net(RFM_CONFIG)
|
209
|
+
# myServer[RFM_CONFIG[:db]]["My Layout"]...
|
210
|
+
#
|
211
|
+
# You might even want to add code to your application.rb to centralize access
|
212
|
+
# to your various layouts.
|
213
|
+
#
|
214
|
+
# === Disable ActiveRecord
|
215
|
+
#
|
216
|
+
# If you're not using any SQL database in your Rails app, you'll quickly discover
|
217
|
+
# that Rails insists on a SQL database configuration anyway. This is easy to fix.
|
218
|
+
# Just turn off ActiveRecord. In the environment.rb, find the line that starts with
|
219
|
+
# +config.frameworks+. This is where you can disable the parts of Rails you're not
|
220
|
+
# using. Uncomment the line and make it look like this:
|
221
|
+
#
|
222
|
+
# config.frameworks -= [ :active_record ]
|
223
|
+
#
|
224
|
+
# Now Rails will no longer insist on a SQL database.
|
225
|
+
|
226
|
+
$: << File.expand_path(File.dirname(__FILE__))
|
227
|
+
|
228
|
+
require 'rfm_command'
|
229
|
+
require 'rfm_util'
|
230
|
+
require 'rfm_result'
|
231
|
+
require 'rfm_factory'
|
232
|
+
require 'rfm_error'
|