fmrest 0.11.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/CHANGELOG.md +32 -0
  4. data/README.md +228 -844
  5. metadata +71 -101
  6. data/.github/workflows/ci.yml +0 -33
  7. data/.gitignore +0 -26
  8. data/.rspec +0 -3
  9. data/.travis.yml +0 -5
  10. data/Gemfile +0 -3
  11. data/Rakefile +0 -6
  12. data/fmrest.gemspec +0 -38
  13. data/lib/fmrest.rb +0 -34
  14. data/lib/fmrest/connection_settings.rb +0 -124
  15. data/lib/fmrest/errors.rb +0 -30
  16. data/lib/fmrest/spyke.rb +0 -21
  17. data/lib/fmrest/spyke/base.rb +0 -23
  18. data/lib/fmrest/spyke/container_field.rb +0 -59
  19. data/lib/fmrest/spyke/model.rb +0 -36
  20. data/lib/fmrest/spyke/model/associations.rb +0 -82
  21. data/lib/fmrest/spyke/model/attributes.rb +0 -171
  22. data/lib/fmrest/spyke/model/auth.rb +0 -43
  23. data/lib/fmrest/spyke/model/connection.rb +0 -135
  24. data/lib/fmrest/spyke/model/container_fields.rb +0 -25
  25. data/lib/fmrest/spyke/model/global_fields.rb +0 -40
  26. data/lib/fmrest/spyke/model/http.rb +0 -37
  27. data/lib/fmrest/spyke/model/orm.rb +0 -212
  28. data/lib/fmrest/spyke/model/serialization.rb +0 -91
  29. data/lib/fmrest/spyke/model/uri.rb +0 -30
  30. data/lib/fmrest/spyke/portal.rb +0 -55
  31. data/lib/fmrest/spyke/relation.rb +0 -359
  32. data/lib/fmrest/spyke/spyke_formatter.rb +0 -273
  33. data/lib/fmrest/spyke/validation_error.rb +0 -25
  34. data/lib/fmrest/string_date.rb +0 -220
  35. data/lib/fmrest/token_store.rb +0 -12
  36. data/lib/fmrest/token_store/active_record.rb +0 -74
  37. data/lib/fmrest/token_store/base.rb +0 -25
  38. data/lib/fmrest/token_store/memory.rb +0 -26
  39. data/lib/fmrest/token_store/moneta.rb +0 -41
  40. data/lib/fmrest/token_store/redis.rb +0 -45
  41. data/lib/fmrest/v1.rb +0 -23
  42. data/lib/fmrest/v1/auth.rb +0 -30
  43. data/lib/fmrest/v1/connection.rb +0 -115
  44. data/lib/fmrest/v1/container_fields.rb +0 -114
  45. data/lib/fmrest/v1/dates.rb +0 -81
  46. data/lib/fmrest/v1/paths.rb +0 -47
  47. data/lib/fmrest/v1/raise_errors.rb +0 -59
  48. data/lib/fmrest/v1/token_session.rb +0 -134
  49. data/lib/fmrest/v1/token_store/active_record.rb +0 -13
  50. data/lib/fmrest/v1/token_store/memory.rb +0 -13
  51. data/lib/fmrest/v1/type_coercer.rb +0 -192
  52. data/lib/fmrest/v1/utils.rb +0 -94
  53. data/lib/fmrest/version.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e6433cf32d6d0111377f6080967e96fd5ff4cd54c5e223551c777a24c58e8662
4
- data.tar.gz: 1a0fcd5951ab9b5bee88d822a429f16b02dcb01d5c95f74de9d529bb1ed00278
3
+ metadata.gz: cebcaeabea056bcedc6e48b911ec3b1941251b7ddfc77e4e4c756fd88c99cdf9
4
+ data.tar.gz: 15a9061d6efc330b645d6bf325f52cfc7e550f9b020d954324e3c1fa456c0276
5
5
  SHA512:
6
- metadata.gz: a0130f8b3598b3723d3c9e2514448a44a10381045176894cfed21244547c7ed41d0bc83fd18ab40981e9a2fc9ac7bd5c7290a5026b301878ea2c1d9ec440bb76
7
- data.tar.gz: 0fc6a827bb57dea0b261bb812b58322dad8a01eecf78a4344bef877732f4f0b016636750833c048c5831e63e5015c707264a0697282cc7fba9a6879a0cd7e8b1
6
+ metadata.gz: 26685e56f1ad34dadbd5d6d7516e692502d7b5184e319bde83b562f713be03ef39ad8637eb967b2e83c7622c81434c91671f59e7ebc314331d44a67117080a6b
7
+ data.tar.gz: 4903de48f1ec3e1d7939ee689298083c09b89c49dbf7c1e27032b3986993021791977bff2d34cf1d13dc408e358a860e6bd65c0fbebf29fb2cda42d4251dae6a
data/.yardopts CHANGED
@@ -1,2 +1,4 @@
1
1
  --markup markdown
2
2
  --plugin activesupport-concern
