her 0.5.4 → 0.5.5

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MmJlNGEzMjNhZjMyOTYyZWVkYmM2NjhhNGEwZDAwZmY0ODk4MWRkNQ==
4
+ OWFlMWJkMGQ3ODVkOTdhZGVmNDM3MDE3OTJiYTIxMThjNDZkZDVhYw==
5
5
  data.tar.gz: !binary |-
6
- OGVjNGUzNDY5YTQxZmQzMzgxMDJmMWM4OGUxNmRhMjE1NWY2YzQ3Mw==
6
+ ODljYTk3MjhiNjhmYWM1MjQ1NDczZmJmNjIxYmMxNDA0NDk0ZDU0MQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YmQ0Y2VkYTM2YTg1ZmRkNzBmODkxMGVhMDI3NTI2YzRkZmYwZTJjMzE5OTI3
10
- Nzg0ZjRiMzU3ZTEzMTY5YTBiMjk4YjYzYzYzMWMwNjFlMmU2MzI3MTdhZDQ5
11
- OGUyODNhMTc4YTA3ZDYzYjVlOTc5ZGY1Y2UzZTk4MzJlM2U0YzI=
9
+ NjlmZmY0MzUxZmZlZjY0MzRkODg3YmM0MzQ1YzI4MDdjOTE5NTM1YTc0NTcw
10
+ OGZiYjgyMzA3YTlmMGRmMzAyNjRiMzQwZjQ3YjM1ODFmYTQzMDNkZmRmMzBk
11
+ ZTRkNWUxZWM2Mzk4NmJlNTQ2YmU1YWQwZmRmNzIxZDFkYjk0NTM=
12
12
  data.tar.gz: !binary |-
13
- NzVmNzU1OWVlNjQ0NzNlNWM2MmVjZDc2NjU5OWQ5NWJlN2I0ZWRkZmY3Y2Q4
14
- MTI1YzkyMDJhNDM2ZDBmN2ZmNmE4MzQxODc5MzhmZDEwNGFjOTE4MzFmYzA4
15
- OTY3OGZlNjM5MDMxZGFhMzExZDRjZTRmOTNkMjZkYWFkOTA4Nzc=
13
+ ZmExYTE0MzIyODFjN2JiYzAxOGUxM2ZhMzIzNjRiYjc4MjVlYjQxMTBlMWU2
14
+ ZmE4ZjE2ZDU2YzI0YmIyNjIxZGQ5M2I1MzJlMDU1NzkwNWFiMDk0NmRlN2Vh
15
+ NDZkMWYxOTNiZDRkNmE0NThjOWFlZjNhZDc4OGMxZjE5NjY2NmI=
data/README.md CHANGED
@@ -593,6 +593,41 @@ end
593
593
  # POST /organizations/2/users
