her 0.5.5 → 0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +1 -1
  3. data/README.md +78 -63
  4. data/UPGRADE.md +21 -0
  5. data/lib/her/model.rb +2 -1
  6. data/lib/her/model/associations.rb +17 -54
  7. data/lib/her/model/associations/association.rb +46 -0
  8. data/lib/her/model/associations/belongs_to_association.rb +34 -0
  9. data/lib/her/model/associations/has_many_association.rb +43 -0
  10. data/lib/her/model/associations/has_one_association.rb +33 -0
  11. data/lib/her/model/attributes.rb +19 -19
  12. data/lib/her/model/base.rb +5 -0
  13. data/lib/her/model/http.rb +17 -21
  14. data/lib/her/model/orm.rb +11 -35
  15. data/lib/her/model/parse.rb +4 -12
  16. data/lib/her/model/paths.rb +3 -2
  17. data/lib/her/model/relation.rb +113 -0
  18. data/lib/her/version.rb +1 -1
  19. data/spec/model/associations_spec.rb +48 -4
  20. data/spec/model/introspection_spec.rb +1 -1
  21. data/spec/model/orm_spec.rb +21 -102
  22. data/spec/model/parse_spec.rb +36 -7
  23. data/spec/model/paths_spec.rb +3 -3
  24. data/spec/model/relation_spec.rb +89 -0
  25. data/spec/spec_helper.rb +1 -0
  26. data/spec/support/macros/her_macros.rb +17 -0
  27. data/spec/support/macros/request_macros.rb +19 -0
  28. metadata +13 -37
  29. data/examples/grape-and-her/.env.default +0 -3
  30. data/examples/grape-and-her/Procfile +0 -2
  31. data/examples/grape-and-her/README.md +0 -27
  32. data/examples/grape-and-her/api/Gemfile +0 -11
  33. data/examples/grape-and-her/api/Rakefile +0 -14
  34. data/examples/grape-and-her/api/app/api.rb +0 -49
  35. data/examples/grape-and-her/api/app/models/organization.rb +0 -7
  36. data/examples/grape-and-her/api/app/models/user.rb +0 -9
  37. data/examples/grape-and-her/api/app/views/organizations/_base.rabl +0 -2
  38. data/examples/grape-and-her/api/app/views/organizations/index.rabl +0 -3
  39. data/examples/grape-and-her/api/app/views/organizations/show.rabl +0 -3
  40. data/examples/grape-and-her/api/app/views/users/_base.rabl +0 -8
  41. data/examples/grape-and-her/api/app/views/users/index.rabl +0 -3
  42. data/examples/grape-and-her/api/app/views/users/show.rabl +0 -3
  43. data/examples/grape-and-her/api/config.ru +0 -5
  44. data/examples/grape-and-her/api/config/boot.rb +0 -17
  45. data/examples/grape-and-her/api/config/unicorn.rb +0 -7
  46. data/examples/grape-and-her/api/db/migrations/001_create_users.rb +0 -11
  47. data/examples/grape-and-her/api/db/migrations/002_create_organizations.rb +0 -8
  48. data/examples/grape-and-her/consumer/Gemfile +0 -23
  49. data/examples/grape-and-her/consumer/app/assets/stylesheets/application.scss +0 -190
  50. data/examples/grape-and-her/consumer/app/assets/stylesheets/reset.scss +0 -53
  51. data/examples/grape-and-her/consumer/app/consumer.rb +0 -74
  52. data/examples/grape-and-her/consumer/app/models/organization.rb +0 -13
  53. data/examples/grape-and-her/consumer/app/models/user.rb +0 -13
  54. data/examples/grape-and-her/consumer/app/views/index.haml +0 -9
  55. data/examples/grape-and-her/consumer/app/views/layout.haml +0 -20
  56. data/examples/grape-and-her/consumer/app/views/organizations/index.haml +0 -25
  57. data/examples/grape-and-her/consumer/app/views/organizations/show.haml +0 -11
  58. data/examples/grape-and-her/consumer/app/views/users/index.haml +0 -33
  59. data/examples/grape-and-her/consumer/app/views/users/show.haml +0 -9
  60. data/examples/grape-and-her/consumer/config.ru +0 -20
  61. data/examples/grape-and-her/consumer/config/boot.rb +0 -30
  62. data/examples/grape-and-her/consumer/config/unicorn.rb +0 -7
  63. data/examples/grape-and-her/consumer/lib/response_logger.rb +0 -18
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OWFlMWJkMGQ3ODVkOTdhZGVmNDM3MDE3OTJiYTIxMThjNDZkZDVhYw==
4
+ NWYxMjI2MTQ0YjdhOTYyNDA1YTkwZjU4MTNhMDFjZDQ1OTM0OTczMQ==
5
5
  data.tar.gz: !binary |-
