fmrest 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a3fd72c8d862e6225e0997c1b5a3f68597304dccba912d4230f92495536bf528
4
+ data.tar.gz: 528e8673d20825ed9d1dacacad8b59493099a8b18f8f530baaac34038ba3e8ce
5
+ SHA512:
6
+ metadata.gz: 38fed0930933ce59b32054459f41a9aeb7b7d1b4c7ae6e5ead53e331452c2180cab4e1a08b582f5729df745e94db85ae4b5fdf448aacebce9dd772e9073f5d53
7
+ data.tar.gz: 00ab8ffd3e3dd0ac1ab8a91eccc8e60f0edd9844e77c32bf2775ac03fbd610e969315e6398d499ca8cf919c78c9dc7baa45b38109ee1f328241b46bca01769a5
@@ -0,0 +1,25 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+
24
+ # rspec failure tracking
25
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.3
5
+ before_install: gem install bundler -v 1.16.1
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at pedro_c@beezwax.net. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Pedro Carbajal and Beezwax Datatools, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,559 @@
1
+ # fmrest-ruby
2
+
3
+ A Ruby client for
4
+ [FileMaker 17's Data API](https://fmhelp.filemaker.com/docs/17/en/dataapi/)
5
+ using
6
+ [Faraday](https://github.com/lostisland/faraday) and with optional
7
+ [Spyke](https://github.com/balvig/spyke) support (ActiveRecord-ish models).
8
+
9
+ FileMaker 16's Data API is not supported (but you shouldn't be using it
10
+ anyway).
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.
14
+
15
+ fmrest-ruby does not currently implement the full spec of FileMaker Data API.
16
+
17
+ ## Installation
18
+
19
+ Add this line to your Gemfile:
20
+
21
+ ```ruby
22
+ gem 'fmrest'
23
+ ```
24
+
25
+ ## Basic usage
26
+
27
+ To get a Faraday connection that can handle FM's Data API auth workflow:
28
+
29
+ ```ruby
30
+ connection = FmRest::V1.build_connection(
31
+ host: "example.com",
32
+ database: "database name",
33
+ username: "username",
34
+ password: "password"
35
+ )
36
+ ```
37
+
38
+ The returned connection will prefix any non-absolute paths with
39
+ `"/fmi/data/v1/databases/:database/"`, so you only need to supply the
40
+ meaningful part of the path.
41
+
42
+ To send a request to the Data API use Faraday's standard methods, e.g.:
43
+
44
+ ```ruby
45
+ # Get all records
46
+ connection.get("layouts/MyFancyLayout/records")
47
+
48
+ # Create new record
49
+ connection.post do |req|
50
+ req.url "layouts/MyFancyLayout/records"
51
+
52
+ # You can just pass a hash for the JSON body
53
+ req.body = { ... }
54
+ end
55
+ ```
56
+
57
+ For each request fmrest-ruby will first request a session token (using the
58
+ provided username and password) if it doesn't yet have one in store.
59
+
60
+ ## Session token store
61
+
62
+ By default fmrest-ruby will use a memory-based store for the session tokens.
63
+ This is generally good enough for development, but not good enough for
64
+ production, as in-memory tokens aren't shared across threads/processes.
65
+
66
+ Besides the default memory token store an ActiveRecord-based token store is
67
+ included with the gem (maybe more to come later).
68
+
69
+ On Rails apps already using ActiveRecord setting up this token store should be
70
+ dead simple:
71
+
72
+ ```ruby
73
+ # config/initializers/fmrest.rb
74
+ require "fmrest/v1/token_store/active_record"
75
+
76
+ FmRest.token_store = FmRest::V1::TokenStore::ActiveRecord
77
+ ```
78
+
79
+ No migrations are needed, the token store table will be created automatically
80
+ when needed, defaulting to the table name "fmrest_session_tokens".
81
+
82
+ ## Spyke support
83
+
84
+ [Spyke](https://github.com/balvig/spyke) is an ActiveRecord-like gem for
85
+ building REST models. fmrest-ruby has Spyke support out of the box, although
86
+ Spyke itself is not a dependency of fmrest-ruby, so you'll need to add it to
87
+ your Gemfile yourself:
88
+
89
+ ```ruby
90
+ gem 'spyke'
91
+ ```
92
+
93
+ Then require fmrest-ruby's Spyke support:
94
+
95
+ ```ruby
96
+ # Put this in config/initializers/fmrest.rb if it's a Rails project
97
+ require "fmrest/spyke"
98
+ ```
99
+
100
+ And finally extend your Spyke models with `FmRest::Spyke`:
101
+
102
+ ```ruby
103
+ class Kitty < Spyke::Base
104
+ include FmRest::Spyke
105
+ end
106
+ ```
107
+
108
+ This will make your Spyke model send all its requests in Data API format, with
109
+ token session auth. Find, create, update and destroy actions should all work
110
+ as expected.
111
+
112
+ Alternatively you can inherit directly from the shorthand
113
+ `FmRest::Spyke::Base`, which is in itself a subclass of `Spyke::Base` with
114
+ `FmRest::Spyke` already included:
115
+
116
+ ```ruby
117
+ class Kitty < FmRest::Spyke::Base
118
+ end
119
+ ```
120
+
121
+ In this case you can pass the `fmrest_config` hash as an argument to `Base()`:
122
+
123
+ ```ruby
124
+ class Kitty < FmRest::Spyke::Base(host: "...", database: "...", username: "...", password: "...")
125
+ end
126
+
127
+ Kitty.fmrest_config # => { host: "...", database: "...", username: "...", password: "..." }
128
+ ```
129
+
130
+ All of Spyke's basic ORM operations work:
131
+
132
+ ```ruby
133
+ kitty = Kitty.new
134
+
135
+ kitty.name = "Felix"
136
+
137
+ kitty.save # POST request
138
+
139
+ kitty.name = "Tom"
140
+
141
+ kitty.save # PATCH request
142
+
143
+ kitty.reload # GET request
144
+
145
+ kitty.destroy # DELETE request
146
+
147
+ kitty = Kitty.find(9) # GET request
148
+ ```
149
+
150
+ Read Spyke's documentation for more information on these basic features.
151
+
152
+ In addition `FmRest::Spyke` extends `Spyke::Base` subclasses with the following
153
+ features:
154
+
155
+ ### Model.fmrest_config=
156
+
157
+ Usually to tell a Spyke object to use a certain Faraday connection you'd use:
158
+
159
+ ```ruby
160
+ class Kitty < Spyke::Base
161
+ self.connection = Faraday.new(...)
162
+ end
163
+ ```
164
+
165
+ fmrest-ruby simplfies the process of setting up your Spyke model with a Faraday
166
+ connection by allowing you to just set your Data API connection settings:
167
+
168
+ ```ruby
169
+ class Kitty < Spyke::Base
170
+ include FmRest::Spyke
171
+
172
+ self.fmrest_config = {
173
+ host: "example.com",
174
+ database: "database name",
175
+ username: "username",
176
+ password: "password"
177
+ }
178
+ end
179
+ ```
180
+
181
+ This will automatically create a proper Faraday connection for those connection
182
+ settings.
183
+
184
+ Note that these settings are inheritable, so you could create a base class that
185
+ does the initial connection setup and then inherit from it in models using that
186
+ same connection. E.g.:
187
+
188
+ ```ruby
189
+ class KittyBase < Spyke::Base
190
+ include FmRest::Spyke
191
+
192
+ self.fmrest_config = {
193
+ host: "example.com",
194
+ database: "My Database",
195
+ username: "username",
196
+ password: "password"
197
+ }
198
+ end
199
+
200
+ class Kitty < KittyBase
201
+ # This model will use the same connection as KittyBase
202
+ end
203
+ ```
204
+
205
+ ### Model.layout
206
+
207
+ Use `layout` to set the `:layout` part of API URLs, e.g.:
208
+
209
+ ```ruby
210
+ class Kitty < FmRest::Spyke::Base
211
+ layout "FluffyKitty" # uri path will be "layouts/FluffyKitty/records(/:id)"
212
+ end
213
+ ```
214
+
215
+ This is much preferred over using Spyke's `uri` to set custom URLs for your
216
+ Data API models.
217
+
218
+ Note that you only need to set this if the name of the model and the name of
219
+ the layout differ, otherwise the default will just work.
220
+
221
+ ### Mapped Model.attributes
222
+
223
+ Spyke allows you to define your model's attributes using `attributes`, however
224
+ sometimes FileMaker's field names aren't very Ruby-ORM-friendly, especially
225
+ since they may sometimes contain spaces and other special characters, so
226
+ fmrest-ruby extends `attributes`' functionality to allow you to map
227
+ Ruby-friendly attribute names to FileMaker field names. E.g.:
228
+
229
+ ```ruby
230
+ class Kitty < FmRest::Spyke::Base
231
+ attributes first_name: "First Name", last_name: "Last Name"
232
+ end
233
+ ```
234
+
235
+ You can then simply use the pretty attribute names whenever working with your
236
+ model and they will get mapped to their FileMaker fields:
237
+
238
+ ```ruby
239
+ kitty = Kitty.find(1)
240
+
241
+ kitty.first_name # => "Mr."
242
+ kitty.last_name # => "Fluffers"
243
+
244
+ kitty.first_name = "Dr."
245
+
246
+ kitty.attributes # => { "First Name": "Dr.", "Last Name": "Fluffers" }
247
+ ```
248
+
249
+ ### Model.has_portal
250
+
251
+ You can define portal associations on your model as such:
252
+
253
+ ```ruby
254
+ class Kitty < FmRest::Spyke::Base
255
+ has_portal :wool_yarns
256
+ end
257
+
258
+ class WoolYarn < FmRest::Spyke::Base
259
+ attributes :color, :thickness
260
+ end
261
+ ```
262
+
263
+ In this case fmrest-ruby will expect the portal table name and portal object
264
+ name to be both "wool_yarns". E.g., the expected portal JSON portion should be
265
+ look like this:
266
+
267
+ ```json
268
+ ...
269
+ "portalData": {
270
+ "wool_yarns": [
271
+ {
272
+ "wool_yarns::color": "yellow",
273
+ "wool_yarns::thickness": "thick",
274
+ }
275
+ ]
276
+ }
277
+ ```
278
+
279
+ If you need to specify different values for them you can do so with
280
+ `portal_key` for the portal table name, and `attribute_prefix` for the portal
281
+ object name, e.g.:
282
+
283
+ ```ruby
284
+ class Kitty < FmRest::Spyke::Base
285
+ has_portal :wool_yarns, portal_key: "Wool Yarn", attribute_prefix: "WoolYarn"
286
+ end
287
+ ```
288
+
289
+ The above expects the following portal JSON portion:
290
+
291
+ ```json
292
+ ...
293
+ "portalData": {
294
+ "Wool Yarn": [
295
+ {
296
+ "WoolYarn::color": "yellow",
297
+ "WoolYarn::thickness": "thick",
298
+ }
299
+ ]
300
+ }
301
+ ```
302
+
303
+ You can also specify a different class name with the `class_name` option:
304
+
305
+ ```ruby
306
+ class Kitty < FmRest::Spyke::Base
307
+ has_portal :wool_yarns, class_name: "FancyWoolYarn"
308
+ end
309
+ ```
310
+
311
+ ### Dirty attributes
312
+
313
+ fmrest-ruby includes support for ActiveModel's Dirty mixin out of the box,
314
+ providing methods like:
315
+
316
+ ```ruby
317
+ kitty = Kitty.new
318
+
319
+ kitty.changed? # => false
320
+
321
+ kitty.name = "Mr. Fluffers"
322
+
323
+ kitty.changed? # => true
324
+
325
+ kitty.name_changed? # => true
326
+ ```
327
+
328
+ fmrest-ruby uses the Dirty functionality to only send changed attributes back
329
+ to the server on save.
330
+
331
+ You can read more about [ActiveModel's Dirty in Rails
332
+ Guides](https://guides.rubyonrails.org/active_model_basics.html#dirty).
333
+
334
+ ### Query API
335
+
336
+ Since Spyke is API-agnostic it only provides a wide-purpose `.where` method for
337
+ passing arbitrary parameters to the REST backend. fmrest-ruby however is well
338
+ aware of its backend API, so it extends Spkye models with a bunch of useful
339
+ querying methods.
340
+
341
+ ```ruby
342
+ class Kitty < Spyke::Base
343
+ include FmRest::Spyke
344
+
345
+ attributes name: "CatName", age: "CatAge"
346
+
347
+ has_portal :toys, portal_key: "CatToys"
348
+ end
349
+ ```
350
+
351
+ `.limit` sets the limit for get and find request:
352
+
353
+ ```ruby
354
+ Kitty.limit(10)
355
+ ```
356
+
357
+ `.offset` sets the offset for get and find requests:
358
+
359
+ ```ruby
360
+ Kitty.offset(10)
361
+ ```
362
+
363
+ `.sort` (or `.order`) sets sorting options for get and find requests:
364
+
365
+ ```ruby
366
+ Kitty.sort(:name, :age)
367
+ Kitty.order(:name, :age) # alias method
368
+ ```
369
+
370
+ You can set descending sort order by appending either `!` or `__desc` to a sort
371
+ attribute (defaults to ascending order):
372
+
373
+ ```ruby
374
+ Kitty.sort(:name, :age!)
375
+ Kitty.sort(:name, :age__desc)
376
+ ```
377
+
378
+ `.portal` (or `.includes`) sets the portals to fetch for get and find requests
379
+ (this recognizes portals defined with `has_portal`):
380
+
381
+ ```ruby
382
+ Kitty.portal(:toys)
383
+ Kitty.includes(:toys) # alias method
384
+ ```
385
+
386
+ `.query` sets query conditions for a find request (and supports attributes as
387
+ defined with `attributes`):
388
+
389
+ ```ruby
390
+ Kitty.query(name: "Mr. Fluffers")
391
+ # JSON -> {"query": [{"CatName": "Mr. Fluffers"}]}
392
+ ```
393
+
394
+ Passing multiple attributes to `.query` will group them in the same JSON object:
395
+
396
+ ```ruby
397
+ Kitty.query(name: "Mr. Fluffers", age: 4)
398
+ # JSON -> {"query": [{"CatName": "Foo", "CatAge": 4}]}
399
+ ```
400
+
401
+ Calling `.query` multiple times or passing it multiple hashes creates separate
402
+ JSON objects (so you can define OR queries):
403
+
404
+ ```ruby
405
+ Kitty.query(name: "Mr. Fluffers").query(name: "Coronel Chai Latte")
406
+ Kitty.query({ name: "Mr. Fluffers" }, { name: "Coronel Chai Latte" })
407
+ # JSON -> {"query": [{"CatName": "Mr. Fluffers"}, {"CatName": "Coronel Chai Latte"}]}
408
+ ```
409
+
410
+ `.omit` works like `.query` but excludes matches:
411
+
412
+ ```ruby
413
+ Kitty.omit(name: "Captain Whiskers")
414
+ # JSON -> {"query": [{"CatName": "Captain Whiskers", "omit": "true"}]}
415
+ ```
416
+
417
+ You can get the same effect by passing `omit: true` to `.query`:
418
+
419
+ ```ruby
420
+ Kitty.query(name: "Captain Whiskers", omit: true)
421
+ # JSON -> {"query": [{"CatName": "Captain Whiskers", "omit": "true"}]}
422
+ ```
423
+
424
+ You can chain all query methods together:
425
+
426
+ ```ruby
427
+ Kitty.limit(10).offset(20).sort(:name, :age!).portal(:toys).query(name: "Mr. Fluffers")
428
+ ```
429
+
430
+ You can also set default values for limit and sort on the class:
431
+
432
+ ```ruby
433
+ Kitty.default_limit = 1000
434
+ Kitty.default_sort = [:name, :age!]
435
+ ```
436
+
437
+ Calling any `Enumerable` method on the resulting scope object will trigger a
438
+ server request, so you can treat the scope as a collection:
439
+
440
+ ```ruby
441
+ Kitty.limit(10).sort(:name).each { |kitty| ... }
442
+ ```
443
+
444
+ If you want to explicitly run the request instead you can use `.find_some` on
445
+ the scope object:
446
+
447
+ ```ruby
448
+ Kitty.limit(10).sort(:name).find_some # => [<Kitty...>, ...]
449
+ ```
450
+
451
+ If you want just a single result you can use `.find_one` instead (this will
452
+ force `.limit(1)`):
453
+
454
+ ```ruby
455
+ Kitty.query(name: "Mr. Fluffers").find_one # => <Kitty...>
456
+ ```
457
+
458
+ NOTE: If you know the id of the record you should use `.find(id)` instead of
459
+ `.query(id: id).find_one` (so that the request is sent as `GET ../:layout/records/:id`
460
+ instead of `POST ../:layout/_find`).
461
+
462
+ ```ruby
463
+ Kitty.find(89) # => <Kitty...>
464
+ ```
465
+
466
+ ## Logging
467
+
468
+ If using fmrest-ruby + Spyke in a Rails app pretty log output will be set up
469
+ for you automatically by Spyke (see [their
470
+ README](https://github.com/balvig/spyke#log-output)).
471
+
472
+ You can also enable simple STDOUT logging (useful for debugging) by passing
473
+ `log: true` in the options hash for either `FmRest.config=` or your models'
474
+ `fmrest_config=`, e.g.:
475
+
476
+ ```ruby
477
+ FmRest.config = {
478
+ host: "example.com",
479
+ database: "My Database",
480
+ username: "z3r0c00l",
481
+ password: "abc123",
482
+ log: true
483
+ }
484
+
485
+ # Or in your model
486
+ class LoggyKitty < FmRest::Spyke::Base
487
+ self.fmrest_config = {
488
+ host: "example.com",
489
+ database: "My Database",
490
+ username: "z3r0c00l",
491
+ password: "abc123",
492
+ log: true
493
+ }
494
+ end
495
+ ```
496
+
497
+ Note that the log option set in `FmRest.config` is ignored by models.
498
+
499
+ If you need to set up more complex logging for your models can use the
500
+ `faraday` block inside your class to inject your own logger middleware into the
501
+ Faraday connection, e.g.:
502
+
503
+ ```ruby
504
+ class LoggyKitty < FmRest::Spyke::Base
505
+ faraday do |conn|
506
+ conn.response :logger, MyApp.logger, bodies: true
507
+ end
508
+ end
509
+ ```
510
+
511
+ ## TODO
512
+
513
+ - [ ] Better/simpler-to-use core Ruby API
514
+ - [ ] Better API documentation and README
515
+ - [ ] Oauth support
516
+ - [ ] Support for portal limit and offset
517
+ - [ ] More options for token storage
518
+ - [x] Optional logging
519
+ - [x] FmRest::Spyke::Base class for single inheritance (as alternative for mixin)
520
+ - [x] Specs
521
+ - [x] Support for portal data
522
+
523
+ ## Development
524
+
525
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
526
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
527
+ prompt that will allow you to experiment (it will auto-load all fixtures in
528
+ spec/fixtures).
529
+
530
+ To install this gem onto your local machine, run `bundle exec rake install`. To
531
+ release a new version, update the version number in `version.rb`, and then run
532
+ `bundle exec rake release`, which will create a git tag for the version, push
533
+ git commits and tags, and push the `.gem` file to
534
+ [rubygems.org](https://rubygems.org).
535
+
536
+ ## Contributing
537
+
538
+ Bug reports and pull requests are welcome. This project is intended to be a
539
+ safe, welcoming space for collaboration, and contributors are expected to
540
+ adhere to the [Contributor Covenant](http://contributor-covenant.org) code of
541
+ conduct.
542
+
543
+ ## License
544
+
545
+ The gem is available as open source under the terms of the
546
+ [MIT License](https://opensource.org/licenses/MIT).
547
+ See [LICENSE.txt](LICENSE.txt).
548
+
549
+ ## Disclaimer
550
+
551
+ This project is not sponsored by or otherwise affiliated with FileMaker, Inc,
552
+ an Apple subsidiary. FileMaker is a trademark of FileMaker, Inc., registered in
553
+ the U.S. and other countries.
554
+
555
+ ## Code of Conduct
556
+
557
+ Everyone interacting in the fmrest-ruby project’s codebases, issue trackers,
558
+ chat rooms and mailing lists is expected to follow the [code of
559
+ conduct](CODE_OF_CONDUCT.md).