594
594
  ```
595
595
 
596
+ ### Custom primary keys
597
+
598
+ If your record uses an attribute other than `:id` to identify itself, specify it using the `primary_key` method:
599
+
600
+ ```ruby
601
+ class User
602
+ include Her::Model
603
+ primary_key :_id
604
+ end
605
+
606
+ user = User.find(1) # GET /users/1 returns { "_id": 1, "name": "Tobias" }
607
+ user.save # PUT /users/1
608
+ ```
609
+
610
+ ### Inheritance
611
+
612
+ If all your models share the same settings, you might want to make them children of a class and only include `Her::Model` in that class.
613
+
614
+ ```ruby
615
+ module MyAPI
616
+ class Model
617
+ include Her::Model
618
+
619
+ parse_root_in_json true
620
+ include_root_in_json true
621
+ end
622
+ end
623
+
624
+ class User < MyAPI::Model
625
+ end
626
+
627
+ User.find(1)
628
+ # GET /users/1
629
+ ```
630
+
596
631
  ### Multiple APIs
597
632
 
598
633
  It is possible to use different APIs for different models. Instead of calling `Her::API.setup`, you can create instances of `Her::API`:
data/UPGRADE.md CHANGED
@@ -12,6 +12,17 @@ Here is a list of backward-incompatible changes that were introduced while Her i
12
12
 
13
13
  Before 0.5, the `errors` method on an object would return an error list received from the server (the `:errors` key defined by the parsing middleware). But now, `errors` returns the error list generated after calling the `valid?` method (or any other similar validation method from `ActiveModel::Validations`). The error list returned from the server is now accessible from the `response_errors` method.
14
14
 
15
+ Since 0.5.5, Her provides a `store_response_errors` method, which allows you to choose the method which will return the response errors. You can use it to revert Her back to its original behavior (ie. `errors` returning the response errors):
16
+
17
+ class User
18
+ include Her::Model
19
+
20
+ store_response_errors :errors
21
+ end
22
+
23
+ user = User.create(:email => "foo") # POST /users returns { :errors => ["Email is invalid"] }
24
+ user.errors # => ["Email is invalid"]
25
+
15
26
  ## 0.2.4
16
27
 
17
28
  * Her no longer includes default middleware when making HTTP requests. The user has now to define all the needed middleware. Before:
data/lib/her/errors.rb CHANGED
@@ -1,7 +1,18 @@
1
1
  module Her
2
2
  module Errors
3
- class PathError < StandardError; end;
4
- class AssociationUnknownError < StandardError; end;
5
- class ParseError < StandardError; end;
3
+ class PathError < StandardError
4
+ attr_reader :missing_parameter
5
+
6
+ def initialize(message, missing_parameter=nil)
7
+ super(message)
8
+ @missing_parameter = missing_parameter
9
+ end
10
+ end
11
+
12
+ class AssociationUnknownError < StandardError
13
+ end
14
+
15
+ class ParseError < StandardError
16
+ end
6
17
  end
7
18
  end
data/lib/her/model.rb CHANGED
@@ -43,19 +43,16 @@ module Her
43
43
 
44
44
  # Class methods
45
45
  included do
46
- # Define the root element name, used when `parse_root_in_json` is set to `true`
47
- root_element self.name.split("::").last.underscore.to_sym
48
-
49
- # Define resource and collection paths
50
- collection_path "#{root_element.to_s.pluralize}"
51
- resource_path "#{root_element.to_s.pluralize}/:id"
52
-
53
46
  # Assign the default API
54
47
  uses_api Her::API.default_api
55
48
 
56
49
  # Define the default primary key
57
50
  primary_key :id
58
51
 
52
+ # Define default storage variables for errors and metadata
53
+ store_response_errors :response_errors
54
+ store_metadata :metadata
55
+
59
56
  # Configure ActiveModel callbacks
60
57
  extend ActiveModel::Callbacks
61
58
  define_model_callbacks :create, :update, :save, :find, :destroy
@@ -4,7 +4,7 @@ module Her
4
4
  module Attributes
5
5
  extend ActiveSupport::Concern
6
6
 
7
- attr_accessor :attributes, :metadata, :response_errors
7
+ attr_accessor :attributes
8
8
  alias :data :attributes
9
9
  alias :data= :attributes=
10
10
 
@@ -167,6 +167,40 @@ module Her
167
167
  memo
168
168
  end
169
169
  end
170
+
171
+ def store_response_errors(value = nil)
172
+ if @_her_store_response_errors
173
+ remove_method @_her_store_response_errors
174
+ remove_method "#{@_her_store_response_errors}="
175
+ end
176
+
177
+ @_her_store_response_errors ||= begin
178
+ superclass.store_response_errors if superclass.respond_to?(:store_response_errors)
179
+ end
180
+
181
+ return @_her_store_response_errors unless value
182
+ @_her_store_response_errors = value
183
+
184
+ define_method(@_her_store_response_errors) { @response_errors }
185
+ define_method("#{@_her_store_response_errors}=") { |value| @response_errors = value }
186
+ end
187
+
188
+ def store_metadata(value = nil)
189
+ if @_her_store_metadata
190
+ remove_method @_her_store_metadata
191
+ remove_method "#{@_her_store_metadata}="
192
+ end
193
+
194
+ @_her_store_metadata ||= begin
195
+ superclass.store_metadata if superclass.respond_to?(:store_metadata)
196
+ end
197
+
198
+ return @_her_store_metadata unless value
199
+ @_her_store_metadata = value
200
+
201
+ define_method(@_her_store_metadata) { @metadata }
202
+ define_method("#{@_her_store_metadata}=") { |value| @metadata = value }
203
+ end
170
204
  end
171
205
  end
172
206
  end
@@ -73,9 +73,12 @@ module Her
73
73
 
74
74
  define_method "custom_#{method}".to_sym do |*paths|
75
75
  metaclass = (class << self; self; end)
76
+ opts = paths.last.is_a?(Hash) ? paths.pop : Hash.new
77
+
76
78
  paths.each do |path|
77
79
  metaclass.send(:define_method, path.to_sym) do |*attrs|
78
- send(method, path, attrs.first || Hash.new)
80
+ attrs = attrs.first || Hash.new
81
+ send(method, path, attrs)
79
82
  end
80
83
  end
81
84
  end
@@ -12,7 +12,13 @@ module Her
12
12
  # @user = User.find(1)
13
13
  # p @user # => #<User(/users/1) id=1 name="Tobias Fünke">
14
14
  def inspect
15
- "#<#{self.class}(#{request_path}) #{attributes.keys.map { |k| "#{k}=#{attribute_for_inspect(send(k))}" }.join(" ")}>"
15
+ resource_path = begin
16
+ request_path
17
+ rescue Her::Errors::PathError => e
18
+ "<unknown path, missing `#{e.missing_parameter}`>"
19
+ end
20
+
21
+ "#<#{self.class}(#{resource_path}) #{attributes.keys.map { |k| "#{k}=#{attribute_for_inspect(send(k))}" }.join(" ")}>"
16
22
  end
