fmrest 0.10.0 → 0.13.0

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