rest-in-peace 2.0.4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,7 +1,13 @@
1
1
  language: ruby
2
+ cache: bundler
2
3
  rvm:
3
4
  - 1.9.3
4
5
  - 2.0.0
5
6
  - 2.1.2
7
+ gemfile:
8
+ - gemfiles/Gemfile.rails-3.2.x
9
+ - gemfiles/Gemfile.rails-4.0.x
10
+ - gemfiles/Gemfile.rails-4.1.x
11
+ - gemfiles/Gemfile.rails-4.2.x
6
12
  script:
7
13
  - bundle exec rake spec
data/README.md CHANGED
@@ -36,11 +36,13 @@ rest_in_peace do
36
36
  end
37
37
  ```
38
38
 
39
+ **There must be at least an attribute called `id` to allow REST-in-Peace to work properly.**
40
+
39
41
  #### API Endpoints
40
42
 
41
- You need to define all the API endpoints you want to consume with `RESTinPeace`. Currently the four HTTP Verbs `GET`, `POST`, `PATCH` and `DELETE` are supported.
43
+ You need to define all the API endpoints you want to consume with `RESTinPeace`. Currently the four HTTP verbs `GET`, `POST`, `PATCH` and `DELETE` are supported.
42
44
 
43
- There are two sections where you can specify endpoints: `resource` and `collection`:
45
+ There are two sections where you can specify endpoints: `resource` and `collection`. `collection` supports the HTTP verb `GET` only.
44
46
 
45
47
  ```ruby
46
48
  rest_in_peace do
@@ -95,7 +97,7 @@ resource.create # calls "POST /rip"
95
97
  resource.reload # calls "GET /rip/1"