6
- ODljYTk3MjhiNjhmYWM1MjQ1NDczZmJmNjIxYmMxNDA0NDk0ZDU0MQ==
6
+ ZDk0YzAxYjUzYTlmMGU4Y2FkMGQ0NGQ2MDM0YjM2MjBlZmRmMGVhZg==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NjlmZmY0MzUxZmZlZjY0MzRkODg3YmM0MzQ1YzI4MDdjOTE5NTM1YTc0NTcw
10
- OGZiYjgyMzA3YTlmMGRmMzAyNjRiMzQwZjQ3YjM1ODFmYTQzMDNkZmRmMzBk
11
- ZTRkNWUxZWM2Mzk4NmJlNTQ2YmU1YWQwZmRmNzIxZDFkYjk0NTM=
9
+ ZDE1MWExN2JkZDY5OGYwNWFkMGZhYTVhZDE1MzEzYjMxYjc3YTU3NDc0MDQ4
10
+ OWMyOTEwMzY3ZTE4OGIxMTNiODlhZDExZGNjMzVlMjYzMWY1ZWNmZGVlM2Qz
11
+ Yjk2ZWRkZDkxMGU0MmJlMmU2ZjU0ZGI3ODA3ZWU2NDUzNTcxZWQ=
12
12
  data.tar.gz: !binary |-
13
- ZmExYTE0MzIyODFjN2JiYzAxOGUxM2ZhMzIzNjRiYjc4MjVlYjQxMTBlMWU2
14
- ZmE4ZjE2ZDU2YzI0YmIyNjIxZGQ5M2I1MzJlMDU1NzkwNWFiMDk0NmRlN2Vh
15
- NDZkMWYxOTNiZDRkNmE0NThjOWFlZjNhZDc4OGMxZjE5NjY2NmI=
13
+ OTcxYzViZjM1MDVkMDJjODhlZTlkN2M3MTliYzRmZDE1NzQ4NDMzMDgzYzhk
14
+ NjNhMGIwMjUxNzFiMzA4Mjg2NmE3OTQzNWRhNWNiMDIyM2Q4MzVlMDk3OWM3
15
+ OTAwNTBlNWYxMmY1MWUwMTlkOWFlYTZkY2E1NDA3NGFkNDdjZjk=
data/.gitignore CHANGED
@@ -1,6 +1,6 @@
1
1
  *.gem
2
2
  .bundle
