rest-in-peace 2.0.4 → 3.0.0

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.
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=