17
23
 
18
24
  private
@@ -28,9 +28,13 @@ module Her
28
28
  # include Her::Model
29
29
  # include_root_in_json true
30
30
  # end
31
- def include_root_in_json(value=nil)
32
- return @include_root_in_json if value.nil?
33
- @include_root_in_json = value
31
+ def include_root_in_json(value = nil)
32
+ @_her_include_root_in_json ||= begin
33
+ superclass.include_root_in_json if superclass.respond_to?(:include_root_in_json)
34
+ end
35
+
36
+ return @_her_include_root_in_json unless value
37
+ @_her_include_root_in_json = value
34
38
  end
35
39
 
36
40
  # Return or change the value of `parse_root_in`
@@ -40,12 +44,16 @@ module Her
40
44
  # include Her::Model
41
45
  # parse_root_in_json true
42
46
  # end
43
- def parse_root_in_json(value=nil)
44
- return @parse_root_in_json if value.nil?
45
- @parse_root_in_json = value
47
+ def parse_root_in_json(value = nil)
48
+ @_her_parse_root_in_json ||= begin
49
+ superclass.parse_root_in_json if superclass.respond_to?(:parse_root_in_json)
50
+ end
51
+
52
+ return @_her_parse_root_in_json unless value
53
+ @_her_parse_root_in_json = value
46
54
  end
47
55
 
48
- # Return or change the value of `root_element`
56
+ # Return or change the value of `root_element`. Always defaults to the base name of the class.
49
57
  #
50
58
  # @example
51
59
  # class User
@@ -56,19 +64,22 @@ module Her
56
64
  #
57
65
  # user = User.find(1) # { :huh => { :id => 1, :name => "Tobias" } }
58
66
  # user.name # => "Tobias"
59
- def root_element(value=nil)
60
- return @root_element if value.nil?
61
- @root_element = value
67
+ def root_element(value = nil)
68
+ if value.nil?
69
+ @_her_root_element ||= self.name.split("::").last.underscore.to_sym
70
+ else
71
+ @_her_root_element = value.to_sym
72
+ end
62
73
  end
63
74
 
64
75
  # @private
65
76
  def parse_root_in_json?
66
- @parse_root_in_json
77
+ parse_root_in_json
67
78
  end
68
79
 
69
80
  # @private
70
81
  def include_root_in_json?
71
- @include_root_in_json
82
+ include_root_in_json
72
83
  end
73
84
 
74
85
  # @private
@@ -28,10 +28,14 @@ module Her
28
28
  # primary_key 'UserId'
29
29
  # end
30
30
  #