96
98
  ```
97
99
 
98
- **For any writing action (`:post`, `:put`, `:patch`) RESTinPeace will include the writable attributes in the body and `id`.**
100
+ **For any writing action (`:post`, `:put`, `:patch`) RESTinPeace will include the *changed* attributes in the body and `id`.**
99
101
 
100
102
  #### Collection
101
103
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.4
1
+ 3.0.0
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'rails', '~> 3.2.0'
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'rails', '~> 4.0.0'
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'rails', '~> 4.1.0'
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'rails', '~> 4.2.0'
@@ -1,4 +1,5 @@
1
1
  require 'active_model'
2
+ require 'active_support/core_ext/object/blank'
2
3
 
3
4
  module RESTinPeace
4
5
  module ActiveModelAPI
@@ -12,25 +13,12 @@ module RESTinPeace
12
13
  def self.included(base)
13
14
  check_for_missing_methods(base)
14
15
 
15
- base.send(:include, ActiveModel::Dirty)
16
16
  base.send(:include, ActiveModel::Conversion)
17
17
  base.extend ActiveModel::Naming
18
18
 
19
19
  base.send(:alias_method, :save_without_dirty_tracking, :save)
20
20
  base.send(:alias_method, :save, :save_with_dirty_tracking)
21
21
 
22
- base.send :define_attribute_methods, base.rip_attributes[:write]
23
-
24
- base.rip_attributes[:write].each do |attribute|
25
- base.send(:define_method, "#{attribute}_with_dirty_tracking=") do |value|
26
- attribute_will_change!(attribute) unless send(attribute) == value
27
- send("#{attribute}_without_dirty_tracking=", value)
28
- end
29
-
30
- base.send(:alias_method, "#{attribute}_without_dirty_tracking=", "#{attribute}=")
31
- base.send(:alias_method, "#{attribute}=", "#{attribute}_with_dirty_tracking=")
32
- end
33
-
34
22
  def base.human_attribute_name(attr, options = {})
35
23
  attr.to_s
36
24
  end
@@ -47,7 +35,7 @@ module RESTinPeace
47
35
 
48
36
  def save_with_dirty_tracking
49
37
  save_without_dirty_tracking.tap do
50
- @changed_attributes.clear if @changed_attributes
38
+ clear_changes
51
39
  end
52
40
  end
53
41
 
@@ -12,8 +12,25 @@ module RESTinPeace
12
12
 
13
13
  def write(*attributes)
14
14
  read(*attributes)
15
- @target.send(:attr_writer, *attributes)
15
+ @target.send :attr_writer, *attributes
16
+ @target.send :define_attribute_methods, attributes
16
17
  @target.rip_attributes[:write].concat(attributes)
18
+
19
+ attributes.each do |attribute|
20
+ define_dirty_tracking attribute
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def define_dirty_tracking(attribute)
27
+ @target.send(:define_method, "#{attribute}_with_dirty_tracking=") do |value|
28
+ attribute_will_change!(attribute) unless send(attribute) == value
29
+ send("#{attribute}_without_dirty_tracking=", value)
30
+ end
31
+
32
+ @target.send(:alias_method, "#{attribute}_without_dirty_tracking=", "#{attribute}=")
33
+ @target.send(:alias_method, "#{attribute}=", "#{attribute}_with_dirty_tracking=")
17
34
  end
18
35
  end
19
36
  end
data/lib/rest_in_peace.rb CHANGED
@@ -1,9 +1,12 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+
1
3
  require 'rest_in_peace/definition_proxy'
2
4
 
3
5
  module RESTinPeace
4
6
 
5
7
  def self.included(base)
6
8
  base.send :extend, ClassMethods
9
+ base.send :include, ActiveModel::Dirty
7
10
  end
8
11
 
9
12
  def api
@@ -16,9 +19,9 @@ module RESTinPeace
16
19
 
17
20
  def hash_for_updates
18
21
  hash_representation = { id: id }
19
- self.class.rip_attributes[:write].map do |key|
22
+ changed.each do |key|
20
23
  value = send(key)
21
- hash_representation[key] = hash_representation_of_object(value)
24
+ hash_representation[key.to_sym] = hash_representation_of_object(value)
22
25
  end
23
26
  if self.class.rip_namespace
24
27
  { id: id, self.class.rip_namespace => hash_representation }
@@ -27,6 +30,18 @@ module RESTinPeace
27
30
  end
28
31
  end
29
32
 
33
+ def clear_changes
34
+ case
35
+ when respond_to?(:clear_changes_information) # ActiveModel >= 4.2
36
+ clear_changes_information
37
+ when respond_to?(:reset_changes) # ActiveModel >= 4.0 && <= 4.1
38
+ reset_changes
39
+ else # ActiveModel <= 3.2
40
+ return unless @changed_attributes
41
+ @changed_attributes.clear
42
+ end
43
+ end
44
+
30
45
  def update_attributes(attributes)
31
46
  attributes.each do |key, value|
32
47
  next unless respond_to?("#{key}=")
@@ -51,6 +66,7 @@ module RESTinPeace
51
66
  instance_variable_set("@#{key}", value)
52
67
  end
53
68
  end
69
+ clear_changes
54
70
  end
55
71
 
56
72
  def hash_representation_of_object(object)
@@ -99,27 +99,6 @@ describe RESTinPeace do
99
99
  allow(api_double).to receive(:post).and_return(response)
100
100
  end
101
101
 
102
- describe '#changed?' do
103
- context 'a new instance' do
104
- specify { expect(instance.changed?).to eq(false) }
105
- end
106
-
107
- context 'a modified instance' do
108
- before do
109
- instance.description = 'new value'
110
- end
111
- specify { expect(instance.changed?).to eq(true) }
112
- end
113
-
114
- context 'a saved instance' do
115
- before do
116
- instance.description = 'new value'
117
- instance.save
118
- end
119
- specify { expect(instance.changed?).to eq(false) }
120
- end
121
- end
122
-
123
102
  describe 'attribute methods' do
124
103
  specify { expect(instance).to respond_to(:description_changed?) }
125
104
  specify { expect(instance).to respond_to(:title_changed?) }
@@ -9,7 +9,7 @@ describe RESTinPeace do
9
9
  rest_in_peace do
10
10
  attributes do
11
11
  read :id, :name, :relation
12
- write :my_array, :my_hash, :array_with_hash, :overridden_attribute
12
+ write :my_array, :my_hash, :array_with_hash, :overridden_attribute, :description
13
13
  end
14
14
  end
15
15
 
@@ -31,6 +31,7 @@ describe RESTinPeace do
31
31
  let(:my_hash) { { element1: 'yolo' } }
32
32
  let(:array_with_hash) { [my_hash.dup] }
33
33
  let(:overridden_attribute) { 'initial value' }
34
+ let(:description) { 'old description' }
34
35
  let(:attributes) do
35
36
  {
36
37
  id: 1,
@@ -40,6 +41,7 @@ describe RESTinPeace do
40
41
  my_hash: my_hash,
41
42
  array_with_hash: array_with_hash,
42
43
  overridden_attribute: overridden_attribute,
44
+ description: description,
43
45
  }
44
46
  end
45
47
  let(:instance) { extended_class.new(attributes) }
@@ -75,8 +77,8 @@ describe RESTinPeace do
75
77
  specify { expect(extended_class).to respond_to(:rip_attributes) }
76
78
  specify do
77
79
  expect(extended_class.rip_attributes).to eq(
78
- read: [:id, :name, :relation, :my_array, :my_hash, :array_with_hash, :overridden_attribute],
79
- write: [:my_array, :my_hash, :array_with_hash, :overridden_attribute])
80
+ read: [:id, :name, :relation, :my_array, :my_hash, :array_with_hash, :overridden_attribute, :description],
81
+ write: [:my_array, :my_hash, :array_with_hash, :overridden_attribute, :description])
80
82
  end
81
83
  end
82
84
 
@@ -110,6 +112,9 @@ describe RESTinPeace do
110
112
  end
111
113
 
112
114
  context 'overridden getter' do
115
+ before do
116
+ subject.overridden_attribute = 'new value'
117
+ end
113
118
  specify { expect(subject.hash_for_updates).to include(overridden_attribute: 'something else') }
114
119
  end
115
120
 
@@ -119,13 +124,22 @@ describe RESTinPeace do
119
124
  end
120
125
 
121
126
  context 'hash' do
122
- specify { expect(subject.hash_for_updates[:my_hash]).to eq(element1: 'yolo') }
127
+ before do
128
+ subject.my_hash = { element1: 'swag' }
129
+ end
130
+
131
+ specify { expect(subject.hash_for_updates[:my_hash]).to eq(element1: 'swag') }
123
132
  end
124
133
 
125
134
  context 'with objects assigned' do
126
- let(:my_hash) { double('OtherClass') }
135
+ let(:new_hash) { double('OtherClass') }
136
+
137
+ before do
138
+ subject.my_hash = new_hash
139
+ end
140
+
127
141
  it 'deeply calls hash_for_updates' do
128
- expect(my_hash).to receive(:hash_for_updates).and_return({})
142
+ expect(new_hash).to receive(:hash_for_updates).and_return({})
129
143
  subject.hash_for_updates
130
144
  end
131
145
  end
@@ -139,7 +153,7 @@ describe RESTinPeace do
139
153
  rest_in_peace do
140
154
  attributes do
141
155
  read :id
142
- write :name
156
+ write :name, :description
143
157
  end
144
158
 
145
159
  namespace_attributes_with :blubb
@@ -147,7 +161,11 @@ describe RESTinPeace do
147
161
  end
148
162
  end
149
163
 
150
- specify { expect(subject.hash_for_updates).to eq(id: 1, blubb: { id: 1, name: 'test' }) }
164
+ before do
165
+ subject.name = 'new value'
166
+ end
167
+
168
+ specify { expect(subject.hash_for_updates).to eq(id: 1, blubb: { id: 1, name: 'new value' }) }
151
169
  end
152
170
  end
153
171
 
@@ -204,4 +222,27 @@ describe RESTinPeace do
204
222
  to_not change(instance, :name).from(attributes[:name])
205
223
  end
206
224
  end
225
+
226
+ describe '#changed?' do
227
+ subject { instance }
228
+
229
+ context 'a new instance' do
230
+ it { is_expected.to_not be_changed }
231
+ end
232
+
233
+ context 'a modified instance' do
234
+ before do
235
+ instance.description = 'new value'
236
+ end
237
+ it { is_expected.to be_changed }
238
+ end
239
+
240
+ context 'a saved instance' do
241
+ before do
242
+ instance.description = 'new value'
243
+ instance.clear_changes
244
+ end
245
+ it { is_expected.to_not be_changed }
246
+ end
247
+ end
207
248
  end
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest-in-peace
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: 3.0.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Raffael Schmid
@@ -13,6 +14,7 @@ dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activemodel
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - ! '>='
18
20
  - !ruby/object:Gem::Version
@@ -23,6 +25,7 @@ dependencies:
23
25
  type: :runtime
24
26
  prerelease: false
25
27
  version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
26
29
  requirements:
27
30
  - - ! '>='
28
31
  - !ruby/object:Gem::Version
@@ -33,6 +36,7 @@ dependencies:
33
36
  - !ruby/object:Gem::Dependency
34
37
  name: rake
35
38
  requirement: !ruby/object:Gem::Requirement
39
+ none: false
36
40
  requirements:
37
41
  - - ~>
38
42
  - !ruby/object:Gem::Version
@@ -40,6 +44,7 @@ dependencies:
40
44
  type: :development
41
45
  prerelease: false
42
46
  version_requirements: !ruby/object:Gem::Requirement
47
+ none: false
43
48
  requirements:
44
49
  - - ~>
45
50
  - !ruby/object:Gem::Version
@@ -47,6 +52,7 @@ dependencies:
47
52
  - !ruby/object:Gem::Dependency
48
53
  name: rspec
49
54
  requirement: !ruby/object:Gem::Requirement
55
+ none: false
50
56
  requirements:
51
57
  - - ~>
52
58
  - !ruby/object:Gem::Version
@@ -54,6 +60,7 @@ dependencies:
54
60
  type: :development
55
61
  prerelease: false
56
62
  version_requirements: !ruby/object:Gem::Requirement
63
+ none: false
57
64
  requirements:
58
65
  - - ~>
59
66
  - !ruby/object:Gem::Version
@@ -61,6 +68,7 @@ dependencies:
61
68
  - !ruby/object:Gem::Dependency
62
69
  name: guard
63
70
  requirement: !ruby/object:Gem::Requirement
71
+ none: false
64
72
  requirements:
65
73
  - - ~>
66
74
  - !ruby/object:Gem::Version
@@ -71,6 +79,7 @@ dependencies:
71
79
  type: :development
72
80
  prerelease: false
73
81
  version_requirements: !ruby/object:Gem::Requirement
82
+ none: false
74
83
  requirements:
75
84
  - - ~>
76
85
  - !ruby/object:Gem::Version
@@ -81,6 +90,7 @@ dependencies:
81
90
  - !ruby/object:Gem::Dependency
82
91
  name: guard-rspec
83
92
  requirement: !ruby/object:Gem::Requirement
93
+ none: false
84
94
  requirements:
85
95
  - - ~>
86
96
  - !ruby/object:Gem::Version
@@ -91,6 +101,7 @@ dependencies:
91
101
  type: :development
92
102
  prerelease: false
93
103
  version_requirements: !ruby/object:Gem::Requirement
104
+ none: false
94
105
  requirements:
95
106
  - - ~>
96
107
  - !ruby/object:Gem::Version
@@ -101,6 +112,7 @@ dependencies:
101
112
  - !ruby/object:Gem::Dependency
102
113
  name: simplecov
103
114
  requirement: !ruby/object:Gem::Requirement
115
+ none: false
104
116
  requirements:
105
117
  - - ~>
106
118
  - !ruby/object:Gem::Version
@@ -111,6 +123,7 @@ dependencies:
111
123
  type: :development
112
124
  prerelease: false
113
125
  version_requirements: !ruby/object:Gem::Requirement
126
+ none: false
114
127
  requirements:
115
128
  - - ~>
116
129
  - !ruby/object:Gem::Version
@@ -137,6 +150,10 @@ files:
137
150
  - Rakefile
138
151
  - VERSION
139
152
  - examples/pagination_with_headers.rb
153
+ - gemfiles/Gemfile.rails-3.2.x
154
+ - gemfiles/Gemfile.rails-4.0.x
155
+ - gemfiles/Gemfile.rails-4.1.x
156
+ - gemfiles/Gemfile.rails-4.2.x
140
157
  - images/rest_in_peace.gif
141
158
  - lib/rest-in-peace.rb
142
159
  - lib/rest_in_peace.rb
@@ -165,26 +182,27 @@ files:
165
182
  homepage: http://github.com/ninech/
166
183
  licenses:
167
184
  - MIT
168
- metadata: {}
169
185
  post_install_message:
170
186
  rdoc_options: []
171
187
  require_paths:
172
188
  - lib
173
189
  required_ruby_version: !ruby/object:Gem::Requirement
190
+ none: false
174
191
  requirements:
175
192
  - - ! '>='
176
193
  - !ruby/object:Gem::Version
177
194
  version: '0'
178
195
  required_rubygems_version: !ruby/object:Gem::Requirement
196
+ none: false
179
197
  requirements:
180
198
  - - ! '>='
181
199
  - !ruby/object:Gem::Version
182
200
  version: '0'
183
201
  requirements: []
184
202
  rubyforge_project:
185
- rubygems_version: 2.2.2
203
+ rubygems_version: 1.8.23.2
186
204
  signing_key:
187
- specification_version: 4
205
+ specification_version: 3
188
206
  summary: REST in peace
189
207
  test_files:
190
208
  - spec/rest_in_peace/active_model_api_spec.rb
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MzVkMWFiODFlNGQ2ZTVkMTM0MTRkYTg1OGRmNjBmYWI1NGM3YWNmYw==
5
- data.tar.gz: !binary |-
6
- ZWZlYjY3NjNkNzQwNjcwOGVlZmU5YzVjZTM2YjBlNjk3YTA2ZTY1Yw==
7
- SHA512:
8
- metadata.gz: !binary |-
9
- ZDRkZjlmY2NlNGU4MDgzM2UyY2ZmZTc5NmQxOWZiMTcxYTdjZTBiN2Y0NTc5
10
- MTg1ZDY5YzA2NDFjNjNkNzFiOWZhZmUyZDBhMGVjNWQxYzNjZGVkZDJiNzRj
11
- YjM2ODBkNDA3NWFkZmU3NWViZmVkNWU1Y2Q0MDQyYmVlYjM1MmY=
12
- data.tar.gz: !binary |-
13
- ZjY1MjExMjJlNGU1MDEzYzEwMzgyZTY3MmQ3ZGNkZDI5NWM2OWM2M2VkYmQ4
14
- NTU1NzY3MmE5N2JlODIyODYxM2ZmNjdhYTk3YWNhMmUzMWRhOTc4MWZkODYx
15
- YmYwMTcyMGUxOTg3YTRmYjRkYTcyYjRhYjIwMmFjMTU1Mjg3MjA=