fmrest 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/CHANGELOG.md +11 -0
  4. data/README.md +175 -809
  5. metadata +61 -109
  6. data/.gitignore +0 -26
  7. data/.rspec +0 -3
  8. data/.travis.yml +0 -5
  9. data/Gemfile +0 -3
  10. data/Rakefile +0 -6
  11. data/UPGRADING +0 -15
  12. data/fmrest.gemspec +0 -49
  13. data/lib/fmrest.rb +0 -36
  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 -9
  18. data/lib/fmrest/spyke/container_field.rb +0 -59
  19. data/lib/fmrest/spyke/model.rb +0 -33
  20. data/lib/fmrest/spyke/model/associations.rb +0 -86
  21. data/lib/fmrest/spyke/model/attributes.rb +0 -163
  22. data/lib/fmrest/spyke/model/auth.rb +0 -43
  23. data/lib/fmrest/spyke/model/connection.rb +0 -163
  24. data/lib/fmrest/spyke/model/container_fields.rb +0 -40
  25. data/lib/fmrest/spyke/model/global_fields.rb +0 -40
  26. data/lib/fmrest/spyke/model/http.rb +0 -77
  27. data/lib/fmrest/spyke/model/orm.rb +0 -256
  28. data/lib/fmrest/spyke/model/record_id.rb +0 -78
  29. data/lib/fmrest/spyke/model/serialization.rb +0 -99
  30. data/lib/fmrest/spyke/model/uri.rb +0 -29
  31. data/lib/fmrest/spyke/portal.rb +0 -55
  32. data/lib/fmrest/spyke/relation.rb +0 -359
  33. data/lib/fmrest/spyke/spyke_formatter.rb +0 -273
  34. data/lib/fmrest/spyke/validation_error.rb +0 -25
  35. data/lib/fmrest/string_date.rb +0 -220
  36. data/lib/fmrest/token_store.rb +0 -12
  37. data/lib/fmrest/token_store/active_record.rb +0 -74
  38. data/lib/fmrest/token_store/base.rb +0 -25
  39. data/lib/fmrest/token_store/memory.rb +0 -26
  40. data/lib/fmrest/token_store/moneta.rb +0 -41
  41. data/lib/fmrest/token_store/null.rb +0 -20
  42. data/lib/fmrest/token_store/redis.rb +0 -45
  43. data/lib/fmrest/v1.rb +0 -23
  44. data/lib/fmrest/v1/auth.rb +0 -30
  45. data/lib/fmrest/v1/connection.rb +0 -115
  46. data/lib/fmrest/v1/container_fields.rb +0 -114
  47. data/lib/fmrest/v1/dates.rb +0 -81
  48. data/lib/fmrest/v1/paths.rb +0 -47
  49. data/lib/fmrest/v1/raise_errors.rb +0 -57
  50. data/lib/fmrest/v1/token_session.rb +0 -133
  51. data/lib/fmrest/v1/token_store/active_record.rb +0 -13
  52. data/lib/fmrest/v1/token_store/memory.rb +0 -13
  53. data/lib/fmrest/v1/type_coercer.rb +0 -192
  54. data/lib/fmrest/v1/utils.rb +0 -94
  55. data/lib/fmrest/version.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 725c8356fc5933f0484f7d04a4458ecc85c638838c8d9869d039a6e09b0b15f6
4
- data.tar.gz: 2a8047594d93d13b0f6d9981159c16b1afdcaa19713c054391fc08ca1fa68633
3
+ metadata.gz: 04e163122c2e385a1957c0c3c111a7b4f9a75cbb04aaf362544383c78b972150
4
+ data.tar.gz: 2b69f8782b89ddbe4464fc7623f2abde16ccd1cdc113a56425e87a47b8b6876e
5
5
  SHA512:
