munson 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 58f61fc4c3adf530a74a67fe73b0c1907e097a3a
4
- data.tar.gz: c0dfb862271eee803921d1a9772514de40f8d669
3
+ metadata.gz: 123416f906ed71b0bdc64d573de72e080c3e96ca
4
+ data.tar.gz: 2b29a00a7dc9417caa47588af57f05fe448d99a7
5
5
  SHA512:
6
- metadata.gz: 59c16ff0e3445ebdc0f9adc4b422537714e0767a0a780533f2b682a08ce1ce2de0cf3af0cb88672c2b2d7fa96dc7a781a42692665f9e832033480f90fbbcf0ec
7
- data.tar.gz: fae8f69311ed2cbec3efc7397c8c2c8c01165b0c493b77e4f4c80805c07aee9b0fb798cbbf8dee8b2d06af3dcf70dd803bd4f74323081460ead7e294f9b4ea4c
6
+ metadata.gz: 53729cc19c386163266f1ee7a13bf4a508f76c757d465410739076525b9cc0b9030710b057e0d198bcb358a74a7e939803fa6e1541acaf6df10a58fb46f2a0d8
7
+ data.tar.gz: 3cf86622c38ee8673daf552033f0aac2cff89a1e40ddd3f6c122bcae58e60f7c947592c6348848e24d3634fcda3f0a848978cc45b3d2d9e334e71eda6dc07226
data/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  [![Code Climate](https://codeclimate.com/github/coryodaniel/munson/badges/gpa.svg)](https://codeclimate.com/github/coryodaniel/munson)
4
4
  [![Test Coverage](https://codeclimate.com/github/coryodaniel/munson/badges/coverage.svg)](https://codeclimate.com/github/coryodaniel/munson/coverage)
5
- ![Build Status](https://travis-ci.org/coryodaniel/munson.svg?branch=master)
5
+ ![Build Status](https://travis-ci.org/stacksocial/munson.svg?branch=master)
6
6
 
7
- A JSON API Spec client for Ruby
7
+ A JSON API client for Ruby
8
8
 
9
9
  ## Installation
10
10
 
@@ -22,116 +22,103 @@ Or install it yourself as:
22
22
 
23
23
  $ gem install munson
24
24
 
25
- ## Usage
26
-
27
- ### Munson::Connection and configuring the default connection
28
-
29
- Munson is designed to support multiple connections or API endpoints. A connection is a wrapper around Faraday::Connection that includes a few pieces of middleware for parsing and encoding requests and responses to JSON API Spec.
25
+ ## Basic Usage
30
26
 
31
27
  ```ruby
32
- Munson.configure(url: 'http://api.example.com') do |c|
33
- c.use MyCustomMiddleware
34
- end
35
- ```
36
-
37
- Options can be any [Faraday::Connection options](https://github.com/lostisland/faraday/blob/master/lib/faraday/connection.rb Faraday::Connection)
28
+ class Article < Munson::Resource
29
+ # This is done automatically if the tableize method is present
30
+ self.type = :articles
38
31
 
39
- Additional connections can be created with:
40
- ```ruby
41
- my_connection = Munson::Connection.new(url: 'http://api2.example.com') do |c|
42
- c.use MoreMiddleware
43
- c.use AllTheMiddlewares
32
+ # how to process the JSON API ID. JSON API always uses strings, but Munson defaults to :integer
33
+ key_type :integer, #:string, ->(id){ }
34
+ attribute :title, :string
44
35
  end
45
36
  ```
46
37
 
47
- ### Munson::Agent
38
+ ### Registering the JSONAPI 'type'
48
39
 
49
- Munson::Agent provides a small 'DSL' to build requests and parse responses,
50
- while allowing additional configuration for a particular 'resource.'
40
+ Calling ```Article.type = :articles``` registers the class ```Article``` as the handler for JSON API resources of the type ```articles```.
51
41
 
42
+ When the ActiveSupport method ```tableize``` is present, this will be set automatically. A class can be bound to multiple types:
52
43
 
53
44
  ```ruby
54
- Munson.configure url: 'http://api.example.com'
55
-
56
- class Product
57
- def self.munson
58
- return @munson if @munson
59
- @munson = Munson::Agent.new(
60
- connection: Munson.default_connection, # || Munson::Connection.new(...)
61
- paginator: :offset,
62
- type: 'products'
63
- )
64
- end
65
- end
45
+ Article.type = :articles
46
+ Munson.register_type(:posts, Article)
66
47
  ```
67
48
 
68
- #### Getting the faraday response
49
+ ### Querying
69
50
  ```ruby
70
- query = Product.munson.filter(min_price: 30, max_price: 65)
71
- # its chainable
72
- query.filter(category: 'Hats').filter(size: ['small', 'medium'])
51
+ articles = Article.fetch # Get some articles
52
+ article = Article.find(9) # Find an article
73
53
 
74
- query.to_params
75
- #=> {:filter=>{:min_price=>"30", :max_price=>"65", :category=>"Hats", :size=>"small,medium"}}
54
+ query = Article.fields(:title).include(:author, :comments).sort(id: :desc).filter(published: true)
55
+ query.to_params #=> {:filter=>{:published=>"true"}, :fields=>{:articles=>"title"}, :include=>"author,comments", :sort=>"-id"}
56
+ query.to_query_string #=> "fields[articles]=title&filter[published]=true&include=author,comments&sort=-id"
76
57
 
77
- Product.munson.get(params: query.to_params)
58
+ query.fetch # Fetch articles w/ the given query string
78
59
  ```
79
60
 
61
+ The Munson::Resource delegates a few methods to its underlying Munson::Connection:
62
+
80
63
  #### Filtering
81
64
 
82
65
  ```ruby
83
- query = Product.munson.filter(min_price: 30, max_price: 65)
66
+ query = Product.filter(min_price: 30, max_price: 65)
67
+
84
68
  # its chainable
85
69
  query.filter(category: 'Hats').filter(size: ['small', 'medium'])
86
70
 
87
71
  query.to_params
88
72
  #=> {:filter=>{:min_price=>"30", :max_price=>"65", :category=>"Hats", :size=>"small,medium"}}
89
73
 
90
- query.fetch #=> Some lovely data
74
+ query.fetch #=> Munson::Collection<Product,Product>
91
75
  ```
92
76
 
93
77
  #### Sorting
94
78
 
95
79
  ```ruby
96
- query = Product.munson.sort(created_at: :desc)
80
+ query = Product.sort(created_at: :desc)
81
+
97
82
  # its chainable
98
83
  query.sort(:price) # defaults to ASC
99
84
 
100
85
  query.to_params
101
86
  #=> {:sort=>"-created_at,price"}
102
87
 
103
- query.fetch #=> Some lovely data
88
+ query.fetch #=> Munson::Collection<Product,Product>
104
89
  ```
105
90
 
106
91
  #### Including (Side loading related resources)
107
92
 
108
93
  ```ruby
109
- query = Product.munson.includes(:manufacturer)
94
+ query = Product.include(:manufacturer)
95
+
110
96
  # its chainable
111
- query.includes(:vendor)
97
+ query.include(:vendor)
112
98
 
113
99
  query.to_params
114
100
  #=> {:include=>"manufacturer,vendor"}
115
101
 
116
- query.fetch #=> Some lovely data
102
+ query.fetch #=> Munson::Collection<Product,Product>
117
103
  ```
118
104
 
119
105
  #### Sparse Fieldsets
120
106
 
121
107
  ```ruby
122
- query = Product.munson.fields(products: [:name, :price])
108
+ query = Product.fields(products: [:name, :price])
109
+
123
110
  # its chainable
124
- query.includes(:manufacturer).fields(manufacturer: [:name])
111
+ query.include(:manufacturer).fields(manufacturer: [:name])
125
112
 
126
113
  query.to_params
127
114
  #=> {:fields=>{:products=>"name,price", :manufacturer=>"name"}, :include=>"manufacturer"}
128
115
 
129
- query.fetch #=> Some lovely data
116
+ query.fetch #=> Munson::Collection<Product,Product>
130
117
  ```
131
118
 
132
119
  #### All the things!
133
120
  ```ruby
134
- query = Product.munson.
121
+ query = Product.
135
122
  filter(min_price: 30, max_price: 65).
136
123
  includes(:manufacturer).
137
124
  sort(popularity: :desc, price: :asc).
@@ -139,228 +126,264 @@ query = Product.munson.
139
126
  page(number: 1, limit: 100)
140
127
 
141
128
  query.to_params
129
+
142
130
  #=> {:filter=>{:min_price=>"30", :max_price=>"65"}, :fields=>{:product=>"name,price", :manufacturer=>"name,website"}, :include=>"manufacturer", :sort=>"-popularity,price", :page=>{:limit=>10}}
143
131
 
144
- query.fetch #=> Some lovely data
132
+ query.fetch #=> Munson::Collection<Product,Product>
145
133
  ```
146
134
 
147
135
  #### Fetching a single resource
148
136
 
149
137
  ```ruby
150
- Product.munson.find(1)
138
+ Product.find(1) #=> product
151
139
  ```
152
140
 
153
- #### Paginating
141
+ ### Accessing Munson internals
142
+ Every Munson::Resource has an internally managed client. It is accessible via ```.munson```
154
143
 
155
- A paged and offset paginator are included with Munson.
156
-
157
- Using the ```offset``` paginator
158
144
  ```ruby
159
- class Product
160
- def self.munson
161
- return @munson if @munson
162
- @munson = Munson::Agent.new(
163
- paginator: :offset,
164
- type: 'products'
165
- )
166
- end
167
- end
168
-
169
- query = Product.munson.includes('manufacturer').page(offset: 10, limit: 25)
170
- query.to_params
171
- # => {:include=>"manufacturer", :page=>{:limit=>10, :offset=>10}}
172
-
173
- query.fetch #=> Some lovely data
145
+ Article.munson #=> Munson::Client
146
+ Article.munson.path #=> base path to use for this resource. Defaults to "/" + type; i.e., "/articles"
147
+ Article.munson.agent #=> Munson::Agent: the agent wraps the Munson::Connection. It performs the low level GET/POST/PUT/PATCH/DELETE methods
148
+ Article.munson.query #=> Munson::Query: a chainable query building instance
149
+ Article.munson.connection #=> Munson::Connection: Small wrapper around the Farady connection
150
+ Article.munson.connection.response_key_format #=> :dasherize, :camelize, nil
151
+ Article.munson.connection.url #=> This endpoints base URL http://api.example.com/
152
+ Article.munson.connection.faraday #=> The faraday object for this connection
153
+ Article.muson.connection = SomeNewConnectionYouPrefer
154
+ Article.munson.connection.configure(opts) do { |faraday_conn| } #=> Feel free to reconfigure me ;D
174
155
  ```
175
156
 
176
- Using the ```paged``` paginator
157
+ ### Persistence Resources
177
158
  ```ruby
178
- class Product
179
- def self.munson
180
- return @munson if @munson
181
- @munson = Munson::Agent.new(
182
- paginator: :paged,
183
- type: 'products'
184
- )
185
- end
159
+ class Article < Munson::Resource
160
+ attribute :title, :string
161
+ attribute :body, :string
162
+ attribute :created_at, :time
186
163
  end
164
+ ```
187
165
 
188
- query = Product.munson.includes('manufacturer').page(page: 10, size: 25)
189
- query.to_params
190
- # => {:include=>"manufacturer", :page=>{:page=>10, :size=>10}}
166
+ Creating a new resource
191
167
 
192
- query.fetch #=> Some lovely data
168
+ ```ruby
169
+ article = Article.new
170
+ article.title = "This is a great read!"
171
+ article.save #=> Boolean: Will attempt to POST to /articles
172
+ article.errors?
173
+ article.errors #=> Array of errors
193
174
  ```
194
175
 
195
- ##### Custom paginators
196
- Since the JSON API Spec does not dictate [how to paginate](http://jsonapi.org/format/#fetching-pagination), Munson has been designed to make adding custom paginators pretty easy.
176
+ Updating a resource
197
177
 
198
178
  ```ruby
199
- class CustomPaginator
200
- # @param [Hash] Hash of options like max/default page size
201
- def initialize(opts={})
202
- end
179
+ article = Article.find(9)
180
+ article.title = "This is a great read!"
181
+ article.save #=> Boolean: Will attempt to PATCH to /articles
182
+ article.errors?
183
+ article.errors #=> Array of errors
184
+ ```
203
185
 
204
- # @param [Hash] Hash to set the 'limit' and 'offset' to be returned later by #to_params
205
- def set(params={})
206
- end
186
+ ### Accessing Side Loaded Resources
207
187
 
208
- # @return [Hash] Params to be merged into query builder.
209
- def to_params
210
- { page: {} }
211
- end
212
- end
188
+ Given the following relationship:
213
189
 
214
- ```
190
+ ```ruby
191
+ class Article < Munson::Resource
192
+ self.type = :articles
193
+ has_one :author
194
+ has_many :comments
215
195
 
216
- ### Munson::Resource
196
+ key_type :integer
197
+ attribute :title, :string
198
+ end
217
199
 
218
- A munson resource provides a DSL in the including class for doing common JSON API queries on your ruby class.
200
+ class Person < Munson::Resource
201
+ self.type = :people
202
+ has_many :articles
219
203
 
220
- It delegates a set of methods so that they dont have to be accessed through the ```munson``` class method and sets a few options based on the including class name.
204
+ attribute :first_name, String
205
+ attribute :last_name, :string
206
+ attribute :twitter, :string
207
+ attribute :created_at, :time, default: ->{ Time.now }, serialize: ->(val){ val.to_s }
208
+ attribute :post_count, :integer
209
+ end
221
210
 
222
- It also will alter the response objects coming from #fetch and #find. Instead of returning a json hash like
223
- when using the bare Munson::Agent, Munson::Resource will pass the JSON Spec attributes and the ID as a hash into your class's initializer.
211
+ class Comment < Munson::Resource
212
+ self.type = :comments
213
+ has_one :author
224
214
 
225
- ```ruby
226
- class Product
227
- include Munson::Resource
228
- register_munson_type :products
215
+ attribute :body, ->(val){ val.to_s }
216
+ attribute :score, :float
217
+ attribute :created_at, :time
218
+ attribute :is_spam, :boolean
219
+ attribute :mentions, :string, array: true
229
220
  end
230
-
231
- # Munson method is there, should you be looking for it.
232
- Product.munson #=> Munson::Agent
233
221
  ```
234
222
 
235
- **Setting the type**
223
+ **Note:** When specifying relationships in Munson, you are specifying the JSON API type name. You'll notice below that when ```.author``` is called it returns a person object. That it is because in the HTTP response, the relationship name is ```author``` but the resource type is ```people```.
224
+
225
+ ```json
226
+ {
227
+ "data": [{
228
+ "type": "articles",
229
+ "id": "1",
230
+ "attributes": {
231
+ "title": "JSON API paints my bikeshed!"
232
+ },
233
+ "relationships": {
234
+ "author": {
235
+ "links": {
236
+ "self": "http://example.com/articles/1/relationships/author",
237
+ "related": "http://example.com/articles/1/author"
238
+ },
239
+ "data": { "type": "people", "id": "9" }
240
+ }
241
+ }
242
+ }]
243
+ }
244
+ ```
236
245
 
237
- This will cause Munson to return a hash instead of a class instance (Product).
246
+ Munson initializes objects for side loaded resources. Only 1 HTTP call is made.
238
247
 
239
248
  ```ruby
240
- class Product
241
- include Munson::Resource
242
- munson.type = :products
243
- end
249
+ article = Article.include(:author, :comments).find(9)
250
+ article.author #=> Person object
251
+ article.comments #=> Munson::Collection<Comment>
252
+
253
+ article.author.first_name #=> Chauncy
244
254
  ```
245
255
 
246
- There are two ways to set the JSON API type when using a Munson::Resource
247
256
 
248
- **Registering the type**
249
257
 
250
- This will cause munson to return your model's datatype. Munson will register this in its type map dictionary and use the class to initialize a model
258
+ ## Configuration
259
+
260
+ Munson is designed to support multiple connections or API endpoints. A connection is a wrapper around Faraday::Connection that includes a few pieces of middleware for parsing and encoding requests and responses to JSON API Spec.
261
+
262
+ Setting the default connection:
251
263
 
252
264
  ```ruby
253
- class Product
254
- include Munson::Resource
255
- register_munson_type :products
265
+ Munson.configure(url: 'http://api.example.com') do |c|
266
+ c.use MyCustomMiddleware
267
+ c.use AllTheMiddlewares
256
268
  end
257
269
  ```
258
270
 
259
- #### Filtering
271
+ Each Munson::Resource has its own Munson::Client. The client *copies* the default connection so its easy to set general configuration options, and overwrite them on a resource by resource basis.
260
272
 
261
273
  ```ruby
262
- query = Product.filter(min_price: 30, max_price: 65)
263
- # its chainable
264
- query.filter(category: 'Hats').filter(size: ['small', 'medium'])
274
+ Munson.configure(url: 'http://api.example.com', response_key_format: :dasherize)
265
275
 
266
- query.to_params
267
- #=> {:filter=>{:min_price=>"30", :max_price=>"65", :category=>"Hats", :size=>"small,medium"}}
276
+ class Kitten < Munson::Resource
277
+ munson.url = "http://api.differentsite.com"
278
+ end
268
279
 
269
- query.fetch #=> Munson::Collection<Product,Product>
280
+ # Overwritten URL
281
+ Kitten.munson.connection.url #=> "http://api.differentsite.com"
282
+ # Copied key format
283
+ Kitten.munson.connection.response_key_format #=> :dasherize
284
+
285
+ Munson.default_connection.url #=> "http://api.example.com"
286
+ Munson.default_connection.response_key_format #=> :dasherize
270
287
  ```
271
288
 
272
- #### Sorting
289
+ ### Configuration Options
273
290
 
274
291
  ```ruby
275
- query = Product.sort(created_at: :desc)
276
- # its chainable
277
- query.sort(:price) # defaults to ASC
292
+ Munson.configure(url: 'http://api.example.com', response_key_format: :dasherize) do |conn|
293
+ conn.use SomeCoolFaradayMiddleware
294
+ end
295
+ ```
278
296
 
279
- query.to_params
280
- #=> {:sort=>"-created_at,price"}
297
+ Two special options can be passed into ```.configure```:
298
+ * ```url``` the base url for this endpoint
299
+ * ```response_key_format``` the format of the JSONAPI response keys. Valid values are: ```:dasherize```, ```:camelize```, ```nil```
281
300
 
282
- query.fetch #=> Munson::Collection<Product,Product>
283
- ```
301
+ Additinally any Faraday Connection options can be passed. [Faraday::Connection options](https://github.com/lostisland/faraday/blob/master/lib/faraday/connection.rb Faraday::Connection)
284
302
 
285
- #### Including (Side loading related resources)
286
303
 
287
- ```ruby
288
- query = Product.includes(:manufacturer)
289
- # its chainable
290
- query.includes(:vendor)
304
+ ## Advanced Usage
291
305
 
292
- query.to_params
293
- #=> {:include=>"manufacturer,vendor"}
306
+ ### Custom Query Builder
294
307
 
295
- query.fetch #=> Munson::Collection<Product,Product>
296
- ```
308
+ Since the filter param's format isn't specified in the [spec](http://jsonapi.org/format/#fetching-filtering)
309
+ this implementation uses (JSONAPI::Resource's implementation](https://github.com/cerebris/jsonapi-resources#filters)
297
310
 
298
- #### Sparse Fieldsets
311
+ To override, implement your own custom query builder inheriting from {Munson::Query}
312
+ {Munson::Client} takes a Query class to use. This method could be overwritten in your Resource
299
313
 
300
314
  ```ruby
301
- query = Product.fields(products: [:name, :price])
302
- # its chainable
303
- query.includes(:manufacturer).fields(manufacturer: [:name])
304
-
305
- query.to_params
306
- #=> {:fields=>{:products=>"name,price", :manufacturer=>"name"}, :include=>"manufacturer"}
315
+ class MyBuilder < Munson::Query
316
+ def filter_to_query_value
317
+ # ... your fancier logic
318
+ end
319
+ end
307
320
 
308
- query.fetch #=> Munson::Collection<Product,Product>
321
+ Article.munson.query_builder = MyBuilder
309
322
  ```
310
323
 
311
- #### All the things!
324
+ ### Without inheriting from Munson::Resource
325
+
326
+ If for some reason you cannot inherit from Munson::Resource, you can still get a lot of JSONAPI parsing functionality
327
+
312
328
  ```ruby
313
- query = Product.
314
- filter(min_price: 30, max_price: 65).
315
- includes(:manufacturer).
316
- sort(popularity: :desc, price: :asc).
317
- fields(product: ['name', 'price'], manufacturer: ['name', 'website']).
318
- page(number: 1, limit: 100)
329
+ class Album
330
+ # Just some attr accessors, NBD
331
+ attr_accessor :id
332
+ attr_accessor :title
319
333
 
320
- query.to_params
321
- #=> {:filter=>{:min_price=>"30", :max_price=>"65"}, :fields=>{:product=>"name,price", :manufacturer=>"name,website"}, :include=>"manufacturer", :sort=>"-popularity,price", :page=>{:limit=>10}}
334
+ # Give Album a client to use
335
+ def self.munson
336
+ return @munson if @munson
337
+ @munson = Munson::Client.new
338
+ end
322
339
 
323
- query.fetch #=> Munson::Collection<Product,Product>
324
- ```
340
+ # Set the type, note, this is not being set on self
341
+ munson.type = :albums
325
342
 
326
- #### Fetching a single resource
343
+ # Register the type w/ munson
344
+ Munson.register_type(munson.type, self)
345
+
346
+ # When you aren't inherited from Munson::Resource, Munson will pass a Munson::Document to a static method called munson_initializer for you to initialze your record as you wish
347
+ def self.munson_initializer(document)
348
+ new(document.id, document.attributes[:title])
349
+ end
350
+
351
+ def initialize(id, title)
352
+ @id = id
353
+ @title = title
354
+ end
355
+ end
356
+ ```
327
357
 
328
358
  ```ruby
329
- Product.find(1) #=> product
359
+ albums = Album.munson.include(:songs).fetch
360
+ albums.first.title #=> An album title!
330
361
  ```
331
362
 
332
- #### Paginating
363
+ ### Any ol' object (Register type, add munson_initializer)
364
+
365
+ As long as a class is registered with munson and it response to munson_initializer, Munson will be able to initialize the object with or without a client
333
366
 
334
- A paged and offset paginator are included with Munson.
367
+ Extending the example above...
335
368
 
336
- Using the ```offset``` paginator
337
369
  ```ruby
338
- class Product
339
- include Munson::Resource
340
- munson.paginator = :offset
341
- munson.paginator_options = {default: 10, max: 100}
342
- end
370
+ class Song
371
+ attr_reader :name
372
+ def self.munson_initializer(document)
373
+ new(document.attributes[:name])
374
+ end
343
375
 
344
- query = Product.includes('manufacturer').page(offset: 10, limit: 25)
345
- query.to_params
346
- # => {:include=>"manufacturer", :page=>{:limit=>10, :offset=>10}}
376
+ def initialize(name)
377
+ @name = name
378
+ end
379
+ end
347
380
 
348
- query.fetch #=> Munson::Collection<Product,Product>
381
+ Munson.register_type :songs, Song
349
382
  ```
350
383
 
351
- Using the ```paged``` paginator
352
384
  ```ruby
353
- class Product
354
- include Munson::Resource
355
- munson.paginator = :paged
356
- munson.paginator_options = {default: 10, max: 100}
357
- end
358
-
359
- query = Product.includes('manufacturer').page(page: 10, size: 25)
360
- query.to_params
361
- # => {:include=>"manufacturer", :page=>{:page=>10, :size=>10}}
362
-
363
- query.fetch #=> Some lovely data
385
+ album = Album.munson.include(:songs).find(9)
386
+ album.songs #=> Munson::Collection<Song>
364
387
  ```
365
388
 
366
389
  ## Development
@@ -369,58 +392,23 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
369
392
 
370
393
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
371
394
 
372
- ## Contributing
373
-
374
- Bug reports and pull requests are welcome on GitHub at https://github.com/coryodaniel/munson.
375
-
376
- ### Munson::Model
377
- WIP see [usage](#usage)
378
-
379
- Finding related resources could set instance methods that mix/override behavior of the class level agent...
380
395
 
381
- /articles/1
382
- Article.find(1) uses Article.munson
383
-
384
- /articles/1/author
385
- article = Article.find(1) uses Article.munson
386
- article.author uses article.munson as a new connection that sets the base uri to /articles/1
396
+ ## Contributing
387
397
 
388
- ## Usage
389
- ```ruby
390
- address = Address.new
391
- address.state = "FL"
392
- address.save
393
- address.state = "CA"
394
- address.save
395
- # Mind mutex adding method accessors on... dangerous, see her, consider storing them in an @attributes hash...
396
- user = User.find(1)
397
- address = user.addresses.build
398
- address.save #posts on the relation
399
-
400
- address = Address.new({...})
401
- address = Address.new
402
- address.assign_attributes
403
- address.update_attributes
404
- address.dirty?
405
-
406
- Address.update(1, {}) #update without loading
407
- Address.destroy(1) #Destroy without loading
408
-
409
- address = Address.find(300)
410
- address.destroy
411
-
412
- Address.find(10)
413
- Address.filter(zip_code: 90210).find(10)
414
- Address.filter(zip_code: 90210).all
415
- Address.filter(zip_code: 90210).fetch
416
- Address.includes(:user, 'user.purchases').filter(active: true).all
417
- Address.includes(:user, 'user.purchases').find(10)
418
- Address.sort(city: :asc)
419
- Address.sort(city: :desc)
420
- Address.fields(:street1, :street2, {user: :name})
421
- Address.fields(:street1, :street2).fields(user: :name)
422
- addresses = Address.fields(:street1, :street2).fields(user: :name)
423
- addresses.first.shipped_products.filter(min_total: 300.00)
424
-
425
- Custom collection/member methods?
426
- ```
398
+ Bug reports and pull requests are welcome on GitHub at https://github.com/stacksocial/munson.
399
+
400
+
401
+ ## TODOS
402
+ * [ ] Update Yard docs :D
403
+ * [ ] A few pending tests :/
404
+ * [ ] Collection#next (queries for next page, if pagination present)
405
+ * [ ] Related Documents/Resources taking advantage of underlying resource[links]
406
+ * [ ] Resource should provide relationship information to the underlying document ?
407
+ * [ ] Error object to wrap an individual error
408
+ * [ ] consider enumerable protocol on a query
409
+ * [ ] Handle null/empty responses...
410
+ * [ ] munson/rails - magic up all the things
411
+ * [ ] auto set type based on pluralization (self.type = :foos)
412
+ * [ ] http://api.rubyonrails.org/classes/ActiveModel/Dirty.html ?
413
+ * [ ] Pluggable pagination (could it be a subclassed QueryBuilder? vs. a set of methods mixed into a query instance)
414
+ * [ ] Query#find([...]) find multiple records