3
+ -
4
+ docs/*
data/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  ## Changelog
2
2
 
3
+ ### 0.14.0
4
+
5
+ * Aliased `FmRest::Spyke::Base` as `FmRest::Layout` (now preferred), and
6
+ provided a shortcut version for setting the layout name (e.g. `class Foo <
7
+ FmRest::Layout("LayoutName")`)
8
+ * Made `layout` class setting subclass-inheritable
9
+
10
+ ### 0.13.1
11
+
12
+ * Fix downloading of container field data from FMS19+
13
+
14
+ ### 0.13.0
15
+
16
+ * Split `fmrest` gem into `fmrest-core` and `fmrest-spyke`. `fmrest` becomes a
17
+ wrapper for the two new gems.
18
+ * Fix bug preventing connection databases with spaces in their names.
19
+ * Improved portal support with ability to delete portal records, and better
20
+ refreshing of portal records after saving the parent.
21
+ * `FmRest::Spyke::Base#__record_id` and `FmRest::Spyke::Base#__mod_id` now
22
+ always return integers if set.
23
+
24
+ ### 0.12.0
25
+
26
+ * Rename `FmRest::Spyke::Base#id=` to `FmRest::Spyke::Base#__record_id=` to
27
+ prevent clobbering of FileMaker layout-defined fields
28
+ * Removed previously deprecated `FmRest::Spyke::Base(config)` syntax
29
+ * Better yard documentation
30
+
31
+ ### 0.11.1
32
+
33
+ * Fix a couple crashes due to missing constants
34
+
3
35
  ### 0.11.0
4
36
 
5
37
  * Added custom class for connection settings, providing indifferent access
data/README.md CHANGED
@@ -7,105 +7,123 @@ A Ruby client for
7
7
  [FileMaker 18 and 19's Data API](https://help.claris.com/en/data-api-guide)
8
8
  using
9
9
  [Faraday](https://github.com/lostisland/faraday) and with optional
10
- [Spyke](https://github.com/balvig/spyke) support (ActiveRecord-ish models).
11
-
12
- If you're looking for a Ruby client for the legacy XML/Custom Web Publishing
13
- API try the fabulous [ginjo-rfm gem](https://github.com/ginjo/rfm) instead.
10
+ ActiveRecord-ish ORM features through [Spyke](https://github.com/balvig/spyke).
14
11
 
15
12
  fmrest-ruby only partially implements FileMaker 18's Data API.
16
13
  See the [implementation completeness table](#api-implementation-completeness-table)
17
14
  to see if a feature you need is natively supported by the gem.
18
15
 
16
+ ## Gems
17
+
18
+ The `fmrest` gem is a wrapper for two other gems:
19
+
20
+ * `fmrest-spyke`, providing an ActiveRecord-like ORM library built on top
21
+ of `fmrest-core` and [Spyke](https://github.com/balvig/spyke).
22
+ * `fmrest-core`, providing the core Faraday connection builder, session
23
+ management, and other core utilities.
24
+
19
25
  ## Installation
20
26
 
21
- Add this line to your Gemfile:
27
+ Add this to your Gemfile:
22
28
 
23
29
  ```ruby
24
30
  gem 'fmrest'
25
-
26
- # Optional but recommended (for ORM features)
27
- gem 'spyke'
28
31
  ```
29
32
 
30
- ## Basic usage (without ORM)
31
-
32
- To get a Faraday connection that can handle FM's Data API auth workflow:
33
+ Or if you just want to use the Faraday connection without the ORM features:
33
34
 
34
35
  ```ruby
35
- connection = FmRest::V1.build_connection(
36
- host: "example.com",
37
- database: "database name",
38
- username: "username",
39
- password: "password"
40
- )
36
+ gem 'fmrest-core'
41
37
  ```
42
38
 
43
- The returned connection will prefix any non-absolute paths with
44
- `"/fmi/data/v1/databases/:database/"`, so you only need to supply the
45
- meaningful part of the path.
39
+ ## Simple examples
40
+
41
+ ### ORM example
46
42
 
47
- To send a request to the Data API use Faraday's standard methods, e.g.:
43
+ Most people would want to use the ORM features:
48
44
 
49
45
  ```ruby
50
- # Get all records
51
- connection.get("layouts/MyFancyLayout/records")
46
+ # A Layout model connecting to the "Honeybees Web" FileMaker layout
47
+ class Honeybee < FmRest::Layout("Honeybees Web")
48
+ # Connection settings
49
+ self.fmrest_config = {
50
+ host: "…",
51
+ database: "…",
52
+ username: "…",
53
+ password: "…"
54
+ }
52
55
 
53
- # Create new record
54
- connection.post do |req|
55
- req.url "layouts/MyFancyLayout/records"
56
+ # Mapped attributes
57
+ attributes name: "Bee Name", age: "Bee Age"
56
58
 
57
- # You can just pass a hash for the JSON body
58
- req.body = { ... }
59
+ # Portals
60
+ has_portal :flowers
61
+
62
+ # File container
63
+ container :photo, field_name: "Bee Photo"
59
64
  end
60
- ```
61
65
 
62
- For each request fmrest-ruby will first request a session token (using the
63
- provided username and password) if it doesn't yet have one in store.
66
+ # Find a record by id
67
+ bee = Honeybee.find(9)
64
68
 
65
- ### Logging out of the database session
69
+ bee.name = "Hutch"
70
+
71
+ # Add a new record to portal
72
+ bee.flowers.build(name: "Daisy")
66
73
 
67
- The Data API requires sending a DELETE request to
68
- `/fmi/data/:version/databases/:database_name/sessions/:session_token`
69
- in order to log out from the session
70
- ([see docs](https://fmhelp.filemaker.com/docs/18/en/dataapi/#connect-database_log-out)).
74
+ bee.save
75
+ ```
71
76
 
72
- Since fmrest-ruby handles the storage of session tokens internally, and the
73
- token is required to build the logout URL, this becomes a non-trivial action.
77
+ ### Barebones connection example (without ORM)
74
78
 
75
- To remedy this, fmrest-ruby connections recognize when you're trying to logout
76
- and substitute whatever is in the `:session_token` section of the logout path
77
- with the actual session token:
79
+ In case you don't need the advanced ORM features (e.g. if you only need minimal
80
+ Data API interaction and just want a lightweight solution) you can simply use
81
+ the Faraday connection provided by `fmrest-core`:
78
82
 
79
83
  ```ruby
80
- # Logout from the database session
81
- connection.delete "sessions/this-will-be-replaced-with-the-actual-token"
84
+ connection = FmRest::V1.build_connection(
85
+ host: "",
86
+ database: "…",
87
+ username: "…",
88
+ password: "…"
89
+ )
90
+
91
+ # Get all records (as parsed JSON)
92
+ connection.get("layouts/FancyLayout/records")
93
+
94
+ # Create new record
95
+ connection.post do |req|
96
+ req.url "layouts/FancyLayout/records"
97
+
98
+ # You can just pass a hash for the JSON body
99
+ req.body = { … }
100
+ end
82
101
  ```
83
102
 
84
- If you're using the ORM features this becomes much easier, see
85
- [Model.logout](#modellogout) below.
103
+ See the [main document on using the base
104
+ connection](docs/BaseConnectionUsage.md) for more.
86
105
 
87
106
  ## Connection settings
88
107
 
89
- In addition to the required `:host`, `:database`, `:username` and `:password`
90
- connection options, you can also pass `:ssl` and `:proxy`, which are passed to
91
- the underlying [Faraday](https://github.com/lostisland/faraday) connection.
108
+ The minimum required connection settings are `:host`, `:database`, `:username`
109
+ and `:password`, but fmrest-ruby has many other options you can pass when
110
+ setting up a connection (see [full list](#full-list-of-available-options) below).
92
111
 
93
- You can use this to, for instance, disable SSL verification:
112
+ `:ssl` and `:proxy` are forwarded to the underlying
113
+ [Faraday](https://github.com/lostisland/faraday) connection. You can use this
114
+ to, for instance, disable SSL verification:
94
115
 
95
116
  ```ruby
96
- FmRest::V1.build_connection(
97
- host: "example.com",
98
- ...
99
- ssl: { verify: false }
100
- )
117
+ {
118
+ host: "",
119
+
120
+ ssl: { verify: false }
121
+ }
101
122
  ```
102
123
 
103
124
  You can also pass a `:log` option for basic request logging, see the section on
104
125
  [Logging](#Logging) below.
105
126
 
106
- `:username` is also aliased as `:account_name` to provide cross-compatibility
107
- with the ginjo-rfm gem.
108
-
109
127
  ### Full list of available options
110
128
 
111
129
  Option | Description | Format | Default
@@ -114,10 +132,11 @@ Option | Description | Format
114
132
  `:database` | | String | None
115
133
  `:username` | | String | None
116
134
  `:password` | | String | None
135
+ `:account_name` | Alias of `:username` | String | None
117
136
  `:ssl` | SSL options to be forwarded to Faraday | Faraday SSL options | None
118
137
  `:proxy` | Proxy options to be forwarded to Faraday | Faraday proxy options | None
119
138
  `:log` | Log JSON responses to STDOUT | Boolean | `false`
120
- `:coerce_dates` | See section on [date fields](#date-fields) | Boolean \| `:hybrid` \| `:full` | `false`
139
+ `:coerce_dates` | See section on [date fields](#date-fields-and-timezones) | Boolean \| `:hybrid` \| `:full` | `false`
121
140
  `:date_format` | Date parsing format | String (FM date format) | `"MM/dd/yyyy"`
122
141
  `:timestamp_format` | Timestmap parsing format | String (FM date format) | `"MM/dd/yyyy HH:mm:ss"`
123
142
  `:time_format` | Time parsing format | String (FM date format) | `"HH:mm:ss"`
@@ -132,232 +151,62 @@ through `FmRest.default_connection_settings=`. E.g.:
132
151
 
133
152
  ```ruby
134
153
  FmRest.default_connection_settings = {
135
- host: "example.com",
136
- database: "database name",
137
- username: "username",
138
- password: "password"
154
+ host: "",
155
+ database: "",
156
+ username: "",
157
+ password: ""
139
158
  }
140
159
  ```
141
160
 
142
- This configuration will be used by default by `FmRest::V1.build_connection` as
143
- well as your models whenever you don't pass a configuration hash explicitly.
144
-
161
+ These settings will be used by default by `FmRest::Layout` models whenever you
162
+ don't set `fmrest_config=` explicitly, as well as by
163
+ `FmRest::V1.build_connection` in case you're setting up your Faraday connection
164
+ manually.
145
165
 
146
166
  ## Session token store
147
167
 
148
- By default fmrest-ruby will use a memory-based store for the session tokens.
149
- This is generally good enough for development, but not good enough for
150
- production, as in-memory tokens aren't shared across threads/processes.
151
-
152
- Besides the default token store the following token stores are bundled with fmrest-ruby:
153
-
154
- ### ActiveRecord
155
-
156
- On Rails apps already using ActiveRecord setting up this token store should be
157
- dead simple:
158
-
159
- ```ruby
160
- # config/initializers/fmrest.rb
161
- require "fmrest/token_store/active_record"
162
-
163
- FmRest.token_store = FmRest::TokenStore::ActiveRecord
164
- ```
165
-
166
- No migrations are needed, the token store table will be created automatically
167
- when needed, defaulting to the table name "fmrest_session_tokens". If you want
168
- to change the table name you can do so by initializing the token store and
169
- passing it the `:table_name` option:
170
-
171
- ```ruby
172
- FmRest.token_store = FmRest::TokenStore::ActiveRecord.new(table_name: "my_token_store")
173
- ```
174
-
175
- ### Redis
176
-
177
- To use the Redis token store do:
178
-
179
- ```ruby
180
- require "fmrest/token_store/redis"
181
-
182
- FmRest.token_store = FmRest::TokenStore::Redis
183
- ```
184
-
185
- You can also initialize it with the following options:
186
-
187
- * `:redis` - A `Redis` object to use as connection, if ommited a new `Redis`
188
- object will be created with remaining options
189
- * `:prefix` - The prefix to use for token keys, by default `"fmrest-token:"`
190
- * Any other options will be passed to `Redis.new` if `:redis` isn't provided
191
-
192
- Examples:
193
-
194
- ```ruby
195
- # Passing a Redis connection explicitly
196
- FmRest.token_store = FmRest::TokenStore::Redis.new(redis: Redis.new, prefix: "my-fancy-prefix:")
197
-
198
- # Passing options for Redis.new
199
- FmRest.token_store = FmRest::TokenStore::Redis.new(prefix: "my-fancy-prefix:", host: "10.0.1.1", port: 6380, db: 15)
200
- ```
201
-
202
- NOTE: redis-rb is not included as a gem dependency of fmrest-ruby, so you'll
203
- have to add it to your Gemfile.
204
-
205
- ### Moneta
206
-
207
- [Moneta](https://github.com/moneta-rb/moneta) is a key/value store wrapper
208
- around many different storage backends. If ActiveRecord or Redis don't suit
209
- your needs, chances are Moneta will.
210
-
211
- To use it:
212
-
213
- ```ruby
214
- # config/initializers/fmrest.rb
215
- require "fmrest/token_store/moneta"
216
-
217
- FmRest.token_store = FmRest::TokenStore::Moneta
218
- ```
219
-
220
- By default the `:Memory` moneta backend will be used.
221
-
222
- You can also initialize it with the following options:
223
-
224
- * `:backend` - The moneta backend to initialize the store with
225
- * `:prefix` - The prefix to use for token keys, by default `"fmrest-token:"`
226
- * Any other options will be passed to `Moneta.new`
227
-
228
- Examples:
229
-
230
- ```ruby
231
- # Using YAML as a backend with a custom prefix
232
- FmRest.token_store = FmRest::TokenStore::Moneta.new(
233
- backend: :YAML,
234
- file: "tmp/tokens.yml",
235
- prefix: "my-tokens"
236
- )
237
- ```
238
-
239
- NOTE: the moneta gem is not included as a dependency of fmrest-ruby, so
240
- you'll have to add it to your Gemfile.
241
-
242
-
243
- ## Date fields
244
-
245
- Since the Data API uses JSON (wich doesn't provide a native date/time object),
246
- dates and timestamps are received in string format. By default fmrest-ruby
247
- leaves those string fields untouched, but it provides an opt-in feature to try
248
- to automatically "coerce" them into Ruby date objects.
249
-
250
- The connection option `:coerce_dates` controls this feature. Possible values
251
- are:
252
-
253
- * `:full` - whenever a string matches the given date/timestamp/time format,
254
- convert them to `Date` or `DateTime` objects as appropriate
255
- * `:hybrid` or `true` - similar as above, but instead of converting to regular
256
- `Date`/`DateTime` it converts strings to `FmRest::StringDate` and
257
- `FmRest::StringDateTime`, "hybrid" classes provided by fmrest-ruby that
258
- retain the functionality of `String` while also providing most the
259
- functionality of `Date`/`DateTime` (more on this below)
260
- * `false` - disable date coercion entirely (default), leave original string
261
- values untouched
262
-
263
- Enabling date coercion works with both basic fmrest-ruby connections and Spyke
264
- models (ORM).
265
-
266
- The connection options `:date_format`, `:timestamp_format` and `:time_format`
267
- control how to match and parse dates. You only need to provide these if you use
268
- a date/time localization different from American format (the default).
269
-
270
- Future versions of fmrest-ruby will provide better (and less heuristic) ways of
271
- specifying and/or detecting date fields (e.g. by requesting layout metadata or
272
- a DSL in model classes).
273
-
274
- ### Hybrid string/date objects
275
-
276
- `FmRest::StringDate` and `FmRest::StringDateTime` are special classes that
277
- inherit from `String`, but internally parse and store a `Date` or `DateTime`,
278
- and delegate any methods not provided by `String` to those objects. In other
279
- words, they quack like a duck *and* bark like a dog.
168
+ fmrest-ruby includes a number of options for storing session tokens:
280
169
 
281
- You can use these when you want fmrest-ruby to provide you with date objects,
282
- but you don't want to worry about date coercion of false positives (i.e. a
283
- string field that gets converted to `Date` because it just so matched the given
284
- date format).
170
+ * Memory
171
+ * ActiveRecord
172
+ * Redis
173
+ * Moneta
285
174
 
286
- Be warned however that these classes come with a fair share of known gotchas
287
- (see GitHub wiki for more info). Some of those gothas can be removed by calling
175
+ See the [main document on token stores](docs/TokenStore.md) for detailed info
176
+ on how to set up each store.
288
177
 
289
- ```ruby
290
- FmRest::StringDateAwareness.enable
291
- ```
292
-
293
- Which will extend the core `Date` and `DateTime` classes to be aware of
294
- `FmRest::StringDate`, especially when calling `Date.===`, `Date.parse` or
295
- `Date._parse`.
296
-
297
- If you're working with ActiveRecord models this will also make them accept
298
- `FmRest::StringDate` values for date fields.
299
-
300
- ### Timezones
301
-
302
- fmrest-ruby has basic timezone support. You can set the `:timezone` option in
303
- your connection settings to one of the following values:
178
+ ## Date fields and timezones
304
179
 
305
- * `:local` - dates will be converted to your system local time offset (as
306
- defined by `ENV["TZ"]`), or the timezone set by `Time.zone` if you're using
307
- ActiveSupport
308
- * `:utc` - dates will be converted to UTC offset
309
- * `nil` - (default) ignore timezones altogether
180
+ fmrest-ruby has automatic detection and coercion of date fields to and from
181
+ Ruby date/time objects. Basic timezone support is also provided.
310
182
 
183
+ See the [main document on date fields](docs/DateFields.md) for more info.
311
184
 
312
- ## Spyke support (ActiveRecord-like ORM)
185
+ ## ActiveRecord-like ORM (fmrest-spyke)
313
186
 
314
187
  [Spyke](https://github.com/balvig/spyke) is an ActiveRecord-like gem for
315
- building REST models. fmrest-ruby has Spyke support out of the box, although
316
- Spyke itself is not a dependency of fmrest-ruby, so you'll need to add it to
317
- your Gemfile yourself:
318
-
319
- ```ruby
320
- gem 'spyke'
321
- ```
322
-
323
- Then require fmrest-ruby's Spyke support:
324
-
325
- ```ruby
326
- # Put this in config/initializers/fmrest.rb if it's a Rails project
327
- require "fmrest/spyke"
328
- ```
188
+ building REST ORM models. fmrest-ruby builds its ORM features atop Spyke,
189
+ bundled in the `fmrest-spyke` gem (already included if you're using the
190
+ `fmrest` gem).
329
191
 
330
- And finally extend your Spyke models with `FmRest::Spyke`:
192
+ To create a model you can inherit directly from `FmRest::Layout` (itself a
193
+ subclass of `Spyke::Base`).
331
194
 
332
195
  ```ruby
333
- class Honeybee < Spyke::Base
334
- include FmRest::Spyke
196
+ class Honeybee < FmRest::Layout
335
197
  end
336
198
  ```
337
199
 
338
- This will make your Spyke model send all its requests in Data API format, with
339
- token session auth. Find, create, update and destroy actions should all work
340
- as expected.
341
-
342
- Alternatively you can inherit directly from the shorthand
343
- `FmRest::Spyke::Base`, which is in itself a subclass of `Spyke::Base` with
344
- `FmRest::Spyke` already included:
345
-
346
- ```ruby
347
- class Honeybee < FmRest::Spyke::Base
348
- end
349
- ```
350
-
351
- All of Spyke's basic ORM operations work:
200
+ All of Spyke's basic ORM operations work as expected:
352
201
 
353
202
  ```ruby
354
203
  bee = Honeybee.new
355
204
 
356
205
  bee.name = "Hutch"
357
- bee.save # POST request
206
+ bee.save # POST request (creates new record)
358
207
 
359
208
  bee.name = "ハッチ"
360
- bee.save # PATCH request
209
+ bee.save # PATCH request (updates existing record)
361
210
 
362
211
  bee.reload # GET request
363
212
 
@@ -366,54 +215,44 @@ bee.destroy # DELETE request
366
215
  bee = Honeybee.find(9) # GET request
367
216
  ```
368
217
 
369
- Read Spyke's documentation for more information on these basic features.
218
+ It's recommended that you read Spyke's documentation for more information on
219
+ these basic features. If you've used ActiveRecord or similar ORM libraries
220
+ you'll find it quite familiar.
221
+
222
+ Notice that `FmRest::Layout` is aliased as `FmRest::Spyke::Base`. Previous
223
+ versions of fmrest-ruby only provided the latter version, so if you're already
224
+ using `FmRest::Spyke::Base` there's no need to rename your classes to
225
+ `FmRest::Layout`, both will continue to work interchangeably.
370
226
 
371
- In addition `FmRest::Spyke` extends `Spyke::Base` subclasses with the following
227
+ In addition, `FmRest::Layout` extends `Spyke::Base` with the following
372
228
  features:
373
229
 
374
- ### Model.fmrest_config=
230
+ ### FmRest::Layout.fmrest_config=
375
231
 
376
- Usually to tell a Spyke object to use a certain Faraday connection you'd use:
232
+ This allows you to set Data API connection settings specific to your model
233
+ class:
377
234
 
378
235
  ```ruby
379
- class Honeybee < Spyke::Base
380
- self.connection = Faraday.new(...)
381
- end
382
- ```
383
-
384
- fmrest-ruby simplfies the process of setting up your Spyke model with a Faraday
385
- connection by allowing you to just set your Data API connection settings:
386
-
387
- ```ruby
388
- class Honeybee < Spyke::Base
389
- include FmRest::Spyke
390
-
236
+ class Honeybee < FmRest::Layout
391
237
  self.fmrest_config = {
392
- host: "example.com",
393
- database: "My Database",
394
- username: "...",
395
- password: "..."
238
+ host: "",
239
+ database: "",
240
+ username: "",
241
+ password: ""
396
242
  }
397
243
  end
398
244
  ```
399
245
 
400
- This will automatically create a proper Faraday connection for those connection
401
- settings.
246
+ This will automatically create a proper Faraday connection using those
247
+ connection settings, so you don't have to worry about setting that up.
402
248
 
403
249
  Note that these settings are inheritable, so you could create a base class that
404
250
  does the initial connection setup and then inherit from it in models using that
405
251
  same connection. E.g.:
406
252
 
407
253
  ```ruby
408
- class BeeBase < Spyke::Base
409
- include FmRest::Spyke
410
-
411
- self.fmrest_config = {
412
- host: "example.com",
413
- database: "My Database",
414
- username: "...",
415
- password: "..."
416
- }
254
+ class BeeBase < FmRest::Layout
255
+ self.fmrest_config = { host: "…", database: "…", … }
417
256
  end
418
257
 
419
258
  class Honeybee < BeeBase
@@ -421,76 +260,45 @@ class Honeybee < BeeBase
421
260
  end
422
261
  ```
423
262
 
424
- ### Model.fmrest_config_overlay=
263
+ Also, if not set, your model will try to use
264
+ `FmRest.default_connection_settings` instead.
425
265
 
426
- There may be cases where you want to use different connection settings
427
- depending on context, for example if you want to use username and password
428
- provided by the user in a web application. Since `Model.fmrest_config` is
429
- global, changing the username/password for one context would also change it for
430
- all other contexts, leading to security issues.
266
+ #### Connection settings overlays
431
267
 
432
- `Model.fmrest_config_overlay=` solves that issue by allowing you to override
433
- some settings in a thread-local and reversible manner. That way, using the same
434
- example as above, you could connect to the Data API with user-provided
435
- credentials without having them leak into other users of your web application.
268
+ There may be cases where you want to use a different set of connection settings
269
+ depending on context. For example, if you want to use username and password
270
+ provided by the user in a web application. Since `.fmrest_config`
271
+ is set at the class level, changing the username/password for the model in one
272
+ context would also change it in all other contexts, leading to security issues.
436
273
 
437
- E.g.:
274
+ To solve this scenario, fmrest-ruby provides a way of defining thread-local and
275
+ reversible connection settings overlays through
276
+ `.fmrest_config_overlay=`.
438
277
 
439
- ```ruby
440
- class BeeBase < Spyke::Base
441
- include FmRest::Spyke
278
+ See the [main document on connection setting overlays](docs/ConfigOverlays.md)
279
+ for details on how it works.
442
280
 
443
- # Host and database provided as base settings
444
- self.fmrest_config = {
445
- host: "example.com",
446
- database: "My Database"
447
- }
448
- end
281
+ ### FmRest::Layout.layout
449
282
 
450
- # E.g. in a controller-action of a Rails application:
451
-
452
- # User-provided credentials
453
- BeeBase.fmrest_config_overlay = {
454
- username: params[:username],
455
- password: params[:password]
456
- }
457
-
458
- # Perform some Data API requests ...
459
- ```
460
-
461
- ### Model.clear_fmrest_config_overlay
462
-
463
- Clears the thread-local settings provided to `fmrest_config_overaly=`.
464
-
465
- ### Model.with_overlay
466
-
467
- Runs a block with the given settings overlay, resetting them after the block
468
- finishes running. It wraps execution in its own fiber, so it doesn't affect the
469
- overlay of the currently-running thread.
283
+ Use `layout` to set the layout name for your model.
470
284
 
471
285
  ```ruby
472
- Honeybee.with_overlay(username: "...", password: "...") do
473
- Honeybee.query(...)
286
+ class Honeybee < FmRest::Layout
287
+ layout "Honeybees Web"
474
288
  end
475
289
  ```
476
290
 
477
- ### Model.layout
478
-
479
- Use `layout` to set the `:layout` part of API URLs, e.g.:
291
+ Alternatively, you can set the layout name in the class definition line:
480
292
 
481
293
  ```ruby
482
- class Honeybee < FmRest::Spyke::Base
483
- layout "Honeybees Web" # uri path will be "layouts/Honeybees%20Web/records(/:id)"
484
- end
294
+ class Honeybee < FmRest::Layout("Honeybees Web")
485
295
  ```
486
296
 
487
- This is much preferred over using Spyke's `uri` to set custom URLs for your
488
- Data API models.
297
+ Note that you only need to manually set the layout name if the name of the
298
+ class and the name of the layout differ, otherwise fmrest-ruby will just use
299
+ the name of the class.
489
300
 
490
- Note that you only need to set this if the name of the model and the name of
491
- the layout differ, otherwise the default will just work.
492
-
493
- ### Model.request_auth_token
301
+ ### FmRest::Layout.request_auth_token
494
302
 
495
303
  Requests a Data API session token using the connection settings in
496
304
  `fmrest_config` and returns it if successful, otherwise returns `false`.
@@ -499,16 +307,16 @@ You normally don't need to use this method as fmrest-ruby will automatically
499
307
  request and store session tokens for you (provided that `:autologin` is
500
308
  `true`).
501
309
 
502
- ### Model.logout
310
+ ### FmRest::Layout.logout
503
311
 
504
- Use `logout` to log out from the database session (you may call it on any model
505
- that uses the database session you want to log out from).
312
+ Use `.logout` to log out from the database session (you may call it on any
313
+ model that uses the database session you want to log out from).
506
314
 
507
315
  ```ruby
508
316
  Honeybee.logout
509
317
  ```
510
318
 
511
- ### Mapped Model.attributes
319
+ ### Mapped FmRest::Layout.attributes
512
320
 
513
321
  Spyke allows you to define your model's attributes using `attributes`, however
514
322
  sometimes FileMaker's field names aren't very Ruby-ORM-friendly, especially
@@ -517,7 +325,7 @@ fmrest-ruby extends `attributes`' functionality to allow you to map
517
325
  Ruby-friendly attribute names to FileMaker field names. E.g.:
518
326
 
519
327
  ```ruby
520
- class Honeybee < FmRest::Spyke::Base
328
+ class Honeybee < FmRest::Layout
521
329
  attributes first_name: "First Name", last_name: "Last Name"
522
330
  end
523
331
  ```
@@ -536,62 +344,21 @@ bee.first_name = "Queen"
536
344
  bee.attributes # => { "First Name": "Queen", "Last Name": "Buzz" }
537
345
  ```
538
346
 
539
- ### Model.has_portal
347
+ ### FmRest::Layout.has_portal
540
348
 
541
- You can define portal associations on your model as such:
349
+ You can define portal associations on your model wth `has_portal`, as such:
542
350
 
543
351
  ```ruby
544
- class Honeybee < FmRest::Spyke::Base
352
+ class Honeybee < FmRest::Layout
545
353
  has_portal :flowers
546
354
  end
547
355
 
548
- class Flower < FmRest::Spyke::Base
356
+ class Flower < FmRest::Layout
549
357
  attributes :color, :species
550
358
  end
551
359
  ```
552
360
 
553
- In this case fmrest-ruby will expect the portal table name and portal object
554
- name to be both "flowers", i.e. the expected portal JSON portion should look
555
- like this:
556
-
557
- ```json
558
- ...
559
- "portalData": {
560
- "flowers": [
561
- {
562
- "flowers::color": "red",
563
- "flowers::species": "rose"
564
- }
565
- ]
566
- }
567
- ```
568
-
569
- If you need to specify different values for them you can do so with
570
- `portal_key` for the portal table name, and `attribute_prefix` for the portal
571
- object name, and `class_name`, e.g.:
572
-
573
- ```ruby
574
- class Honeybee < FmRest::Spyke::Base
575
- has_portal :pollinated_flowers, portal_key: "Bee Flowers",
576
- attribute_prefix: "Flower",
577
- class_name: "Flower"
578
- end
579
- ```
580
-
581
- The above will use the `Flower` model class and expects the following portal JSON
582
- portion:
583
-
584
- ```json
585
- ...
586
- "portalData": {
587
- "Bee Flowers": [
588
- {
589
- "Flower::color": "white",
590
- "Flower::species": "rose"
591
- }
592
- ]
593
- }
594
- ```
361
+ See the [main document on portal associations](docs/Portals.md) for details.
595
362
 
596
363
  ### Dirty attributes
597
364
 
@@ -621,208 +388,11 @@ Guides](https://guides.rubyonrails.org/active_model_basics.html#dirty).
621
388
  Since Spyke is API-agnostic it only provides a wide-purpose `.where` method for
622
389
  passing arbitrary parameters to the REST backend. fmrest-ruby however is well
623
390
  aware of its backend API, so it extends Spkye models with a bunch of useful
624
- querying methods.
625
-
626
- #### .limit
627
-
628
- `.limit` sets the limit for get and find request:
629
-
630
- ```ruby
631
- Honeybee.limit(10)
632
- ```
633
-
634
- NOTE: You can also set a default limit value for a model class, see
635
- [other notes on querying](#other-notes-on-querying).
636
-
637
- You can also use `.limit` to set limits on portals:
638
-
639
- ```ruby
640
- Honeybee.limit(hives: 3, flowers: 2)
641
- ```
642
-
643
- To remove the limit on a portal set it to `nil`:
644
-
645
- ```ruby
646
- Honeybee.limit(flowers: nil)
647
- ```
648
-
649
- #### .offset
650
-
651
- `.offset` sets the offset for get and find requests:
652
-
653
- ```ruby
654
- Honeybee.offset(10)
655
- ```
656
-
657
- You can also use `.offset` to set offsets on portals:
658
-
659
- ```ruby
660
- Honeybee.offset(hives: 3, flowers: 2)
661
- ```
662
-
663
- To remove the offset on a portal set it to `nil`:
664
-
665
- ```ruby
666
- Honeybee.offset(flowers: nil)
667
- ```
668
-
669
- #### .sort
670
-
671
- `.sort` (or `.order`) sets sorting options for get and find requests:
672
-
673
- ```ruby
674
- Honeybee.sort(:name, :age)
675
- Honeybee.order(:name, :age) # alias method
676
- ```
677
-
678
- You can set descending sort order by appending either `!` or `__desc` to a sort
679
- attribute (defaults to ascending order):
680
-
681
- ```ruby
682
- Honeybee.sort(:name, :age!)
683
- Honeybee.sort(:name, :age__desc)
684
- ```
685
-
686
- NOTE: You can also set default sort values for a model class, see
687
- [Other notes on querying](#other-notes-on-querying).
688
-
689
- #### .portal
690
-
691
- `.portal` (aliased as `.includes` and `.portals`) sets which portals to fetch
692
- (if any) for get and find requests (this recognizes portals defined with
693
- `has_portal`):
694
-
695
- ```ruby
696
- Honeybee.portal(:hives) # include just the :hives portal
697
- Honeybee.includes(:hives) # alias method
698
- Honeybee.portals(:hives, :flowers) # alias for pluralization fundamentalists
699
- ```
700
-
701
- Chaining calls to `.portal` will add portals to the existing included list:
702
-
703
- ```ruby
704
- Honeybee.portal(:flowers).portal(:hives) # include both portals
705
- ```
706
-
707
- If you want to disable portals for the scope call `.portal(false)`:
708
-
709
- ```ruby
710
- Honeybee.portal(false) # disable portals for this scope
711
- ```
712
-
713
- If you want to include all portals call `.portal(true)`:
714
-
715
- ```ruby
716
- Honeybee.portal(true) # include all portals
717
- ```
718
-
719
- For convenience you can also use `.with_all_portals` and `.without_portals`,
720
- which behave just as calling `.portal(true)` and `portal(false)` respectively.
721
-
722
- NOTE: By default all portals are included.
723
-
724
- #### .query
725
-
726
- `.query` sets query conditions for a find request (and supports attributes as
727
- defined with `attributes`):
728
-
729
- ```ruby
730
- Honeybee.query(name: "Hutch")
731
- # JSON -> {"query": [{"Bee Name": "Hutch"}]}
732
- ```
733
-
734
- Passing multiple attributes to `.query` will group them in the same JSON object:
735
-
736
- ```ruby
737
- Honeybee.query(name: "Hutch", age: 4)
738
- # JSON -> {"query": [{"Bee Name": "Hutch", "Bee Age": 4}]}
739
- ```
740
-
741
- Calling `.query` multiple times or passing it multiple hashes creates separate
742
- JSON objects (so you can define OR queries):
743
-
744
- ```ruby
745
- Honeybee.query(name: "Hutch").query(name: "Maya")
746
- Honeybee.query({ name: "Hutch" }, { name: "Maya" })
747
- # JSON -> {"query": [{"Bee Name": "Hutch"}, {"Bee Name": "Maya"}]}
748
- ```
749
-
750
- #### .omit
751
-
752
- `.omit` works like `.query` but excludes matches:
753
-
754
- ```ruby
755
- Honeybee.omit(name: "Hutch")
756
- # JSON -> {"query": [{"Bee Name": "Hutch", "omit": "true"}]}
757
- ```
758
-
759
- You can get the same effect by passing `omit: true` to `.query`:
760
-
761
- ```ruby
762
- Honeybee.query(name: "Hutch", omit: true)
763
- # JSON -> {"query": [{"Bee Name": "Hutch", "omit": "true"}]}
764
- ```
765
-
766
- #### .script
767
-
768
- `.script` enables the execution of scripts during query requests.
769
-
770
- ```ruby
771
- Honeybee.script("My script").find_some # Fetch records and execute a script
772
- ```
773
-
774
- See section on [script execution](#script-execution) below for more info.
775
-
776
- #### Other notes on querying
777
-
778
- You can chain all query methods together:
779
-
780
- ```ruby
781
- Honeybee.limit(10).offset(20).sort(:name, :age!).portal(:hives).query(name: "Hutch")
782
- ```
783
-
784
- You can also set default values for limit and sort on the class:
785
-
786
- ```ruby
787
- class Honeybee < FmRest::Spyke::Base
788
- self.default_limit = 1000
789
- self.default_sort = [:name, :age!]
790
- end
791
- ```
792
-
793
- Calling any `Enumerable` method on the resulting scope object will trigger a
794
- server request, so you can treat the scope as a collection:
795
-
796
- ```ruby
797
- Honeybee.limit(10).sort(:name).each { |bee| ... }
798
- ```
799
-
800
- If you want to explicitly run the request instead you can use `.find_some` on
801
- the scope object:
802
-
803
- ```ruby
804
- Honeybee.limit(10).sort(:name).find_some # => [<Honeybee...>, ...]
805
- ```
806
-
807
- If you want just a single result you can use `.first` instead (this will
808
- force `.limit(1)`):
809
-
810
- ```ruby
811
- Honeybee.query(name: "Hutch").first # => <Honeybee...>
812
- ```
813
-
814
- If you know the id of the record you should use `.find(id)` instead of
815
- `.query(id: id).first` (so that the sent request is
816
- `GET ../:layout/records/:id` instead of `POST ../:layout/_find`).
817
-
818
- ```ruby
819
- Honeybee.find(89) # => <Honeybee...>
820
- ```
821
-
822
- Note also that if you use `.find(id)` your `.query()` parameters (as well as
823
- limit, offset and sort parameters) will be discarded as they're not supported
824
- by the single record endpoint.
391
+ querying methods: `.query`, `.limit`, `.offset`, `.sort`, `.portal`, `.script`,
392
+ etc.
825
393
 
394
+ See the [main document on querying](docs/Querying.md) for detailed information
395
+ on the query API methods.
826
396
 
827
397
  ### Finding records in batches
828
398
 
@@ -830,249 +400,63 @@ Sometimes you want to iterate over a very large number of records to do some
830
400
  processing, but requesting them all at once would result in one huge request to
831
401
  the Data API, and loading too many records in memory all at once.
832
402
 
833
- To mitigate this problem you can use `.find_in_batches` and `.find_each`. If
834
- you've used ActiveRecord you're probably familiar with how they operate:
835
-
836
- ```ruby
837
- # Find records in batches of 100 each
838
- Honeybee.query(hive: "Queensville").find_in_batches(batch_size: 100) do |batch|
839
- dispatch_bees(batch)
840
- end
841
-
842
- # Iterate over all records using batches
843
- Honeybee.query(hive: "Queensville").find_each(batch_size: 100) do |bee|
844
- bee.dispatch
845
- end
846
- ```
847
-
848
- `.find_in_batches` yields collections of records (batches), while `.find_each`
849
- yields individual records, but using batches behind the scenes.
850
-
851
- Both methods accept a block-less form in which case they return an
852
- `Enumerator`:
853
-
854
- ```ruby
855
- batch_enum = Honeybee.find_in_batches
856
-
857
- batch = batch_enum.next # => Spyke::Collection
858
-
859
- batch_enum.each do |batch|
860
- process_batch(batch)
861
- end
862
-
863
- record_enum = Honeybee.find_each
864
-
865
- record_enum.next # => Honeybee
866
- ```
867
-
868
- NOTE: By its nature, batch processing is subject to race conditions if other
869
- processes are modifying the database.
403
+ To mitigate this problem you can use `.find_in_batches` and `.find_each`.
870
404
 
405
+ See the [main document on finding in batches](docs/FindInBatches.md) for
406
+ detailed information on how those work.
871
407
 
872
408
  ### Container fields
873
409
 
874
410
  You can define container fields on your model class with `container`:
875
411
 
876
412
  ```ruby
877
- class Honeybee < FmRest::Spyke::Base
413
+ class Honeybee < FmRest::Layout
878
414
  container :photo, field_name: "Beehive Photo ID"
879
415
  end
880
416
  ```
881
417
 
882
- `:field_name` specifies the original field in the FM layout and is optional, if
883
- not given it will default to the name of your attribute (just `:photo` in this
884
- example).
885
-
886
- (Note that you don't need to define container fields with `attributes` in
887
- addition to the `container` definition.)
888
-
889
- This will provide you with the following instance methods:
890
-
891
- ```ruby
892
- bee = Honeybee.new
893
-
894
- bee.photo.url # The URL of the container file on the FileMaker server
895
-
896
- bee.photo.download # Download the contents of the container as an IO object
897
-
898
- bee.photo.upload(filename_or_io) # Upload a file to the container
899
- ```
900
-
901
- `upload` also accepts an options hash with the following options:
902
-
903
- * `:repetition` - Sets the field repetition
904
- * `:filename` - The filename to use when uploading (defaults to
905
- `filename_or_io.original_filename` if available)
906
- * `:content_type` - The MIME content type to use (defaults to
907
- `application/octet-stream`)
908
-
418
+ See the [main document on container fields](docs/ContainerFields.md) for
419
+ details on how to use it.
909
420
 
910
421
  ### Script execution
911
422
 
912
- The Data API allows running scripts as part of many types of requests.
913
-
914
- #### Model.execute_script
915
- As of FM18 you can execute scripts directly. To do that for a specific model
916
- use `Model.execute_script`:
917
-
918
- ```ruby
919
- result = Honeybee.execute_script("My Script", param: "optional parameter")
920
- ```
921
-
922
- This will return a `Spyke::Result` object containing among other things the
923
- result of the script execution:
924
-
925
- ```ruby
926
- result.metadata[:script][:after]
927
- # => { result: "oh hi", error: "0" }
928
- ```
929
-
930
- #### Script options object format
931
-
932
- All other script-capable requests take one or more of three possible script
933
- execution options: `script.prerequest`, `script.presort` and plain `script`
934
- (which fmrest-ruby dubs `after` for convenience).
935
-
936
- Because of that fmrest-ruby uses a common object format for specifying script options
937
- across multiple methods. That object format is as follows:
938
-
939
- ```ruby
940
- # Just a string means to execute that `after' script without a parameter
941
- "My Script"
942
-
943
- # A 2-elemnent array means [script name, script parameter]
944
- ["My Script", "parameter"]
945
-
946
- # A hash with keys :prerequest, :presort and/or :after sets those scripts for
947
- {
948
- prerequest: "My Prerequest Script",
949
- presort: "My Presort Script",
950
- after: "My Script"
951
- }
952
-
953
- # Using 2-element arrays as objects in the hash allows specifying parameters
954
- {
955
- prerequest: ["My Prerequest Script", "parameter"],
956
- presort: ["My Presort Script", "parameter"],
957
- after: ["My Script", "parameter"]
958
- }
959
- ```
960
-
961
- #### Script execution on record save, destroy and reload
962
-
963
- A record instance's `.save` and `.destroy` methods both accept a `script:`
964
- option to which you can pass a script options object with
965
- [the above format](#script-options-object-format):
966
-
967
- ```ruby
968
- # Save the record and execute an `after' script called "My Script"
969
- bee.save(script: "My Script")
970
-
971
- # Same as above but with an added parameter
972
- bee.save(script: ["My Script", "parameter"])
973
-
974
- # Save the record and execute a presort script and an `after' script
975
- bee.save(script: { presort: "My Presort Script", after: "My Script" })
976
-
977
- # Destroy the record and execute a prerequest script with a parameter
978
- bee.destroy(script: { prerequest: ["My Prerequest Script", "parameter"] })
979
-
980
- # Reload the record and execute a prerequest script with a parameter
981
- bee.reload(script: { prerequest: ["My Prerequest Script", "parameter"] })
982
- ```
983
-
984
- #### Retrieving script execution results
985
-
986
- Every time a request is ran on a model or record instance of a model, a
987
- thread-local `Model.last_request_metadata` attribute is set on that model,
988
- which is a hash containing the results of script executions, if any were
989
- performed, among other metadata.
990
-
991
- The results for `:after`, `:prerequest` and `:presort` scripts are stored
992
- separately, under their matching key.
993
-
994
- ```ruby
995
- bee.save(script: { presort: "My Presort Script", after: "My Script" })
996
-
997
- Honeybee.last_request_metadata.script
998
- # => { after: { result: "oh hi", error: "0" }, presort: { result: "lo", error: "0" } }
999
- ```
1000
-
1001
- #### Executing scripts through query requests
1002
-
1003
- As mentioned under the [Query API](#query-api) section, you can use the
1004
- `.script` query method to specify that you want scripts executed when a query
1005
- is performed on that scope.
1006
-
1007
- `.script` takes the same options object specified [above](#script-options-object-format):
1008
-
1009
- ```ruby
1010
- # Find one Honeybee record executing a presort and after script
1011
- Honeybee.script(presort: ["My Presort Script", "parameter"], after: "My Script").first
1012
- ```
1013
-
1014
- The model class' `.last_request_metadata` will be set in case you need to get the result.
1015
-
1016
- In the case of retrieving multiple results (i.e. via `.find_some`) the
1017
- resulting collection will have a `.metadata` attribute method containing the
1018
- same metadata hash with script execution results. Note that this does not apply
1019
- to retrieving single records, in that case you'll have to use
1020
- `.last_request_metadata`.
423
+ The FM Data API allows running scripts as part of many types of requests, and
424
+ `fmrest-spyke` provides mechanisms for all of them.
1021
425
 
426
+ See the [main document on script execution](docs/ScriptExecution.md) for
427
+ details.
1022
428
 
1023
429
  ### Setting global field values
1024
430
 
1025
- You can call `.set_globals` on any `FmRest::Spyke::Base` model to set glabal
431
+ You can call `.set_globals` on any `FmRest::Layout` model to set global
1026
432
  field values on the database that model is configured for.
1027
433
 
1028
- You can pass it either a hash of fully qualified field names
1029
- (table_name::field_name), or 1-level-deep nested hashes, with the outer being a
1030
- table name and the inner keys being the field names:
1031
-
1032
- ```ruby
1033
- Honeybee.set_globals(
1034
- "beeTable::myVar" => "value",
1035
- "beeTable::myOtherVar" => "also a value"
1036
- )
1037
-
1038
- # Equivalent to the above example
1039
- Honeybee.set_globals(beeTable: { myVar: "value", myOtherVar: "also a value" })
1040
-
1041
- # Combined
1042
- Honeybee.set_globals(
1043
- "beeTable::myVar" => "value",
1044
- beeTable: { myOtherVar: "also a value" }
1045
- )
1046
- ```
1047
-
434
+ See the [main document on setting global field values](docs/GlobalFields.md)
435
+ for details.
1048
436
 
1049
437
  ## Logging
1050
438
 
1051
- If using fmrest-ruby + Spyke in a Rails app pretty log output will be set up
1052
- for you automatically by Spyke (see [their
439
+ If using `fmrest-spyke` with Rails then pretty log output will be set up for
440
+ you automatically by Spyke (see [their
1053
441
  README](https://github.com/balvig/spyke#log-output)).
1054
442
 
1055
- You can also enable simple STDOUT logging (useful for debugging) by passing
1056
- `log: true` in the options hash for either
443
+ You can also enable simple Faraday STDOUT logging of raw requests (useful for
444
+ debugging) by passing `log: true` in the options hash for either
1057
445
  `FmRest.default_connection_settings=` or your models' `fmrest_config=`, e.g.:
1058
446
 
1059
447
  ```ruby
1060
448
  FmRest.default_connection_settings = {
1061
- host: "example.com",
1062
- database: "My Database",
1063
- username: "z3r0c00l",
1064
- password: "abc123",
1065
- log: true
449
+ host: "",
450
+
451
+ log: true
1066
452
  }
1067
453
 
1068
454
  # Or in your model
1069
- class LoggyBee < FmRest::Spyke::Base
455
+ class LoggyBee < FmRest::Layout
1070
456
  self.fmrest_config = {
1071
- host: "example.com",
1072
- database: "My Database",
1073
- username: "...",
1074
- password: "...",
1075
- log: true
457
+ host: "",
458
+
459
+ log: true
1076
460
  }
1077
461
  end
1078
462
  ```
@@ -1082,7 +466,7 @@ If you need to set up more complex logging for your models can use the
1082
466
  Faraday connection, e.g.:
1083
467
 
1084
468
  ```ruby
1085
- class LoggyBee < FmRest::Spyke::Base
469
+ class LoggyBee < FmRest::Layout
1086
470
  faraday do |conn|
1087
471
  conn.response :logger, MyApp.logger, bodies: true
1088
472
  end
@@ -1093,33 +477,43 @@ end
1093
477
 
1094
478
  FM Data API reference: https://fmhelp.filemaker.com/docs/18/en/dataapi/
1095
479
 
1096
- | FM 18 Data API feature | Supported by basic connection | Supported by FmRest::Spyke::Base |
1097
- |-------------------------------------|-------------------------------|----------------------------------|
1098
- | Log in using HTTP Basic Auth | Yes | Yes |
1099
- | Log in using OAuth | No | No |
1100
- | Log in to an external data source | No | No |
1101
- | Log in using a FileMaker ID account | No | No |
1102
- | Log out | Yes | Yes |
1103
- | Get product information | Manual* | No |
1104
- | Get database names | Manual* | No |
1105
- | Get script names | Manual* | No |
1106
- | Get layout names | Manual* | No |
1107
- | Get layout metadata | Manual* | No |
1108
- | Create a record | Manual* | Yes |
1109
- | Edit a record | Manual* | Yes |
1110
- | Duplicate a record | Manual* | No |
1111
- | Delete a record | Manual* | Yes |
1112
- | Get a single record | Manual* | Yes |
1113
- | Get a range of records | Manual* | Yes |
1114
- | Get container data | Manual* | Yes |
1115
- | Upload container data | Manual* | Yes |
1116
- | Perform a find request | Manual* | Yes |
1117
- | Set global field values | Manual* | Yes
1118
- | Run a script | Manual* | Yes |
1119
- | Run a script with another request | Manual* | Yes |
480
+ | FM 18 Data API feature | Supported by basic connection | Supported by FmRest::Layout |
481
+ |-------------------------------------|-------------------------------|-----------------------------|
482
+ | Log in using HTTP Basic Auth | Yes | Yes |
483
+ | Log in using OAuth | No | No |
484
+ | Log in to an external data source | No | No |
485
+ | Log in using a FileMaker ID account | No | No |
486
+ | Log out | Yes | Yes |
487
+ | Get product information | Manual* | No |
488
+ | Get database names | Manual* | No |
489
+ | Get script names | Manual* | No |
490
+ | Get layout names | Manual* | No |
491
+ | Get layout metadata | Manual* | No |
492
+ | Create a record | Manual* | Yes |
493
+ | Edit a record | Manual* | Yes |
494
+ | Duplicate a record | Manual* | No |
495
+ | Delete a record | Manual* | Yes |
496
+ | Edit portal records | Manual* | Yes |
497
+ | Get a single record | Manual* | Yes |
498
+ | Get a range of records | Manual* | Yes |
499
+ | Get container data | Manual* | Yes |
500
+ | Upload container data | Manual* | Yes |
501
+ | Perform a find request | Manual* | Yes |
502
+ | Set global field values | Manual* | Yes |
503
+ | Run a script | Manual* | Yes |
504
+ | Run a script with another request | Manual* | Yes |
1120
505
 
1121
506
  \* You can manually supply the URL and JSON to a `FmRest` connection.
1122
507
 
508
+ ## Supported Ruby versions
509
+
510
+ fmrest-ruby aims to support and is [tested against](https://github.com/beezwax/fmrest-ruby/actions?query=workflow%3ACI)
511
+ the following Ruby implementations:
512
+
513
+ * Ruby 2.5
514
+ * Ruby 2.6
515
+ * Ruby 2.7
516
+ * Ruby 3.0
1123
517
 
1124
518
  ## Gem development
1125
519
 
@@ -1128,20 +522,11 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
1128
522
  prompt that will allow you to experiment (it will auto-load all fixtures in
1129
523
  spec/fixtures).
1130
524
 
1131
- To install this gem onto your local machine, run `bundle exec rake install`. To
1132
- release a new version, update the version number in `version.rb`, and then run
1133
- `bundle exec rake release`, which will create a git tag for the version, push
1134
- git commits and tags, and push the `.gem` file to
1135
- [rubygems.org](https://rubygems.org).
1136
-
1137
-
1138
- ## Contributing
1139
-
1140
- Bug reports and pull requests are welcome. This project is intended to be a
1141
- safe, welcoming space for collaboration, and contributors are expected to
1142
- adhere to the [Contributor Covenant](http://contributor-covenant.org) code of
1143
- conduct.
1144
-
525
+ To install all gems onto your local machine, run
526
+ `bundle exec rake all:install`. To release a new version, update the version
527
+ number in `lib/fmrest/version.rb`, and then run `bundle exec rake all:release`,
528
+ which will create a git tag for the version, push git commits and tags, and
529
+ push the `.gem` files to [rubygems.org](https://rubygems.org).
1145
530
 
1146
531
  ## License
1147
532
 
@@ -1149,7 +534,6 @@ The gem is available as open source under the terms of the
1149
534
  [MIT License](https://opensource.org/licenses/MIT).
1150
535
  See [LICENSE.txt](LICENSE.txt).
1151
536
 
1152
-
1153
537
  ## Disclaimer
1154
538
 
1155
539
  This project is not sponsored by or otherwise affiliated with FileMaker, Inc,