fmrest 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +559 -0
- data/Rakefile +6 -0
- data/fmrest.gemspec +33 -0
- data/lib/fmrest.rb +13 -0
- data/lib/fmrest/spyke.rb +11 -0
- data/lib/fmrest/spyke/base.rb +15 -0
- data/lib/fmrest/spyke/json_parser.rb +143 -0
- data/lib/fmrest/spyke/model.rb +23 -0
- data/lib/fmrest/spyke/model/associations.rb +77 -0
- data/lib/fmrest/spyke/model/attributes.rb +198 -0
- data/lib/fmrest/spyke/model/connection.rb +53 -0
- data/lib/fmrest/spyke/model/orm.rb +81 -0
- data/lib/fmrest/spyke/model/uri.rb +28 -0
- data/lib/fmrest/spyke/portal.rb +53 -0
- data/lib/fmrest/spyke/relation.rb +140 -0
- data/lib/fmrest/v1.rb +54 -0
- data/lib/fmrest/v1/token_session.rb +91 -0
- data/lib/fmrest/v1/token_store.rb +6 -0
- data/lib/fmrest/v1/token_store/active_record.rb +73 -0
- data/lib/fmrest/v1/token_store/base.rb +14 -0
- data/lib/fmrest/v1/token_store/memory.rb +26 -0
- data/lib/fmrest/version.rb +3 -0
- metadata +211 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
@@ -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
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -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
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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).
|