31
- # @param [Symbol] field
32
- def primary_key(field = nil)
33
- return @her_primary_key if field.nil?
34
- @her_primary_key = field.to_sym
31
+ # @param [Symbol] value
32
+ def primary_key(value = nil)
33
+ @_her_primary_key ||= begin
34
+ superclass.primary_key.to_sym if superclass.respond_to?(:primary_key)
35
+ end
36
+
37
+ return @_her_primary_key unless value
38
+ @_her_primary_key = value.to_sym
35
39
  end
36
40
 
37
41
  # Defines a custom collection path for the resource
@@ -41,14 +45,13 @@ module Her
41
45
  # include Her::Model
42
46
  # collection_path "/users"
43
47
  # end
44
- def collection_path(path=nil)
45
- @_her_collection_path ||= begin
46
- superclass.collection_path.dup if superclass.respond_to?(:collection_path)
48
+ def collection_path(path = nil)
49
+ if path.nil?
50
+ @_her_collection_path ||= "#{root_element.to_s.pluralize}"
51
+ else
52
+ @_her_collection_path = path
53
+ @_her_resource_path = "#{path}/:id"
47
54
  end
48
-
49
- return @_her_collection_path unless path
50
- @_her_resource_path = "#{path}/:id"
51
- @_her_collection_path = path
52
55
  end
53
56
 
54
57
  # Defines a custom resource path for the resource
@@ -74,13 +77,12 @@ module Her
74
77
  # resource_path '/users/:id'
75
78
  # end
76
79
  #
77
- def resource_path(path=nil)
78
- @_her_resource_path ||= begin
79
- superclass.resource_path.dup if superclass.respond_to?(:resource_path)
80
+ def resource_path(path = nil)
81
+ if path.nil?
82
+ @_her_resource_path ||= "#{root_element.to_s.pluralize}/:id"
83
+ else
84
+ @_her_resource_path = path
80
85
  end
81
-
82
- return @_her_resource_path unless path
83
- @_her_resource_path = path
84
86
  end
85
87
 
86
88
  # Return a custom path based on the collection path and variable parameters
@@ -108,7 +110,7 @@ module Her
108
110
 
109
111
  path.gsub(/:([\w_]+)/) do
110
112
  # Look for :key or :_key, otherwise raise an exception
111
- parameters.delete($1.to_sym) || parameters.delete("_#{$1}".to_sym) || raise(Her::Errors::PathError, "Missing :_#{$1} parameter to build the request path. Path is `#{path}`. Parameters are `#{parameters.inspect}`.")
113
+ parameters.delete($1.to_sym) || parameters.delete("_#{$1}".to_sym) || raise(Her::Errors::PathError.new("Missing :_#{$1} parameter to build the request path. Path is `#{path}`. Parameters are `#{parameters.inspect}`.", $1))
112
114
  end
113
115
  end
114
116
 
data/lib/her/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Her
2
- VERSION = "0.5.4"
2
+ VERSION = "0.5.5"
3
3
  end
@@ -136,4 +136,31 @@ describe Her::Model::Attributes do
136
136
  hash.should == { user => false }
137
137
  end
138
138
  end
139
+
140
+ context "handling metadata and errors" do
141
+ before do
142
+ spawn_model 'Foo::User' do
143
+ store_response_errors :errors
144
+ store_metadata :my_data
145
+ end
146
+
147
+ @user = Foo::User.new(:_errors => ["Foo", "Bar"], :_metadata => { :secret => true })
148
+ end
149
+
150
+ it "should return response_errors stored in the method provided by `store_response_errors`" do
151
+ @user.errors.should == ["Foo", "Bar"]
152
+ end
153
+
154
+ it "should remove the default method for errors" do
155
+ expect { @user.response_errors }.to raise_error(NoMethodError)
156
+ end
157
+
158
+ it "should return metadata stored in the method provided by `store_metadata`" do
159
+ @user.my_data.should == { :secret => true }
160
+ end
161
+
162
+ it "should remove the default method for metadata" do
163
+ expect { @user.metadata }.to raise_error(NoMethodError)
164
+ end
165
+ end
139
166
  end
@@ -161,13 +161,15 @@ describe Her::Model::HTTP do
161
161
  subject { Foo::User }
162
162
 
163
163
  describe :custom_get do
