soulless 0.5.1 → 0.5.2
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 +4 -4
- data/README.md +71 -33
- data/lib/soulless/model.rb +25 -12
- data/lib/soulless/version.rb +1 -1
- data/spec/soulless_spec.rb +5 -0
- data/spec/support/dummy_class.rb +9 -3
- data/spec/support/dummy_soulless_inheritance.rb +0 -16
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6c63b43665d1f50ce110a47e5795d8bd3a15c40
|
4
|
+
data.tar.gz: 31f52968fa34dfd97a1432bc7cbc70e0a538d6f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ec6eebae341e1b509848e5c41ac563476e962364fca7cf63eec12d448e70c1a06a7f87d81fbb7721704b763bb99c24fda8ffe26610204d921dc02d7b6c979ea
|
7
|
+
data.tar.gz: 110ccec9dc80a0425e82da7e2ba4bb389fa6e8f016a1553478df82221459d962b5d0547ee375db73d935b0760b610570ca788ad52111ac737b56e75c4c41f468
|
data/README.md
CHANGED
@@ -26,16 +26,16 @@ Just define a plain-old-ruby-object, include Soulless and get crackin'!
|
|
26
26
|
```ruby
|
27
27
|
class UserSignupForm
|
28
28
|
include Soulless.model
|
29
|
-
|
29
|
+
|
30
30
|
attribute :name, String
|
31
31
|
attribute :email, String
|
32
32
|
attribute :password, String
|
33
|
-
|
33
|
+
|
34
34
|
validates :name, presence: true
|
35
|
-
|
35
|
+
|
36
36
|
validates :email, presence: true,
|
37
37
|
uniqueness: { model: User }
|
38
|
-
|
38
|
+
|
39
39
|
validates :password, presence: true,
|
40
40
|
lenght: { is_at_least: 8 }
|
41
41
|
|
@@ -54,7 +54,7 @@ Soulless let's _you_ define what happens when your object is ready to be process
|
|
54
54
|
class UserSignupForm
|
55
55
|
|
56
56
|
...
|
57
|
-
|
57
|
+
|
58
58
|
private
|
59
59
|
def persist!
|
60
60
|
user = User.create!(name: name, email: email, password: password)
|
@@ -83,12 +83,12 @@ Soulless lets you define your validations and manage your errors just like you d
|
|
83
83
|
class UserSignupForm
|
84
84
|
|
85
85
|
...
|
86
|
-
|
86
|
+
|
87
87
|
validates :name, presence: true
|
88
|
-
|
88
|
+
|
89
89
|
validates :email, presence: true,
|
90
90
|
uniqueness: { model: User }
|
91
|
-
|
91
|
+
|
92
92
|
validates :password, presence: true,
|
93
93
|
lenght: { minimum: 8 }
|
94
94
|
|
@@ -120,12 +120,12 @@ If you're using Soulless in Rails it's even possible to validate uniqueness.
|
|
120
120
|
class UserSignupForm
|
121
121
|
|
122
122
|
...
|
123
|
-
|
123
|
+
|
124
124
|
validates :primary_email, presence: true,
|
125
125
|
uniqueness: { model: User, attribute: :email }
|
126
|
-
|
126
|
+
|
127
127
|
...
|
128
|
-
|
128
|
+
|
129
129
|
end
|
130
130
|
```
|
131
131
|
|
@@ -140,15 +140,15 @@ When you need associations use ```has_one``` and ```has_many```. Look familiar?
|
|
140
140
|
```ruby
|
141
141
|
class Person
|
142
142
|
include Soulless.model
|
143
|
-
|
143
|
+
|
144
144
|
attribute :name, String
|
145
|
-
|
145
|
+
|
146
146
|
validates :name, presence: true
|
147
|
-
|
147
|
+
|
148
148
|
has_one :spouse do
|
149
149
|
attribute :name, String
|
150
150
|
end
|
151
|
-
|
151
|
+
|
152
152
|
has_many :friends do
|
153
153
|
attribute :name, String
|
154
154
|
end
|
@@ -168,17 +168,17 @@ It's also possible for an association to inherit from a parent class and then ex
|
|
168
168
|
```ruby
|
169
169
|
class Person
|
170
170
|
include Soulless.model
|
171
|
-
|
171
|
+
|
172
172
|
attribute :name, String
|
173
|
-
|
173
|
+
|
174
174
|
validates :name, presence: true
|
175
|
-
|
175
|
+
|
176
176
|
has_one :spouse, Person do # inherits 'name' and validation from Person
|
177
177
|
attribute :anniversary, DateTime
|
178
|
-
|
178
|
+
|
179
179
|
validates :anniversary, presence: true
|
180
180
|
end
|
181
|
-
|
181
|
+
|
182
182
|
has_many :friends, Person # just inherit from Person, don't extend
|
183
183
|
end
|
184
184
|
```
|
@@ -188,11 +188,11 @@ Your association has access to it's ```parent``` object as well.
|
|
188
188
|
```ruby
|
189
189
|
class Person
|
190
190
|
include Soulless.model
|
191
|
-
|
191
|
+
|
192
192
|
attribute :name, String
|
193
|
-
|
193
|
+
|
194
194
|
validates :name, presence: true
|
195
|
-
|
195
|
+
|
196
196
|
has_one :children do
|
197
197
|
attribute :name, String, default: lambda { "#{parent.name} Jr." }
|
198
198
|
end
|
@@ -205,17 +205,17 @@ When you need to make sure an association is valid before processing the object
|
|
205
205
|
class Person
|
206
206
|
|
207
207
|
...
|
208
|
-
|
208
|
+
|
209
209
|
has_one :spouse do
|
210
210
|
attribute :name, String
|
211
|
-
|
211
|
+
|
212
212
|
validates :name, presence: true
|
213
213
|
end
|
214
|
-
|
214
|
+
|
215
215
|
validates_associated :spouse
|
216
|
-
|
216
|
+
|
217
217
|
...
|
218
|
-
|
218
|
+
|
219
219
|
end
|
220
220
|
|
221
221
|
person = Person.new(name: 'Anthony')
|
@@ -225,6 +225,44 @@ person.errors[:spouse] # => ["is invalid"]
|
|
225
225
|
person.spouse.errors[:name] # => ["can't be blank"]
|
226
226
|
```
|
227
227
|
|
228
|
+
### Callbacks
|
229
|
+
|
230
|
+
Soulless supports the validation and save callbacks. You can use these callbacks
|
231
|
+
as you would on a Rails model.
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
class Person
|
235
|
+
include Soulless.model
|
236
|
+
|
237
|
+
attribute :name, String
|
238
|
+
|
239
|
+
validates :name, presence: true
|
240
|
+
|
241
|
+
before_validation :change_name_to_bart_simpson
|
242
|
+
|
243
|
+
before_save :change_name_to_mickey_mouse
|
244
|
+
|
245
|
+
has_one :children do
|
246
|
+
attribute :name, String, default: lambda { "#{parent.name} Jr." }
|
247
|
+
end
|
248
|
+
|
249
|
+
private
|
250
|
+
def change_name_to_bart_simpson
|
251
|
+
self.name = 'Bart Simpson'
|
252
|
+
end
|
253
|
+
|
254
|
+
def change_name_to_mickey_mouse
|
255
|
+
self.name = 'Mickey Mouse'
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
person = Person.new(name: 'Anthony')
|
260
|
+
person.valid?
|
261
|
+
person.name # => "Bart Simpson"
|
262
|
+
person.save
|
263
|
+
person.name # => "Mickey Mouse"
|
264
|
+
```
|
265
|
+
|
228
266
|
### Dirty Attributes
|
229
267
|
|
230
268
|
Dirty attribute allow you to track changes to a Soulless object before it's saved.
|
@@ -262,7 +300,7 @@ To get rid of this annoying issue Soulless implements the ```#inherit_from(klass
|
|
262
300
|
```ruby
|
263
301
|
class User < ActiveRecord::Base
|
264
302
|
validates :name, presence: true
|
265
|
-
|
303
|
+
|
266
304
|
validates :email, presence: true,
|
267
305
|
uniqueness: { case_insensitive: true }
|
268
306
|
end
|
@@ -271,7 +309,7 @@ end
|
|
271
309
|
```ruby
|
272
310
|
class UserSignupForm
|
273
311
|
include Soulless.model
|
274
|
-
|
312
|
+
|
275
313
|
inherit_from(User)
|
276
314
|
end
|
277
315
|
```
|
@@ -294,7 +332,7 @@ If you don't want to inherit the ```email``` attribute define it using the ```ex
|
|
294
332
|
```ruby
|
295
333
|
class UserSignupForm
|
296
334
|
include Soulless.model
|
297
|
-
|
335
|
+
|
298
336
|
inherit_from(User, exclude: :email)
|
299
337
|
end
|
300
338
|
|
@@ -309,7 +347,7 @@ You can also flip it around if you only want the ```name``` attribute by using t
|
|
309
347
|
```ruby
|
310
348
|
class UserSignupForm
|
311
349
|
include Soulless.model
|
312
|
-
|
350
|
+
|
313
351
|
inherit_from(User, only: :name)
|
314
352
|
end
|
315
353
|
|
@@ -375,4 +413,4 @@ en:
|
|
375
413
|
|
376
414
|
Soulless is maintained and funded by [Sticksnleaves](http://www.sticksnleaves.com)
|
377
415
|
|
378
|
-
Thanks to all of our [contributors](https://github.com/anthonator/soulless/graphs/contributors)
|
416
|
+
Thanks to all of our [contributors](https://github.com/anthonator/soulless/graphs/contributors)
|
data/lib/soulless/model.rb
CHANGED
@@ -4,50 +4,63 @@ module Soulless
|
|
4
4
|
base.class_eval do
|
5
5
|
extend ActiveModel::Naming
|
6
6
|
extend ActiveModel::Translation
|
7
|
+
extend ActiveModel::Callbacks
|
7
8
|
include ActiveModel::Conversion
|
8
9
|
include ActiveModel::Dirty
|
9
10
|
include ActiveModel::Validations
|
10
|
-
|
11
|
+
|
11
12
|
class << self
|
12
13
|
def i18n_scope
|
13
14
|
:soulless
|
14
15
|
end
|
15
16
|
end
|
16
|
-
|
17
|
+
|
18
|
+
define_model_callbacks :validation, :save
|
19
|
+
|
17
20
|
def initialize(params = {})
|
18
21
|
init_accessors(attribute_set.map { |a| a.name })
|
19
22
|
super
|
20
23
|
init_dirty
|
21
24
|
end
|
22
|
-
|
25
|
+
|
23
26
|
def persisted?
|
24
27
|
false
|
25
28
|
end
|
26
|
-
|
29
|
+
|
30
|
+
def valid_with_callbacks?
|
31
|
+
run_callbacks :validation do
|
32
|
+
valid_without_callbacks?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
alias_method_chain :valid?, :callbacks
|
37
|
+
|
27
38
|
def save
|
28
39
|
if valid?
|
29
|
-
|
30
|
-
|
31
|
-
|
40
|
+
run_callbacks :save do
|
41
|
+
persist!
|
42
|
+
changes_applied
|
43
|
+
true
|
44
|
+
end
|
32
45
|
else
|
33
46
|
false
|
34
47
|
end
|
35
48
|
end
|
36
|
-
|
49
|
+
|
37
50
|
def assign_attributes(attributes)
|
38
51
|
deep_update(self, attributes)
|
39
52
|
end
|
40
|
-
|
53
|
+
|
41
54
|
def update_attributes(attributes)
|
42
55
|
assign_attributes(attributes)
|
43
56
|
save
|
44
57
|
end
|
45
|
-
|
58
|
+
|
46
59
|
private
|
47
60
|
def persist!
|
48
61
|
raise 'Method persist! not defined...'
|
49
62
|
end
|
50
|
-
|
63
|
+
|
51
64
|
def deep_update(object, attributes)
|
52
65
|
attributes.each do |key, value|
|
53
66
|
if value.kind_of?(Hash)
|
@@ -60,4 +73,4 @@ module Soulless
|
|
60
73
|
end
|
61
74
|
end
|
62
75
|
end
|
63
|
-
end
|
76
|
+
end
|
data/lib/soulless/version.rb
CHANGED
data/spec/soulless_spec.rb
CHANGED
@@ -53,4 +53,9 @@ describe Soulless do
|
|
53
53
|
it '#persisted? should be false' do
|
54
54
|
expect(@dummy_class.persisted?).to eq(false)
|
55
55
|
end
|
56
|
+
|
57
|
+
it 'should call the before_validation callback' do
|
58
|
+
@dummy_class.save
|
59
|
+
expect(@dummy_class.validation_callback).to eq(true)
|
60
|
+
end
|
56
61
|
end
|
data/spec/support/dummy_class.rb
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
class DummyClass
|
2
2
|
include Soulless.model
|
3
|
-
|
3
|
+
|
4
4
|
attribute :name, String, default: 'Anthony'
|
5
5
|
attribute :email, String
|
6
|
+
attribute :validation_callback, Boolean
|
7
|
+
attribute :save_callback, Boolean
|
6
8
|
attribute :saved, Boolean, default: false
|
7
9
|
|
8
10
|
validates :name, presence: true
|
9
|
-
|
11
|
+
|
12
|
+
before_validation lambda { self.validation_callback = true }
|
13
|
+
|
14
|
+
before_save lambda { self.save_callback = true }
|
15
|
+
|
10
16
|
private
|
11
17
|
def persist!
|
12
18
|
self.saved = true
|
13
19
|
end
|
14
|
-
end
|
20
|
+
end
|
@@ -8,19 +8,3 @@ class DummySoullessInheritance
|
|
8
8
|
self.saved = true
|
9
9
|
end
|
10
10
|
end
|
11
|
-
|
12
|
-
# This is a hack for now. For some reason Travis can't see dummy_class.rb.
|
13
|
-
class DummyClass
|
14
|
-
include Soulless.model
|
15
|
-
|
16
|
-
attribute :name, String, default: 'Anthony'
|
17
|
-
attribute :email, String
|
18
|
-
attribute :saved, Boolean, default: false
|
19
|
-
|
20
|
-
validates :name, presence: true
|
21
|
-
|
22
|
-
private
|
23
|
-
def persist!
|
24
|
-
self.saved = true
|
25
|
-
end
|
26
|
-
end
|