6
- metadata.gz: 7a41a3e747bf6ccfe0de7e5541b0db35d30d9723b7a0eeb895fbe9e21f4c2c7e6f08ccd3012c1e6f4edaa5403966e2a7563b74490327c721990fbdd4ab79608a
7
- data.tar.gz: 16fb2868c102905a58632b1183581dcf4617d4e6c9f7529abad12916b78b3c692d21a469eaf7b23101d53ff55e8c9ccbfc1167556cc09855516647ce00565ea8
6
+ metadata.gz: e13a616364f5e6e5f61c4e97d27ecbef7450cf427f10fceb67d67d3dfb0394fc1e07ce27d80b1d0bf4310305b46c7fd0bd32175a1ba55aba30183334e153f72a
7
+ data.tar.gz: 23e8705ed23af5cb644b7b8616abdb72a04c3bf82e01a99b0118451f0b0f35267db04ad86781d2f754c0622a0e8c6a8dc6a92a0c107375bd11f2e79c17ccf49f
data/.yardopts CHANGED
@@ -1,2 +1,4 @@
1
1
  --markup markdown
2
2
  --plugin activesupport-concern
3
+ -
4
+ docs/*
data/CHANGELOG.md CHANGED
@@ -1,9 +1,20 @@
1
1
  ## Changelog
2
2
 
3
+ ### 0.13.0
4
+
5
+ * Split `fmrest` gem into `fmrest-core` and `fmrest-spyke`. `fmrest` becomes a
6
+ wrapper for the two new gems.
7
+ * Fix bug preventing connection databases with spaces in their names.
8
+ * Improved portal support with ability to delete portal records, and better
9
+ refreshing of portal records after saving the parent.
10
+ * `FmRest::Spyke::Base#__record_id` and `FmRest::Spyke::Base#__mod_id` now
11
+ always return integers if set.
12
+
3
13
  ### 0.12.0
4
14
 
5
15
  * Rename `FmRest::Spyke::Base#id=` to `FmRest::Spyke::Base#__record_id=` to
6
16
  prevent clobbering of FileMaker layout-defined fields
17
+ * Removed previously deprecated `FmRest::Spyke::Base(config)` syntax
7
18
  * Better yard documentation
8
19
 
9
20
  ### 0.11.1
data/README.md CHANGED
@@ -7,105 +7,122 @@ 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-core`, which provides the core Faraday connection builder, session
21
+ management, and other core utilities.
22
+ * `fmrest-spyke`, which provides an ActiveRecord-like ORM library built on top
23
+ of `fmrest-core` and Spyke.
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, do:
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 provided by `fmrest-spyke`:
48
44
 
49
45
  ```ruby
50
- # Get all records
51
- connection.get("layouts/MyFancyLayout/records")
46
+ class Honeybee < FmRest::Spyke::Base
47
+ # Connection settings
48
+ self.fmrest_config = {
49
+ host: "…",
50
+ database: "…",
51
+ username: "…",
52
+ password: "…"
53
+ }
52
54
 
53
- # Create new record
54
- connection.post do |req|
55
- req.url "layouts/MyFancyLayout/records"
55
+ # Mapped attributes
56
+ attributes name: "Bee Name", age: "Bee Age"
56
57
 
57
- # You can just pass a hash for the JSON body
58
- req.body = { ... }
58
+ # Portals
59
+ has_portal :flowers
60
+
61
+ # File container
62
+ container :photo, field_name: "Bee Photo"
59
63
  end
60
- ```
61
64
 
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.
65
+ # Find a record by id
66
+ bee = Honeybee.find(9)
67
+
68
+ bee.name = "Hutch"
64
69
 
65
- ### Logging out of the database session
70
+ # Add a new record to portal
71
+ bee.flowers.build(name: "Daisy")
66
72
 
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)).
73
+ bee.save
74
+ ```
71
75
 
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.
76
+ ### Barebones connection example (without ORM)
74
77
 
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:
78
+ In case you don't need the advanced ORM features (e.g. if you only need minimal
79
+ Data API interaction and just want a lightweight solution) you can simply use
80
+ the Faraday connection provided by `fmrest-core`:
78
81
 
79
82
  ```ruby
80
- # Logout from the database session
81
- connection.delete "sessions/this-will-be-replaced-with-the-actual-token"
83
+ connection = FmRest::V1.build_connection(
84
+ host: "",
85
+ database: "…",
86
+ username: "…",
87
+ password: "…"
88
+ )
89
+
90
+ # Get all records (as parsed JSON)
91
+ connection.get("layouts/MyFancyLayout/records")
92
+
93
+ # Create new record
94
+ connection.post do |req|
95
+ req.url "layouts/MyFancyLayout/records"
96
+
97
+ # You can just pass a hash for the JSON body
98
+ req.body = { … }
99
+ end
82
100
  ```
83
101
 
84
- If you're using the ORM features this becomes much easier, see
85
- [Model.logout](#modellogout) below.
102
+ See the [main document on using the base
103
+ connection](docs/BaseConnectionUsage.md) for more.
86
104
 
87
105
  ## Connection settings
88
106
 
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.
107
+ The minimum required connection settings are `:host`, `:database`, `:username`
108
+ and `:password`, but fmrest-ruby has many other options you can pass when
109
+ setting up a connection (see [full list](#full-list-of-available-options) below).
92
110
 
93
- You can use this to, for instance, disable SSL verification:
111
+ `:ssl` and `:proxy` are forwarded to the underlying
112
+ [Faraday](https://github.com/lostisland/faraday) connection. You can use this
113
+ to, for instance, disable SSL verification:
94
114
 
95
115
  ```ruby
96
- FmRest::V1.build_connection(
97
- host: "example.com",
98
- ...
99
- ssl: { verify: false }
100
- )
116
+ {
117
+ host: "",
118
+
119
+ ssl: { verify: false }
120
+ }
101
121
  ```
102
122
 
103
123
  You can also pass a `:log` option for basic request logging, see the section on
104
124
  [Logging](#Logging) below.
105
125
 
106
- `:username` is also aliased as `:account_name` to provide cross-compatibility
107
- with the ginjo-rfm gem.
108
-
109
126
  ### Full list of available options
110
127
 
111
128
  Option | Description | Format | Default
@@ -114,10 +131,11 @@ Option | Description | Format
114
131
  `:database` | | String | None
115
132
  `:username` | | String | None
116
133
  `:password` | | String | None
134
+ `:account_name` | Alias of `:username` | String | None
117
135
  `:ssl` | SSL options to be forwarded to Faraday | Faraday SSL options | None
118
136
  `:proxy` | Proxy options to be forwarded to Faraday | Faraday proxy options | None
119
137
  `:log` | Log JSON responses to STDOUT | Boolean | `false`
120
- `:coerce_dates` | See section on [date fields](#date-fields) | Boolean \| `:hybrid` \| `:full` | `false`
138
+ `:coerce_dates` | See section on [date fields](#date-fields-and-timezones) | Boolean \| `:hybrid` \| `:full` | `false`
121
139
  `:date_format` | Date parsing format | String (FM date format) | `"MM/dd/yyyy"`
122
140
  `:timestamp_format` | Timestmap parsing format | String (FM date format) | `"MM/dd/yyyy HH:mm:ss"`
123
141
  `:time_format` | Time parsing format | String (FM date format) | `"HH:mm:ss"`
@@ -132,232 +150,62 @@ through `FmRest.default_connection_settings=`. E.g.:
132
150
 
133
151
  ```ruby
134
152
  FmRest.default_connection_settings = {
135
- host: "example.com",
136
- database: "database name",
137
- username: "username",
138
- password: "password"
153
+ host: "",
154
+ database: "",
155
+ username: "",
156
+ password: ""
139
157
  }
140
158
  ```
141
159
 
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
-
160
+ These settings will be used by default by `FmRest::Spyke::Base` models whenever
161
+ you don't set `fmrest_config=` explicitly, as well as by
162
+ `FmRest::V1.build_connection` in case you're setting up your Faraday connection
163
+ manually.
145
164
 
146
165
  ## Session token store
147
166
 
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.
167
+ fmrest-ruby includes a number of options for storing session tokens:
210
168
 
211
- To use it:
169
+ * Memory
170
+ * ActiveRecord
171
+ * Redis
172
+ * Moneta
212
173
 
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
- ```
174
+ See the [main document on token stores](docs/TokenStore.md) for detailed info
175
+ on how to set up each store.
238
176
 
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.
177
+ ## Date fields and timezones
241
178
 
179
+ fmrest-ruby has automatic detection and coercion of date fields to and from
180
+ Ruby date/time objects. Basic timezone support is also provided.
242
181
 
243
- ## Date fields
182
+ See the [main document on date fields](docs/DateFields.md) for more info.
244
183
 
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.
280
-
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).
285
-
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
288
-
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:
304
-
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
310
-
311
-
312
- ## Spyke support (ActiveRecord-like ORM)
184
+ ## ActiveRecord-like ORM (fmrest-spyke)
313
185
 
314
186
  [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
- ```
187
+ building REST ORM models. fmrest-ruby builds its ORM features atop Spyke,
188
+ bundled in the `fmrest-spyke` gem (already included if you're using the
189
+ `fmrest` gem).
322
190
 
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
- ```
329
-
330
- And finally extend your Spyke models with `FmRest::Spyke`:
331
-
332
- ```ruby
333
- class Honeybee < Spyke::Base
334
- include FmRest::Spyke
335
- end
336
- ```
337
-
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:
191
+ To create a model you can inherit directly from `FmRest::Spyke::Base`, which is
192
+ itself a subclass of `Spyke::Base`.
345
193
 
346
194
  ```ruby
347
195
  class Honeybee < FmRest::Spyke::Base
348
196
  end
349
197
  ```
350
198
 
351
- All of Spyke's basic ORM operations work:
199
+ All of Spyke's basic ORM operations work as expected:
352
200
 
353
201
  ```ruby
354
202
  bee = Honeybee.new
355
203
 
356
204
  bee.name = "Hutch"
357
- bee.save # POST request
205
+ bee.save # POST request (creates new record)
358
206
 
359
207
  bee.name = "ハッチ"
360
- bee.save # PATCH request
208
+ bee.save # PATCH request (updates existing record)
361
209
 
362
210
  bee.reload # GET request
363
211
 
@@ -366,53 +214,38 @@ bee.destroy # DELETE request
366
214
  bee = Honeybee.find(9) # GET request
367
215
  ```
368
216
 
369
- Read Spyke's documentation for more information on these basic features.
217
+ It's recommended that you read Spyke's documentation for more information on
218
+ these basic features. If you've used ActiveRecord or similar ORM libraries
219
+ however you'll find it quite familiar.
370
220
 
371
- In addition `FmRest::Spyke` extends `Spyke::Base` subclasses with the following
221
+ In addition, `FmRest::Spyke::Base` extends `Spyke::Base` with the following
372
222
  features:
373
223
 
374
224
  ### Model.fmrest_config=
375
225
 
376
- Usually to tell a Spyke object to use a certain Faraday connection you'd use:
377
-
378
- ```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:
226
+ This allows you to set your Data API connection settings on your model:
386
227
 
387
228
  ```ruby
388
- class Honeybee < Spyke::Base
389
- include FmRest::Spyke
390
-
229
+ class Honeybee < FmRest::Spyke::Base
391
230
  self.fmrest_config = {
392
- host: "example.com",
393
- database: "My Database",
394
- username: "...",
395
- password: "..."
231
+ host: "",
232
+ database: "",
233
+ username: "",
234
+ password: ""
396
235
  }
397
236
  end
398
237
  ```
399
238
 
400
- This will automatically create a proper Faraday connection for those connection
401
- settings.
239
+ This will automatically create a proper Faraday connection using those
240
+ connection settings, so you don't have to worry about setting that up.
402
241
 
403
242
  Note that these settings are inheritable, so you could create a base class that
404
243
  does the initial connection setup and then inherit from it in models using that
405
244
  same connection. E.g.:
406
245
 
407
246
  ```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: "..."
247
+ class BeeBase < FmRest::Spyke::Base
248
+ self.fmrest_config = { host: "…", … }
416
249
  }
417
250
  end
418
251
 
@@ -421,72 +254,30 @@ class Honeybee < BeeBase
421
254
  end
422
255
  ```
423
256
 
424
- ### Model.fmrest_config_overlay=
425
-
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.
431
-
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.
436
-
437
- E.g.:
438
-
439
- ```ruby
440
- class BeeBase < Spyke::Base
441
- include FmRest::Spyke
442
-
443
- # Host and database provided as base settings
444
- self.fmrest_config = {
445
- host: "example.com",
446
- database: "My Database"
447
- }
448
- end
449
-
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
- ```
257
+ #### Connection settings overlays
460
258
 
461
- ### Model.clear_fmrest_config_overlay
259
+ There may be cases where you want to use a different set of connection settings
260
+ depending on context. For example, if you want to use username and password
261
+ provided by the user in a web application. Since `Model.fmrest_config` is set
262
+ at the class level, changing the username/password for the model in one context
263
+ would also change it in all other contexts, leading to security issues.
462
264
 
463
- Clears the thread-local settings provided to `fmrest_config_overaly=`.
265
+ To solve this scenario, fmrest-ruby provides a way of defining thread-local and
266
+ reversible connection settings overlays through `Model.fmrest_config_overlay=`.
464
267
 
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.
470
-
471
- ```ruby
472
- Honeybee.with_overlay(username: "...", password: "...") do
473
- Honeybee.query(...)
474
- end
475
- ```
268
+ See the [main document on connection setting overlays](docs/ConfigOverlays.md)
269
+ for details on how it works.
476
270
 
477
271
  ### Model.layout
478
272
 
479
- Use `layout` to set the `:layout` part of API URLs, e.g.:
273
+ Use `Model.layout` to define the layout for your model.
480
274
 
481
275
  ```ruby
482
276
  class Honeybee < FmRest::Spyke::Base
483
- layout "Honeybees Web" # uri path will be "layouts/Honeybees%20Web/records(/:id)"
277
+ layout "Honeybees Web"
484
278
  end
485
279
  ```
486
280
 
487
- This is much preferred over using Spyke's `uri` to set custom URLs for your
488
- Data API models.
489
-
490
281
  Note that you only need to set this if the name of the model and the name of
491
282
  the layout differ, otherwise the default will just work.
492
283
 
@@ -501,8 +292,8 @@ request and store session tokens for you (provided that `:autologin` is
501
292
 
502
293
  ### Model.logout
503
294
 
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).
295
+ Use `Model.logout` to log out from the database session (you may call it on any
296
+ model that uses the database session you want to log out from).
506
297
 
507
298
  ```ruby
508
299
  Honeybee.logout
@@ -538,7 +329,7 @@ bee.attributes # => { "First Name": "Queen", "Last Name": "Buzz" }
538
329
 
539
330
  ### Model.has_portal
540
331
 
541
- You can define portal associations on your model as such:
332
+ You can define portal associations on your model wth `has_portal`, as such:
542
333
 
543
334
  ```ruby
544
335
  class Honeybee < FmRest::Spyke::Base
@@ -550,48 +341,7 @@ class Flower < FmRest::Spyke::Base
550
341
  end
551
342
  ```
552
343
 
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
- ```
344
+ See the [main document on portal associations](docs/Portals.md) for details.
595
345
 
596
346
  ### Dirty attributes
597
347
 
@@ -621,208 +371,11 @@ Guides](https://guides.rubyonrails.org/active_model_basics.html#dirty).
621
371
  Since Spyke is API-agnostic it only provides a wide-purpose `.where` method for
622
372
  passing arbitrary parameters to the REST backend. fmrest-ruby however is well
623
373
  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.
374
+ querying methods: `.query`, `.limit`, `.offset`, `.sort`, `.portal`, `.script`,
375
+ etc.
825
376
 
377
+ See the [main document on querying](docs/Querying.md) for detailed information
378
+ on the query API methods.
826
379
 
827
380
  ### Finding records in batches
828
381
 
@@ -830,44 +383,10 @@ Sometimes you want to iterate over a very large number of records to do some
830
383
  processing, but requesting them all at once would result in one huge request to
831
384
  the Data API, and loading too many records in memory all at once.
832
385
 
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.
386
+ To mitigate this problem you can use `.find_in_batches` and `.find_each`.
870
387
 
388
+ See the [main document on finding in batches](docs/FindInBatches.md) for
389
+ detailed information on how those work.
871
390
 
872
391
  ### Container fields
873
392
 
@@ -879,200 +398,48 @@ class Honeybee < FmRest::Spyke::Base
879
398
  end
880
399
  ```
881
400
 
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
-
401
+ See the [main document on container fields](docs/ContainerFields.md) for
402
+ details on how to use it.
909
403
 
910
404
  ### Script execution
911
405
 
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`.
406
+ The FM Data API allows running scripts as part of many types of requests, and
407
+ `fmrest-spyke` provides mechanisms for all of them.
1021
408
 
409
+ See the [main document on script execution](docs/ScriptExecution.md) for
410
+ details.
1022
411
 
1023
412
  ### Setting global field values
1024
413
 
1025
- You can call `.set_globals` on any `FmRest::Spyke::Base` model to set glabal
414
+ You can call `.set_globals` on any `FmRest::Spyke::Base` model to set global
1026
415
  field values on the database that model is configured for.
1027
416
 
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
-
417
+ See the [main document on setting global field values](docs/GlobalFields.md)
418
+ for details.
1048
419
 
1049
420
  ## Logging
1050
421
 
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
422
+ If using `fmrest-spyke` with Rails then pretty log output will be set up for
423
+ you automatically by Spyke (see [their
1053
424
  README](https://github.com/balvig/spyke#log-output)).
1054
425
 
1055
- You can also enable simple STDOUT logging (useful for debugging) by passing
1056
- `log: true` in the options hash for either
426
+ You can also enable simple Faraday STDOUT logging of raw requests (useful for
427
+ debugging) by passing `log: true` in the options hash for either
1057
428
  `FmRest.default_connection_settings=` or your models' `fmrest_config=`, e.g.:
1058
429
 
1059
430
  ```ruby
1060
431
  FmRest.default_connection_settings = {
1061
- host: "example.com",
1062
- database: "My Database",
1063
- username: "z3r0c00l",
1064
- password: "abc123",
1065
- log: true
432
+ host: "",
433
+
434
+ log: true
1066
435
  }
1067
436
 
1068
437
  # Or in your model
1069
438
  class LoggyBee < FmRest::Spyke::Base
1070
439
  self.fmrest_config = {
1071
- host: "example.com",
1072
- database: "My Database",
1073
- username: "...",
1074
- password: "...",
1075
- log: true
440
+ host: "",
441
+
442
+ log: true
1076
443
  }
1077
444
  end
1078
445
  ```
@@ -1109,17 +476,26 @@ FM Data API reference: https://fmhelp.filemaker.com/docs/18/en/dataapi/
1109
476
  | Edit a record | Manual* | Yes |
1110
477
  | Duplicate a record | Manual* | No |
1111
478
  | Delete a record | Manual* | Yes |
479
+ | Edit portal records | Manual* | Yes |
1112
480
  | Get a single record | Manual* | Yes |
1113
481
  | Get a range of records | Manual* | Yes |
1114
482
  | Get container data | Manual* | Yes |
1115
483
  | Upload container data | Manual* | Yes |
1116
484
  | Perform a find request | Manual* | Yes |
1117
- | Set global field values | Manual* | Yes
485
+ | Set global field values | Manual* | Yes |
1118
486
  | Run a script | Manual* | Yes |
1119
487
  | Run a script with another request | Manual* | Yes |
1120
488
 
1121
489
  \* You can manually supply the URL and JSON to a `FmRest` connection.
1122
490
 
491
+ ## Supported Ruby versions
492
+
493
+ fmrest-ruby aims to support and is [tested against](https://github.com/beezwax/fmrest-ruby/actions?query=workflow%3ACI)
494
+ the following Ruby implementations:
495
+
496
+ * Ruby 2.5
497
+ * Ruby 2.6
498
+ * Ruby 2.7
1123
499
 
1124
500
  ## Gem development
1125
501
 
@@ -1128,20 +504,11 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
1128
504
  prompt that will allow you to experiment (it will auto-load all fixtures in
1129
505
  spec/fixtures).
1130
506
 
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
-
507
+ To install all gems onto your local machine, run
508
+ `bundle exec rake all:install`. To release a new version, update the version
509
+ number in `lib/fmrest/version.rb`, and then run `bundle exec rake all:release`,
510
+ which will create a git tag for the version, push git commits and tags, and
511
+ push the `.gem` files to [rubygems.org](https://rubygems.org).
1145
512
 
1146
513
  ## License
1147
514
 
@@ -1149,7 +516,6 @@ The gem is available as open source under the terms of the
1149
516
  [MIT License](https://opensource.org/licenses/MIT).
1150
517
  See [LICENSE.txt](LICENSE.txt).
1151
518
 
1152
-
1153
519
  ## Disclaimer
1154
520
 
1155
521
  This project is not sponsored by or otherwise affiliated with FileMaker, Inc,