her 0.6.6 → 0.6.7

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -6,4 +6,15 @@ rvm:
6
6
  - 1.9.2
7
7
  - 1.8.7
8
8
 
9
+ gemfile:
10
+ - Gemfile
11
+ - gemfiles/activemodel-4.0.gemfile
12
+
13
+ matrix:
14
+ exclude:
15
+ - rvm: 1.8.7
16
+ gemfile: gemfiles/activemodel-4.0.gemfile
17
+ - rvm: 1.9.2
18
+ gemfile: gemfiles/activemodel-4.0.gemfile
19
+
9
20
  script: "echo 'COME ON!' && bundle exec rake spec"
data/README.md CHANGED
@@ -367,6 +367,20 @@ You can use the association methods to build new objects and save them.
367
367
  # => [#<Comment id=3 body="Hello world." user_id=1>]
368
368
  ```
369
369
 
370
+ You can also explicitly request a new object via the API when using ``build``. This is useful if you're dealing with default attributes.
371
+
372
+ ```ruby
373
+ class Comment
374
+ include Her::Model
375
+ request_new_object_on_build true
376
+ end
377
+
378
+ @user = User.find(1)
379
+ @user.comments.build(body: "Just a draft")
380
+ # GET "/users/1/comments/new" with `body=Just+a+draft.`
381
+ # => [#<Comment id=nil body="Just a draft" archived=false user_id=1>]
382
+ ```
383
+
370
384
  #### Notes about paths
371
385
 
372
386
  Resources must always have all the required attributes to build their complete path. For example, if you have these models:
@@ -448,7 +462,7 @@ class User
448
462
  end
449
463
  end
450
464
 
451
- @user = User.create(fullname: "Tobias Funke")
465
+ @user = User.create(fullname: "Tobias Fünke")
452
466
  # POST "/users" with `fullname=Tobias+Fünke&internal_id=42`
453
467
 
454
468
  @user = User.find(1)
@@ -891,6 +905,7 @@ These [fine folks](https://github.com/remiprev/her/contributors) helped with Her
891
905
  * [@seanreads](https://github.com/seanreads)
892
906
  * [@jonkarna](https://github.com/jonkarna)
893
907
  * [@aclevy](https://github.com/aclevy)
908
+ * [@stevschmid](https://github.com/stevschmid)
894
909
 
895
910
  ## License
896
911
 
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: "../"
4
+
5
+ gem 'activemodel', '~> 4.0.0.rc1'
data/her.gemspec CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
20
20
  s.add_development_dependency "rake", "~> 10.0"
21
21
  s.add_development_dependency "rspec", "~> 2.13"
22
22
  s.add_development_dependency "fivemat", "~> 1.2"
23
+ s.add_development_dependency "json", "~> 1.7.7"
23
24
 
24
25
  s.add_runtime_dependency "activemodel", ">= 3.0.0"
25
26
  s.add_runtime_dependency "activesupport", ">= 3.0.0"
@@ -45,7 +45,7 @@ module Her
45
45
  # new_organization = user.organization.build(:name => "Foo Inc.")
46
46
  # new_organization # => #<Organization name="Foo Inc.">
47
47
  def build(attributes = {})
48
- @klass.new(attributes)
48
+ @klass.build(attributes)
49
49
  end
50
50
 
51
51
  # Create a new object, save it and associate it to the parent
@@ -49,7 +49,7 @@ module Her
49
49
  # new_comment = user.comments.build(:body => "Hello!")
50
50
  # new_comment # => #<Comment user_id=1 body="Hello!">
51
51
  def build(attributes = {})
52
- @klass.new(attributes.merge(:"#{@parent.singularized_resource_name}_id" => @parent.id))
52
+ @klass.build(attributes.merge(:"#{@parent.singularized_resource_name}_id" => @parent.id))
53
53
  end
54
54
 
55
55
  # Create a new object, save it and add it to the associated collection
@@ -44,7 +44,7 @@ module Her
44
44
  # new_role = user.role.build(:title => "moderator")
45
45
  # new_role # => #<Role user_id=1 title="moderator">
46
46
  def build(attributes = {})
47
- @klass.new(attributes.merge(:"#{@parent.singularized_resource_name}_id" => @parent.id))
47
+ @klass.build(attributes.merge(:"#{@parent.singularized_resource_name}_id" => @parent.id))
48
48
  end
49
49
 
50
50
  # Create a new object, save it and associate it to the parent
data/lib/her/model/orm.rb CHANGED
@@ -88,7 +88,7 @@ module Her
88
88
  # User.page(2).all # Called via GET "/users?page=2"
89
89
  def scope(name, code)
90
90
  # Add the scope method to the class
91
- (class << self; self end).define_method(name) do |*args|
91
+ (class << self; self end).send(:define_method, name) do |*args|
92
92
  instance_exec(*args, &code)
93
93
  end
94
94
 
@@ -165,6 +165,24 @@ module Her
165
165
  @method_for[action] = method.to_s.downcase.to_sym
166
166
  end
167
167
 
168
+ # Build a new resource with the given attributes.
169
+ # If the request_new_object_on_build flag is set, the new object is requested via API.
170
+ def build(attributes = {})
171
+ params = attributes
172
+ return self.new(params) unless self.request_new_object_on_build?
173
+
174
+ path = self.build_request_path(params.merge(self.primary_key => 'new'))
175
+ method = self.method_for(:new)
176
+
177
+ resource = nil
178
+ self.request(params.merge(:_method => method, :_path => path)) do |parsed_data, response|
179
+ if response.success?
180
+ resource = self.new_from_parsed_data(parsed_data)
181
+ end
182
+ end
183
+ resource
184
+ end
185
+
168
186
  private
169
187
  # @private
170
188
  def blank_relation
@@ -61,6 +61,23 @@ module Her
61
61
  end
62
62
  alias parse_root_in_json? parse_root_in_json
63
63
 
64
+ # Return or change the value of `request_new_object_on_build`
65
+ #
66
+ # @example
67
+ # class User
68
+ # include Her::Model
69
+ # request_new_object_on_build true
70
+ # end
71
+ def request_new_object_on_build(value = nil)
72
+ @_her_request_new_object_on_build ||= begin
73
+ superclass.request_new_object_on_build if superclass.respond_to?(:request_new_object_on_build)
74
+ end
75
+
76
+ return @_her_request_new_object_on_build unless value
77
+ @_her_request_new_object_on_build = value
78
+ end
79
+ alias request_new_object_on_build? request_new_object_on_build
80
+
64
81
  # Return or change the value of `root_element`. Always defaults to the base name of the class.
65
82
  #
66
83
  # @example
@@ -17,7 +17,7 @@ module Her
17
17
 
18
18
  # Build a new resource
19
19
  def build(attributes = {})
20
- @parent.new(@params.merge(attributes))
20
+ @parent.build(@params.merge(attributes))
21
21
  end
22
22
 
23
23
  # Add a query string parameter
@@ -30,7 +30,7 @@ module Her
30
30
  # @users = User.where(:approved => 1).all
31
31
  # # Fetched via GET "/users?approved=1"
32
32
  def where(params = {})
33
- return self if params.blank? && @_fetch.blank?
33
+ return self if params.blank? && !@_fetch.nil?
34
34
  self.clone.tap do |r|
35
35
  r.params = r.params.merge(params)
36
36
  r.clear_fetch_cache!
data/lib/her/model.rb CHANGED
@@ -53,6 +53,7 @@ module Her
53
53
  method_for :update, :put
54
54
  method_for :find, :get
55
55
  method_for :destroy, :delete
56
+ method_for :new, :get
56
57
 
57
58
  # Define the default primary key
58
59
  primary_key :id
data/lib/her/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Her
2
- VERSION = "0.6.6"
2
+ VERSION = "0.6.7"
3
3
  end
@@ -208,6 +208,43 @@ describe Her::Model::ORM do
208
208
  end
209
209
  end
210
210
 
211
+ context "building resources" do
212
+ context "when request_new_object_on_build is not set (default)" do
213
+ before do
214
+ spawn_model("Foo::User")
215
+ end
216
+
217
+ it "builds a new resource without requesting it" do
218
+ Foo::User.should_not_receive(:request)
219
+ @new_user = Foo::User.build(:fullname => "Tobias Fünke")
220
+ @new_user.new?.should be_true
221
+ @new_user.fullname.should == "Tobias Fünke"
222
+ end
223
+ end
224
+
225
+ context "when request_new_object_on_build is set" do
226
+ before do
227
+ Her::API.setup :url => "https://api.example.com" do |builder|
228
+ builder.use Her::Middleware::FirstLevelParseJSON
229
+ builder.use Faraday::Request::UrlEncoded
230
+ builder.adapter :test do |stub|
231
+ stub.get("/users/new") { |env| ok! :id => nil, :fullname => params(env)[:fullname], :email => "tobias@bluthcompany.com" }
232
+ end
233
+ end
234
+
235
+ spawn_model("Foo::User") { request_new_object_on_build true }
236
+ end
237
+
238
+ it "requests a new resource" do
239
+ Foo::User.should_receive(:request).once.and_call_original
240
+ @new_user = Foo::User.build(:fullname => "Tobias Fünke")
241
+ @new_user.new?.should be_true
242
+ @new_user.fullname.should == "Tobias Fünke"
243
+ @new_user.email.should == "tobias@bluthcompany.com"
244
+ end
245
+ end
246
+ end
247
+
211
248
  context "creating resources" do
212
249
  before do
213
250
  Her::API.setup :url => "https://api.example.com" do |builder|
metadata CHANGED
@@ -1,18 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: her
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.6
4
+ version: 0.6.7
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Rémi Prévost
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-05-03 00:00:00.000000000 Z
12
+ date: 2013-05-27 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rake
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - ~>
18
20
  - !ruby/object:Gem::Version
@@ -20,6 +22,7 @@ dependencies:
20
22
  type: :development
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
27
  - - ~>
25
28
  - !ruby/object:Gem::Version
@@ -27,6 +30,7 @@ dependencies:
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: rspec
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
35
  - - ~>
32
36
  - !ruby/object:Gem::Version
@@ -34,6 +38,7 @@ dependencies:
34
38
  type: :development
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
43
  - - ~>
39
44
  - !ruby/object:Gem::Version
@@ -41,6 +46,7 @@ dependencies:
41
46
  - !ruby/object:Gem::Dependency
42
47
  name: fivemat
43
48
  requirement: !ruby/object:Gem::Requirement
49
+ none: false
44
50
  requirements:
45
51
  - - ~>
46
52
  - !ruby/object:Gem::Version
@@ -48,13 +54,31 @@ dependencies:
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
51
58
  requirements:
52
59
  - - ~>
53
60
  - !ruby/object:Gem::Version
54
61
  version: '1.2'
62
+ - !ruby/object:Gem::Dependency
63
+ name: json
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.7.7
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.7.7
55
78
  - !ruby/object:Gem::Dependency
56
79
  name: activemodel
57
80
  requirement: !ruby/object:Gem::Requirement
81
+ none: false
58
82
  requirements:
59
83
  - - ! '>='
60
84
  - !ruby/object:Gem::Version
@@ -62,6 +86,7 @@ dependencies:
62
86
  type: :runtime
63
87
  prerelease: false
64
88
  version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
65
90
  requirements:
66
91
  - - ! '>='
67
92
  - !ruby/object:Gem::Version
@@ -69,6 +94,7 @@ dependencies:
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: activesupport
71
96
  requirement: !ruby/object:Gem::Requirement
97
+ none: false
72
98
  requirements:
73
99
  - - ! '>='
74
100
  - !ruby/object:Gem::Version
@@ -76,6 +102,7 @@ dependencies:
76
102
  type: :runtime
77
103
  prerelease: false
78
104
  version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
79
106
  requirements:
80
107
  - - ! '>='
81
108
  - !ruby/object:Gem::Version
@@ -83,6 +110,7 @@ dependencies:
83
110
  - !ruby/object:Gem::Dependency
84
111
  name: faraday
85
112
  requirement: !ruby/object:Gem::Requirement
113
+ none: false
86
114
  requirements:
87
115
  - - ~>
88
116
  - !ruby/object:Gem::Version
@@ -90,6 +118,7 @@ dependencies:
90
118
  type: :runtime
91
119
  prerelease: false
92
120
  version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
93
122
  requirements:
94
123
  - - ~>
95
124
  - !ruby/object:Gem::Version
@@ -97,6 +126,7 @@ dependencies:
97
126
  - !ruby/object:Gem::Dependency
98
127
  name: multi_json
99
128
  requirement: !ruby/object:Gem::Requirement
129
+ none: false
100
130
  requirements:
101
131
  - - ~>
102
132
  - !ruby/object:Gem::Version
@@ -104,6 +134,7 @@ dependencies:
104
134
  type: :runtime
105
135
  prerelease: false
106
136
  version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
107
138
  requirements:
108
139
  - - ~>
109
140
  - !ruby/object:Gem::Version
@@ -125,6 +156,7 @@ files:
125
156
  - README.md
126
157
  - Rakefile
127
158
  - UPGRADE.md
159
+ - gemfiles/activemodel-4.0.gemfile
128
160
  - her.gemspec
129
161
  - lib/her.rb
130
162
  - lib/her/api.rb
@@ -179,26 +211,33 @@ files:
179
211
  homepage: http://her-rb.org
180
212
  licenses:
181
213
  - MIT
182
- metadata: {}
183
214
  post_install_message:
184
215
  rdoc_options: []
185
216
  require_paths:
186
217
  - lib
187
218
  required_ruby_version: !ruby/object:Gem::Requirement
219
+ none: false
188
220
  requirements:
189
221
  - - ! '>='
190
222
  - !ruby/object:Gem::Version
191
223
  version: '0'
224
+ segments:
225
+ - 0
226
+ hash: 1578317715926145011
192
227
  required_rubygems_version: !ruby/object:Gem::Requirement
228
+ none: false
193
229
  requirements:
194
230
  - - ! '>='
195
231
  - !ruby/object:Gem::Version
196
232
  version: '0'
233
+ segments:
234
+ - 0
235
+ hash: 1578317715926145011
197
236
  requirements: []
198
237
  rubyforge_project:
199
- rubygems_version: 2.0.2
238
+ rubygems_version: 1.8.23
200
239
  signing_key:
201
- specification_version: 4
240
+ specification_version: 3
202
241
  summary: A simple Representational State Transfer-based Hypertext Transfer Protocol-powered
203
242
  Object Relational Mapper. Her?
204
243
  test_files:
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NWQ2MzM5ODU1NDgyMmFlODFmNzJiZWRkY2ViMGNhYmY0MDc2YTIyZQ==
5
- data.tar.gz: !binary |-
6
- YTUzYTM2MjY4ZGM2Njc3NDA2ZGRlMDUyYzc4MmNmOGFkODhjNmVlZA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- ZmMyZTY3NTg1ODFjNDBkODYzYWFlZDg4YTZhNTM5Mzk2NzViYzZhZmI3NTQw
10
- OTI5ZDQyOWVjZDg5MzRmNGVhMDYzOTcyYTlkM2MwNWI1NzYzYTIyNDU2NGE1
11
- YTg3MDY3OWU5NTQxODFlYjhiY2Y0MGYwYTVkMjdlZTg3NzUzZmM=
12
- data.tar.gz: !binary |-
13
- ZGE4MjRkN2Y1NjFhYjcxNGE5MTI5ODAzMTdjNGZkMDgzZGNmYmRjODExNDBm
14
- YTU0NDM4YjQ5ZGFhM2I0MTEyZDZlMTlmOTMxZjY4NjNiODVhYTczMjY1Njc0
15
- YzFmMzQxOGU1MmU1ODEyYTY0MDc1YWQxODY2NmMyZmYwYTRlMjQ=