164
- before { Foo::User.custom_get :popular, :recent }
165
- it { should respond_to(:popular) }
166
- it { should respond_to(:recent) }
167
-
168
- context "making the HTTP request" do
169
- subject { Foo::User.popular }
170
- its(:length) { should == 2 }
164
+ context "without cache" do
165
+ before { Foo::User.custom_get :popular, :recent }
166
+ it { should respond_to(:popular) }
167
+ it { should respond_to(:recent) }
168
+
169
+ context "making the HTTP request" do
170
+ subject { Foo::User.popular }
171
+ its(:length) { should == 2 }
172
+ end
171
173
  end
172
174
  end
173
175
 
@@ -12,10 +12,14 @@ describe Her::Model::Introspection do
12
12
  stub.get("/users/1") { |env| [200, {}, { :id => 1, :name => "Tobias Funke" }.to_json] }
13
13
  stub.put("/users/1") { |env| [200, {}, { :id => 1, :name => "Tobias Funke" }.to_json] }
14
14
  stub.delete("/users/1") { |env| [200, {}, { :id => 1, :name => "Tobias Funke" }.to_json] }
15
+ stub.get("/projects/1/comments") { |env| [200, {}, [{ :id => 1, :body => "Hello!" }].to_json] }
15
16
  end
16
17
  end
17
18
 
18
19
  spawn_model "Foo::User"
20
+ spawn_model "Foo::Comment" do
21
+ collection_path "projects/:project_id/comments"
22
+ end
19
23
  end
20
24
 
21
25
  describe "#inspect" do
@@ -37,6 +41,14 @@ describe Her::Model::Introspection do
37
41
  @user.inspect.should_not include("password=\"Funke\"")
38
42
  end
39
43
  end
44
+
45
+ describe "#inspect with errors in resource path" do
46
+ it "prints the resource path as “unknown”" do
47
+ @comment = Foo::Comment.all(:project_id => 1).first
48
+ path = '<unknown path, missing `project_id`>'
49
+ ["#<Foo::Comment(#{path}) body=\"Hello!\" id=1>", "#<Foo::Comment(#{path}) id=1 body=\"Hello!\">"].should include(@comment.inspect)
50
+ end
51
+ end
40
52
  end
41
53
 
42
54
  describe "#her_nearby_class" do
@@ -399,90 +399,4 @@ describe Her::Model::ORM do
399
399
  end
400
400
  end
401
401
 