3
- Gemfile.lock
3
+ /Gemfile.lock
4
4
  pkg/*
5
5
  rake
6
6
  tmp
data/README.md CHANGED
@@ -1,4 +1,14 @@
1
- # Her [![Build Status](https://secure.travis-ci.org/remiprev/her.png?branch=master)](http://travis-ci.org/remiprev/her) [![Gem dependency status](https://gemnasium.com/remiprev/her.png?travis)](https://gemnasium.com/remiprev/her)
1
+ # Her
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/her.png)][gem]
4
+ [![Build Status](https://secure.travis-ci.org/remiprev/her.png?branch=master)][travis]
5
+ [![Dependency Status](https://gemnasium.com/remiprev/her.png?travis)][gemnasium]
6
+ [![Code Climate](https://codeclimate.com/github/remiprev/her.png)][codeclimate]
7
+
8
+ [gem]: https://rubygems.org/gems/her
9
+ [travis]: http://travis-ci.org/remiprev/her
10
+ [gemnasium]: https://gemnasium.com/remiprev/her
11
+ [codeclimate]: https://codeclimate.com/github/remiprev/her
2
12
 
3
13
  Her is an ORM (Object Relational Mapper) that maps REST resources to Ruby objects. It is designed to build applications that are powered by a RESTful API instead of a database.
4
14
 
@@ -18,7 +28,7 @@ First, you have to define which API your models will be bound to. For example, w
18
28
 
19
29
  ```ruby
20
30
  # config/initializers/her.rb
21
- Her::API.setup :url => "https://api.example.com" do |connection|
31
+ Her::API.setup url: "https://api.example.com" do |connection|
22
32
  connection.use Faraday::Request::UrlEncoded
23
33
  connection.use Her::Middleware::DefaultParseJSON
24
34
  connection.use Faraday::Adapter::NetHttp
@@ -42,10 +52,10 @@ User.all
42
52
  User.find(1)
43
53
  # GET https://api.example.com/users/1 and return a User object
44
54
 
45
- @user = User.create(:fullname => "Tobias Fünke")
55
+ @user = User.create(fullname: "Tobias Fünke")
46
56
  # POST "https://api.example.com/users" with the data and return a User object
47
57
 
48
- @user = User.new(:fullname => "Tobias Fünke")
58
+ @user = User.new(fullname: "Tobias Fünke")
49
59
  @user.occupation = "actor"
50
60
  @user.save
51
61
  # POST https://api.example.com/users with the data and return a User object
@@ -68,11 +78,11 @@ end
68
78
  # Update a fetched resource
69
79
  user = User.find(1)
70
80
  user.fullname = "Lindsay Fünke"
71
- # OR user.assign_attributes :fullname => "Lindsay Fünke"
81
+ # OR user.assign_attributes(fullname: "Lindsay Fünke")
72
82
  user.save
73
83
 
74
84
  # Update a resource without fetching it
75
- User.save_existing(1, :fullname => "Lindsay Fünke")
85
+ User.save_existing(1, fullname: "Lindsay Fünke")
76
86
 
77
87
  # Destroy a fetched resource
78
88
  user = User.find(1)
@@ -83,20 +93,21 @@ User.destroy_existing(1)
83
93
 
84
94
  # Fetching a collection of resources
85
95
  User.all
96
+ User.where(moderator: 1).all
86
97
 
87
98
  # Create a new resource
88
- User.create(:fullname => "Maeby Fünke")
99
+ User.create(fullname: "Maeby Fünke")
89
100
 
90
101
  # Save a new resource
91
- user = User.new(:fullname => "Maeby Fünke")
102
+ user = User.new(fullname: "Maeby Fünke")
92
103
  user.save
93
104
  ```
94
105
 
95
- You can look into the `examples` directory for a sample application using Her. For a complete reference of all the methods you can use, check out [the documentation](http://rdoc.info/github/remiprev/her).
106
+ You can look into the [`her-example`](https://github.com/remiprev/her-example) repository for a sample application using Her. For a complete reference of all the methods you can use, check out [the documentation](http://rdoc.info/github/remiprev/her).
96
107
 
97
108
  ## Middleware
98
109
 
99
- Since Her relies on [Faraday](https://github.com/technoweenie/faraday) to send HTTP requests, you can choose the middleware used to handle requests and responses. Using the block in the `setup` call, you have access to Faraday’s `connection` object and are able to customize the middleware stack used on each request and response.
110
+ Since Her relies on [Faraday](https://github.com/lostisland/faraday) to send HTTP requests, you can choose the middleware used to handle requests and responses. Using the block in the `setup` call, you have access to Faraday’s `connection` object and are able to customize the middleware stack used on each request and response.
100
111
 
101
112
  ### Authentication
102
113
 
@@ -126,7 +137,7 @@ end
126
137
  # config/initializers/her.rb
127
138
  require "lib/my_token_authentication"
128
139
 
129
- Her::API.setup :url => "https://api.example.com" do |connection|
140
+ Her::API.setup url: "https://api.example.com" do |connection|
130
141
  connection.use MyTokenAuthentication
131
142
  connection.use Faraday::Request::UrlEncoded
132
143
  connection.use Her::Middleware::DefaultParseJSON
@@ -153,13 +164,13 @@ In your Ruby code:
153
164
  ```ruby
154
165
  # Create an application on `https://dev.twitter.com/apps` to set these values
155
166
  TWITTER_CREDENTIALS = {
156
- :consumer_key => "",
157
- :consumer_secret => "",
158
- :token => "",
159
- :token_secret => ""
167
+ consumer_key: "",
168
+ consumer_secret: "",
169
+ token: "",
170
+ token_secret: ""
160
171
  }
161
172
 
162
- Her::API.setup :url => "https://api.twitter.com/1/" do |connection|
173
+ Her::API.setup url: "https://api.twitter.com/1/" do |connection|
163
174
  connection.use FaradayMiddleware::OAuth, TWITTER_CREDENTIALS
164
175
  connection.use Her::Middleware::DefaultParseJSON
165
176
  connection.use Faraday::Adapter::NetHttp
@@ -188,7 +199,7 @@ By default, Her handles JSON data. It expects the resource/collection data to be
188
199
 
189
200
  However, if you want Her to be able to parse the data from a single root element (usually based on the model name), you’ll have to use the `parse_root_in_json` method (See the **JSON attributes-wrapping** section).
190
201
 
191
- Also, you can define your own parsing method using a response middleware. The middleware should set `env[:body]` to a hash with three keys: `data`, `errors` and `metadata`. The following code uses a custom middleware to parse the JSON data:
202
+ Also, you can define your own parsing method using a response middleware. The middleware should set `env[:body]` to a hash with three symbol keys: `:data`, `:errors` and `:metadata`. The following code uses a custom middleware to parse the JSON data:
192
203
 
193
204
  ```ruby
194
205
  # Expects responses like:
@@ -198,21 +209,21 @@ Also, you can define your own parsing method using a response middleware. The mi
198
209
  # "id": 1,
199
210
  # "name": "Tobias Fünke"
200
211
  # },
201
- # "errors" => []
212
+ # "errors": []
202
213
  # }
203
214
  #
204
215
  class MyCustomParser < Faraday::Response::Middleware
205
216
  def on_complete(env)
206
- json = MultiJson.load(env[:body], :symbolize_keys => true)
217
+ json = MultiJson.load(env[:body], symbolize_keys: true)
207
218
  env[:body] = {
208
- :data => json[:result],
209
- :errors => json[:errors],
210
- :metadata => json[:metadata]
219
+ data: json[:result],
220
+ errors: json[:errors],
221
+ metadata: json[:metadata]
211
222
  }
212
223
  end
213
224
  end
214
225
 
215
- Her::API.setup :url => "https://api.example.com" do |connection|
226
+ Her::API.setup url: "https://api.example.com" do |connection|
216
227
  connection.use MyCustomParser
217
228
  connection.use Faraday::Adapter::NetHttp
218
229
  end
@@ -233,7 +244,7 @@ gem "memcached"
233
244
  In your Ruby code:
234
245
 
235
246
  ```ruby
236
- Her::API.setup :url => "https://api.example.com" do |connection|
247
+ Her::API.setup url: "https://api.example.com" do |connection|
237
248
  connection.use FaradayMiddleware::Caching, Memcached::Rails.new('127.0.0.1:11211')
238
249
  connection.use Her::Middleware::DefaultParseJSON
239
250
  connection.use Faraday::Adapter::NetHttp
@@ -289,14 +300,14 @@ If there’s association data in the resource, no extra HTTP request is made whe
289
300
  ```ruby
290
301
  @user = User.find(1)
291
302
  # {
292
- # :id => 1,
293
- # :name => "George Michael Bluth",
294
- # :comments => [
295
- # { :id => 1, :text => "Foo" },
296
- # { :id => 2, :text => "Bar" }
303
+ # "id": 1,
304
+ # "name": "George Michael Bluth",
305
+ # "comments": [
306
+ # { "id": 1, "text": "Foo" },
307
+ # { "id": 2, "text": "Bar" }
297
308
  # ],
298
- # :role => { :id => 1, :name => "Admin" },
299
- # :organization => { :id => 2, :name => "Bluth Company" }
309
+ # "role": { "id": 1, "name": "Admin" },
310
+ # "organization": { "id": 2, "name": "Bluth Company" }
300
311
  # }
301
312
  @user.comments
302
313
  # [#<Comment id=1 text="Foo">, #<Comment id=2 text="Bar">]
@@ -310,13 +321,17 @@ If there’s no association data in the resource, Her makes a HTTP request to re
310
321
 
311
322
  ```ruby
312
323
  @user = User.find(1)
313
- # { :id => 1, :name => "George Michael Bluth", :organization_id => 2 }
324
+ # { "id": 1, "name": "George Michael Bluth", "organization_id": 2 }
314
325
 
315
326
  # has_many association:
316
327
  @user.comments
317
328
  # GET /users/1/comments
318
329
  # [#<Comment id=1>, #<Comment id=2>]
319
330
 
331
+ @user.comments.where(approved: 1)
332
+ # GET /users/1/comments?approved=1
333
+ # [#<Comment id=1>]
334
+
320
335
  # has_one association:
321
336
  @user.role
322
337
  # GET /users/1/role
@@ -364,11 +379,11 @@ class User
364
379
  include Her::Model
365
380
 
366
381
  attributes :fullname, :email
367
- validates :fullname, :presence => true
368
- validates :email, :presence => true
382
+ validates :fullname, presence: true
383
+ validates :email, presence: true
369
384
  end
370
385
 
371
- @user = User.new(:fullname => "Tobias Fünke")
386
+ @user = User.new(fullname: "Tobias Fünke")
372
387
  @user.valid? # => false
373
388
 
374
389
  @user.save
@@ -386,7 +401,7 @@ class User
386
401
  attributes :fullname, :email
387
402
  end
388
403
 
389
- @user = User.new(:fullname => "Tobias Fünke")
404
+ @user = User.new(fullname: "Tobias Fünke")
390
405
  @user.fullname_changed? # => true
391
406
  @user.changes # => { :fullname => [nil, "Tobias Fünke"] }
392
407
 
@@ -412,7 +427,7 @@ class User
412
427
  end
413
428
  end
414
429
 
415
- @user = User.create(:fullname => "Tobias Funke")
430
+ @user = User.create(fullname: "Tobias Funke")
416
431
  # POST /users&fullname=Tobias+Fünke&internal_id=42
417
432
 
418
433
  @user = User.find(1)
@@ -450,10 +465,10 @@ class Article
450
465
  include_root_in_json :post
451
466
  end
452
467
 
453
- User.create(:fullname => "Tobias Fünke")
468
+ User.create(fullname: "Tobias Fünke")
454
469
  # POST { "user": { "fullname": "Tobias Fünke" } } to /users
455
470
 
456
- Article.create(:title => "Hello world.")
471
+ Article.create(title: "Hello world.")
457
472
  # POST { "post": { "title": "Hello world." } } to /articles
458
473
  ```
459
474
 
@@ -473,11 +488,11 @@ class Article
473
488
  end
474
489
 
475
490
  # POST /users returns { "user": { "fullname": "Tobias Fünke" } }
476
- user = User.create(:fullname => "Tobias Fünke")
491
+ user = User.create(fullname: "Tobias Fünke")
477
492
  user.fullname # => "Tobias Fünke"
478
493
 
479
494
  # POST /articles returns { "post": { "title": "Hello world." } }
480
- article = Article.create(:title => "Hello world.")
495
+ article = Article.create(title: "Hello world.")
481
496
  article.title # => "Hello world."
482
497
  ```
483
498
 
@@ -502,7 +517,7 @@ User.unpopular
502
517
  # GET /users/unpopular
503
518
  # [#<User id=3>, #<User id=4>]
504
519
 
505
- User.from_default(:name => "Maeby Fünke")
520
+ User.from_default(name: "Maeby Fünke")
506
521
  # POST /users/from_default?name=Maeby+Fünke
507
522
  # #<User id=5 name="Maeby Fünke">
508
523
  ```
@@ -582,13 +597,13 @@ class User
582
597
  collection_path "/organizations/:organization_id/users"
583
598
  end
584
599
 
585
- @user = User.find(1, :_organization_id => 2)
600
+ @user = User.find(1, _organization_id: 2)
586
601
  # GET /organizations/2/users/1
587
602
 
588
- @user = User.all(:_organization_id => 2)
603
+ @user = User.all(_organization_id: 2)
589
604
  # GET /organizations/2/users
590
605
 
591
- @user = User.new(:fullname => "Tobias Fünke", :organization_id => 2)
606
+ @user = User.new(fullname: "Tobias Fünke", organization_id: 2)
592
607
  @user.save
593
608
  # POST /organizations/2/users
594
609
  ```
@@ -603,8 +618,8 @@ class User
603
618
  primary_key :_id
604
619
  end
605
620
 
606
- user = User.find(1) # GET /users/1 returns { "_id": 1, "name": "Tobias" }
607
- user.save # PUT /users/1
621
+ user = User.find("4fd89a42ff204b03a905c535") # GET /users/1 returns { "_id": "4fd89a42ff204b03a905c535", "name": "Tobias" }
622
+ user.save # PUT /users/4fd89a42ff204b03a905c535
608
623
  ```
609
624
 
610
625
  ### Inheritance
@@ -634,14 +649,14 @@ It is possible to use different APIs for different models. Instead of calling `H
634
649
 
635
650
  ```ruby
636
651
  # config/initializers/her.rb
637
- $my_api = Her::API.new
638
- $my_api.setup :url => "https://my_api.example.com" do |connection|
652
+ MY_API = Her::API.new
653
+ MY_API.setup url: "https://my-api.example.com" do |connection|
639
654
  connection.use Her::Middleware::DefaultParseJSON
640
655
  connection.use Faraday::Adapter::NetHttp
641
656
  end
642
657
 
643
- $other_api = Her::API.new
644
- $other_api.setup :url => "https://other_api.example.com" do |connection|
658
+ OTHER_API = Her::API.new
659
+ OTHER_API.setup url: "https://other-api.example.com" do |connection|
645
660
  connection.use Her::Middleware::DefaultParseJSON
646
661
  connection.use Faraday::Adapter::NetHttp
647
662
  end
@@ -652,28 +667,28 @@ You can then define which API a model will use:
652
667
  ```ruby
653
668
  class User
654
669
  include Her::Model
655
- uses_api $my_api
670
+ use_api MY_API
656
671
  end
657
672
 
658
673
  class Category
659
674
  include Her::Model
660
- uses_api $other_api
675
+ use_api OTHER_API
661
676
  end
662
677
 
663
678
  User.all
664
- # GET https://my_api.example.com/users
679
+ # GET https://my-api.example.com/users
665
680
 
666
681
  Category.all
667
- # GET https://other_api.example.com/categories
682
+ # GET https://other-api.example.com/categories
668
683
  ```
669
684
 
670
685
  ### SSL
671
686
 
672
- When initializing `Her::API`, you can pass any parameter supported by `Faraday.new`. So [to use HTTPS](https://github.com/technoweenie/faraday/wiki/Setting-up-SSL-certificates), you can use Faraday’s `:ssl` option.
687
+ When initializing `Her::API`, you can pass any parameter supported by `Faraday.new`. So [to use HTTPS](https://github.com/lostisland/faraday/wiki/Setting-up-SSL-certificates), you can use Faraday’s `:ssl` option.
673
688
 
674
689
  ```ruby
675
- ssl_options = { :ca_path => "/usr/lib/ssl/certs" }
676
- Her::API.setup :url => "https://api.example.com", :ssl => ssl_options do |connection|
690
+ ssl_options = { ca_path: "/usr/lib/ssl/certs" }
691
+ Her::API.setup url: "https://api.example.com", ssl: ssl_options do |connection|
677
692
  connection.use Her::Middleware::DefaultParseJSON
678
693
  connection.use Faraday::Adapter::NetHttp
679
694
  end
@@ -704,11 +719,11 @@ In order to test them, we’ll have to stub the remote API requests. With [RSpec
704
719
  RSpec.configure do |config|
705
720
  config.include(Module.new do
706
721
  def stub_api_for(klass)
707
- klass.uses_api (api = Her::API.new)
722
+ klass.use_api (api = Her::API.new)
708
723
 
709
724
  # Here, you would customize this for your own API (URL, middleware, etc)
710
725
  # like you have done in your application’s initializer
711
- api.setup :url => "http://api.example.com" do |connection|
726
+ api.setup url: "http://api.example.com" do |connection|
712
727
  connection.use Her::Middleware::FirstLevelParseJSON
713
728
  connection.adapter(:test) { |s| yield(s) }
714
729
  end
@@ -724,7 +739,7 @@ Then, in your tests, we can specify what (fake) HTTP requests will return:
724
739
  describe User do
725
740
  before do
726
741
  stub_api_for(User) do |stub|
727
- stub.get("/users/popular") { |env| [200, {}, [{ :id => 1, :name => "Tobias Fünke" }, { :id => 2, :name => "Lindsay Fünke" }].to_json] }
742
+ stub.get("/users/popular") { |env| [200, {}, [{ id: 1, name: "Tobias Fünke" }, { id: 2, name: "Lindsay Fünke" }].to_json] }
728
743
  end
729
744
  end
730
745
 
@@ -744,7 +759,7 @@ describe Post do
744
759
  describe :recent do
745
760
  before do
746
761
  stub_api_for(Post) do |stub|
747
- stub.get("/posts/recent") { |env| [200, {}, [{ :id => 1 }, { :id => 2 }].to_json] }
762
+ stub.get("/posts/recent") { |env| [200, {}, [{ id: 1 }, { id: 2 }].to_json] }
748
763
  end
749
764
  end
750
765
 
@@ -756,7 +771,7 @@ describe Post do
756
771
  describe :archived do
757
772
  before do
758
773
  stub_api_for(Post) do |stub|
759
- stub.get("/posts/archived") { |env| [200, {}, [{ :id => 1 }, { :id => 2 }].to_json] }
774
+ stub.get("/posts/archived") { |env| [200, {}, [{ id: 1 }, { id: 2 }].to_json] }
760
775
  end
761
776
  end
762
777
 
data/UPGRADE.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  Here is a list of backward-incompatible changes that were introduced while Her is pre-1.0. After reaching 1.0, it will follow the [Semantic Versioning](http://semver.org/) system.
4
4
 
5
+ ## 0.6
6
+
7
+ * Associations have been refactored so that calling the association name method doesn’t immediately load or fetch the data.
8
+
9
+ class User
10
+ include Her::Model
11
+ has_many :comments
12
+ end
13
+
14
+ # This doesn’t fetch the data yet
15
+ comments = User.find(1).comments
16
+
17
+ # This actually fetches the data
18
+ puts comments.inspect
19
+
20
+ # This is no longer possible
21
+ comments = User.find(1).comments(:approved => 1)
22
+
23
+ # To pass additional parameters to the HTTP request, we now have to do this
24
+ comments = User.find(1).comments.where(:approved => 1)
25
+
5
26
  ## 0.5.4
6
27
 
7
28
  * Her does not support Ruby 1.8.7 anymore. You should upgrade to 1.9.2, 1.9.3 or 2.0.0.
data/lib/her/model.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "her/model/base"
2
2
  require "her/model/http"
3
3
  require "her/model/attributes"
4
+ require "her/model/relation"
4
5
  require "her/model/orm"
5
6
  require "her/model/parse"
6
7
  require "her/model/associations"
@@ -44,7 +45,7 @@ module Her
44
45
  # Class methods
45
46
  included do
46
47
  # Assign the default API
47
- uses_api Her::API.default_api
48
+ use_api Her::API.default_api
48
49
 
49
50
  # Define the default primary key
50
51
  primary_key :id