402
- context "when include_root_in_json is true" do
403
- context "when include_root_in_json is true" do
404
- before do
405
- spawn_model "Foo::User" do
406
- include_root_in_json true
407
- end
408
- end
409
-
410
- it "wraps params in the element name" do
411
- @new_user = Foo::User.new(:fullname => "Tobias Fünke")
412
- @new_user.to_params.should == { :user => { :fullname => "Tobias Fünke" } }
413
- end
414
- end
415
-
416
- context "when include_root_in_json is set to another value" do
417
- before do
418
- spawn_model "Foo::User" do
419
- include_root_in_json :person
420
- end
421
- end
422
-
423
- it "wraps params in the specified value" do
424
- @new_user = Foo::User.new(:fullname => "Tobias Fünke")
425
- @new_user.to_params.should == { :person => { :fullname => "Tobias Fünke" } }
426
- end
427
- end
428
- end
429
-
430
- context "when parse_root_in_json is set" do
431
- before do
432
- Her::API.setup :url => "https://api.example.com" do |builder|
433
- builder.use Her::Middleware::FirstLevelParseJSON
434
- builder.use Faraday::Request::UrlEncoded
435
- end
436
- end
437
-
438
- context "when parse_root_in_json is true" do
439
- before do
440
- Her::API.default_api.connection.adapter :test do |stub|
441
- stub.post("/users") { |env| [200, {}, { :user => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
442
- stub.get("/users") { |env| [200, {}, [{ :user => { :id => 1, :fullname => "Lindsay Fünke" } }].to_json] }
443
- stub.get("/users/1") { |env| [200, {}, { :user => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
444
- stub.put("/users/1") { |env| [200, {}, { :user => { :id => 1, :fullname => "Tobias Fünke Jr." } }.to_json] }
445
- end
446
-
447
- spawn_model("Foo::User") { parse_root_in_json true }
448
- end
449
-
450
- it "parse the data from the JSON root element after .create" do
451
- @new_user = Foo::User.create(:fullname => "Lindsay Fünke")
452
- @new_user.fullname.should == "Lindsay Fünke"
453
- end
454
-
455
- it "parse the data from the JSON root element after .all" do
456
- @users = Foo::User.all
457
- @users.first.fullname.should == "Lindsay Fünke"
458
- end
459
-
460
- it "parse the data from the JSON root element after .find" do
461
- @user = Foo::User.find(1)
462
- @user.fullname.should == "Lindsay Fünke"
463
- end
464
-
465
- it "parse the data from the JSON root element after .save" do
466
- @user = Foo::User.find(1)
467
- @user.fullname = "Tobias Fünke"
468
- @user.save
469
- @user.fullname.should == "Tobias Fünke Jr."
470
- end
471
- end
472
-
473
- context "when parse_root_in_json is set to a symbol" do
474
- before do
475
- Her::API.default_api.connection.adapter :test do |stub|
476
- stub.post("/users") { |env| [200, {}, { :person => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
477
- end
478
-
479
- spawn_model("Foo::User") { parse_root_in_json :person }
480
- end
481
-
482
- it "parse the data with the symbol" do
483
- @new_user = Foo::User.create(:fullname => "Lindsay Fünke")
484
- @new_user.fullname.should == "Lindsay Fünke"
485
- end
486
- end
487
- end
488
402
  end
@@ -0,0 +1,125 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
3
+
4
+ describe Her::Model::Parse do
5
+ context "when include_root_in_json is true" do
6
+ context "when include_root_in_json is true" do
7
+ before do
8
+ spawn_model "Foo::User" do
9
+ include_root_in_json true
10
+ end
11
+ end
12
+
13
+ it "wraps params in the element name" do
14
+ @new_user = Foo::User.new(:fullname => "Tobias Fünke")
15
+ @new_user.to_params.should == { :user => { :fullname => "Tobias Fünke" } }
16
+ end
17
+ end
18
+
19
+ context "when include_root_in_json is set to another value" do
20
+ before do
21
+ spawn_model "Foo::User" do
22
+ include_root_in_json :person
23
+ end
24
+ end
25
+
26
+ it "wraps params in the specified value" do
27
+ @new_user = Foo::User.new(:fullname => "Tobias Fünke")
28
+ @new_user.to_params.should == { :person => { :fullname => "Tobias Fünke" } }
29
+ end
30
+ end
31
+
32
+ context "when include_root_in_json is set in the parent class" do
33
+ before do
34
+ spawn_model("Foo::Model") { include_root_in_json true }
35
+
36
+ class User < Foo::Model; end
37
+ @spawned_models << :User
38
+ end
39
+
40
+ it "wraps params with the class name" do
41
+ @new_user = User.new(:fullname => "Tobias Fünke")
42
+ @new_user.to_params.should == { :user => { :fullname => "Tobias Fünke" } }
43
+ end
44
+ end
45
+ end
46
+
47
+ context "when parse_root_in_json is set" do
48
+ before do
49
+ Her::API.setup :url => "https://api.example.com" do |builder|
50
+ builder.use Her::Middleware::FirstLevelParseJSON
51
+ builder.use Faraday::Request::UrlEncoded
52
+ end
53
+ end
54
+
55
+ context "when parse_root_in_json is true" do
56
+ before do
57
+ Her::API.default_api.connection.adapter :test do |stub|
58
+ stub.post("/users") { |env| [200, {}, { :user => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
59
+ stub.get("/users") { |env| [200, {}, [{ :user => { :id => 1, :fullname => "Lindsay Fünke" } }].to_json] }
60
+ stub.get("/users/1") { |env| [200, {}, { :user => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
61
+ stub.put("/users/1") { |env| [200, {}, { :user => { :id => 1, :fullname => "Tobias Fünke Jr." } }.to_json] }
62
+ end
63
+
64
+ spawn_model("Foo::User") { parse_root_in_json true }
65
+ end
66
+
67
+ it "parse the data from the JSON root element after .create" do
68
+ @new_user = Foo::User.create(:fullname => "Lindsay Fünke")
69
+ @new_user.fullname.should == "Lindsay Fünke"
70
+ end
71
+
72
+ it "parse the data from the JSON root element after .all" do
73
+ @users = Foo::User.all
74
+ @users.first.fullname.should == "Lindsay Fünke"
75
+ end
76
+
77
+ it "parse the data from the JSON root element after .find" do
78
+ @user = Foo::User.find(1)
79
+ @user.fullname.should == "Lindsay Fünke"
80
+ end
81
+
82
+ it "parse the data from the JSON root element after .save" do
83
+ @user = Foo::User.find(1)
84
+ @user.fullname = "Tobias Fünke"
85
+ @user.save
86
+ @user.fullname.should == "Tobias Fünke Jr."
87
+ end
88
+ end
89
+
90
+ context "when parse_root_in_json is set to a symbol" do
91
+ before do
92
+ Her::API.default_api.connection.adapter :test do |stub|
93
+ stub.post("/users") { |env| [200, {}, { :person => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
94
+ end
95
+
96
+ spawn_model("Foo::User") { parse_root_in_json :person }
97
+ end
98
+
99
+ it "parse the data with the symbol" do
100
+ @new_user = Foo::User.create(:fullname => "Lindsay Fünke")
101
+ @new_user.fullname.should == "Lindsay Fünke"
102
+ end
103
+ end
104
+
105
+ context "when parse_root_in_json is set from the parent class" do
106
+ before do
107
+ Her::API.default_api.connection.adapter :test do |stub|
108
+ stub.post("/users") { |env| [200, {}, { :user => { :id => 1, :fullname => "Lindsay Fünke" } }.to_json] }
109
+ end
110
+
111
+ spawn_model("Foo::Model") { parse_root_in_json true }
112
+ class User < Foo::Model
113
+ collection_path "/users"
114
+ end
115
+
116
+ @spawned_models << :User
117
+ end
118
+
119
+ it "parse the data with the symbol" do
120
+ @new_user = User.create(:fullname => "Lindsay Fünke")
121
+ @new_user.fullname.should == "Lindsay Fünke"
122
+ end
123
+ end
124
+ end
125
+ end
@@ -14,9 +14,29 @@ describe "Her::Model and ActiveModel::Validations" do
14
14
  it "validates attributes when calling #valid?" do
15
15
  user = Foo::User.new
16
16
  user.should_not be_valid
17
+ user.errors.full_messages.should include("Fullname can't be blank")
18
+ user.errors.full_messages.should include("Email can't be blank")
17
19
  user.fullname = "Tobias Fünke"
18
20
  user.email = "tobias@bluthcompany.com"
19
21
  user.should be_valid
20
22
  end
21
23
  end
24
+
25
+ context "handling server errors" do
26
+ before do
27
+ spawn_model("Foo::Model") do
28
+ def errors
29
+ @response_errors
30
+ end
31
+ end
32
+
33
+ class User < Foo::Model; end
34
+ @spawned_models << :User
35
+ end
36
+
37
+ it "validates attributes when calling #valid?" do
38
+ user = User.new(:_errors => ["Email cannot be blank"])
39
+ user.errors.should include("Email cannot be blank")
40
+ end
41
+ end
22
42
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: her
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rémi Prévost
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-08 00:00:00.000000000 Z
11
+ date: 2013-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -193,6 +193,7 @@ files:
193
193
  - spec/model/introspection_spec.rb
194
194
  - spec/model/nested_attributes_spec.rb
195
195
  - spec/model/orm_spec.rb
196
+ - spec/model/parse_spec.rb
196
197
  - spec/model/paths_spec.rb
197
198
  - spec/model/validations_spec.rb
198
199
  - spec/model_spec.rb
@@ -239,6 +240,7 @@ test_files:
239
240
  - spec/model/introspection_spec.rb
240
241
  - spec/model/nested_attributes_spec.rb
241
242
  - spec/model/orm_spec.rb
243
+ - spec/model/parse_spec.rb
242
244
  - spec/model/paths_spec.rb
243
245
  - spec/model/validations_spec.rb
244
246
  - spec/model_spec.rb