soulless 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/README.md +28 -53
- data/lib/soulless/dirty.rb +48 -0
- data/lib/soulless/model.rb +3 -1
- data/lib/soulless/version.rb +1 -1
- data/lib/soulless.rb +5 -15
- data/spec/dirty_spec.rb +56 -0
- data/spec/soulless_spec.rb +5 -0
- data/spec/spec_helper.rb +2 -2
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3da6f6da8006ae59da0d6b1266c2d2882042d15
|
4
|
+
data.tar.gz: 59054e7d56f394f0f81bad19f22fd1029efa7198
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b36b03a5ccd3f4e6700caa0b072a8ccf819d4d42c5d4076ef6641ef7a99a35ed335e24dc6a53e115f53abde94e872b1d569919e29d19cc2131ae9b20306ddb46
|
7
|
+
data.tar.gz: 9ff554ead5d5fe0eaed31d8841e5dbaccc0bdae59dc4afa2f9bcd9b9a25be1c146e7a0436bbc8a7829e96e1a1cd085bb019e7638cd9510f91d4a13b00f7f6b99
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -46,59 +46,6 @@ class UserSignupForm
|
|
46
46
|
end
|
47
47
|
```
|
48
48
|
|
49
|
-
### Default Values
|
50
|
-
|
51
|
-
When defining attributes it's possible to specify default values.
|
52
|
-
|
53
|
-
```ruby
|
54
|
-
class UserSignupForm
|
55
|
-
|
56
|
-
...
|
57
|
-
|
58
|
-
attribute :name, String, default: 'Anthony'
|
59
|
-
|
60
|
-
...
|
61
|
-
end
|
62
|
-
```
|
63
|
-
|
64
|
-
### Embedded Values
|
65
|
-
|
66
|
-
It's possible to use other Soulless objects as attribute types.
|
67
|
-
|
68
|
-
```ruby
|
69
|
-
class User
|
70
|
-
include Soulless.model
|
71
|
-
|
72
|
-
attribute :name, String
|
73
|
-
attribute :email, String
|
74
|
-
attribute :password, String
|
75
|
-
end
|
76
|
-
|
77
|
-
class UserSignupForm
|
78
|
-
include Soulless.model
|
79
|
-
|
80
|
-
attribute :user, User
|
81
|
-
end
|
82
|
-
```
|
83
|
-
|
84
|
-
### Collection Coercions
|
85
|
-
|
86
|
-
Define collections with specific types.
|
87
|
-
|
88
|
-
```ruby
|
89
|
-
class PhoneNumber
|
90
|
-
include Soulless.model
|
91
|
-
|
92
|
-
attribute :number, String
|
93
|
-
end
|
94
|
-
|
95
|
-
class Person
|
96
|
-
include Soulless.model
|
97
|
-
|
98
|
-
attribute :phone_numbers, Array[PhoneNumber]
|
99
|
-
end
|
100
|
-
```
|
101
|
-
|
102
49
|
### Processing an Object
|
103
50
|
|
104
51
|
Soulless let's _you_ define what happens when your object is ready to be processed.
|
@@ -260,6 +207,34 @@ person.errors[:spouse] # => ["is invalid"]
|
|
260
207
|
person.spouse.errors[:name] # => ["can't be blank"]
|
261
208
|
```
|
262
209
|
|
210
|
+
### Dirty Attributes
|
211
|
+
|
212
|
+
Dirty attribute allow you to track changes to a Soulless object before it's saved.
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
person = Person.name(name: "Anthony", spouse: { name: "Mary Jane Watson" })
|
216
|
+
person.name = 'Peter Parker'
|
217
|
+
person.changed? # => true
|
218
|
+
person.changed # => ["name"]
|
219
|
+
person.changes # => { name: ["Anthony", "Peter Parker"] }
|
220
|
+
person.name_changed? # => true
|
221
|
+
person.name_was # => "Anthony"
|
222
|
+
person.name_change # => ["Anthony", "Peter Parker"]
|
223
|
+
```
|
224
|
+
|
225
|
+
Works on ```has_one``` and ```has_many``` too.
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
person.spouse.name = 'Gwen Stacy'
|
229
|
+
person.spouse.changed? # => true
|
230
|
+
person.spouse.changed # => ["name"]
|
231
|
+
person.spouse.changes # => { name: ["Mary Jane Watson", "Gwen Stacy"] }
|
232
|
+
person.spouse.name_changed? # => true
|
233
|
+
person.spouse.name_was # => "Mary Jane Watson"
|
234
|
+
person.spouse.name_change # => ["Mary Jane Watson", "Gwen Stacy"]
|
235
|
+
person.changed? # => false
|
236
|
+
```
|
237
|
+
|
263
238
|
### I18n
|
264
239
|
|
265
240
|
Define locales similar to how you would define them in Rails.
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Soulless
|
2
|
+
module Dirty
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
def initialize(params = {})
|
6
|
+
super
|
7
|
+
init_dirty(attribute_set.map { |a| a.name })
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
def init_dirty(attributes)
|
12
|
+
define_dirty_attributes(attributes)
|
13
|
+
define_dirty_methods(attributes)
|
14
|
+
@changed_attributes = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def changes_applied
|
18
|
+
@previously_changed = changed
|
19
|
+
@changed_attributes = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_dirty_attributes(attributes)
|
23
|
+
self.class.define_attribute_methods(attributes)
|
24
|
+
end
|
25
|
+
|
26
|
+
def define_dirty_methods(attributes)
|
27
|
+
attributes.each do |attribute|
|
28
|
+
define_dirty_reader(attribute)
|
29
|
+
define_dirty_writer(attribute)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def define_dirty_reader(name)
|
34
|
+
self.class.send(:define_method, "#{name}".to_sym) do
|
35
|
+
instance_variable_get("@#{name}")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def define_dirty_writer(name)
|
40
|
+
self.class.send(:define_method, "#{name}=".to_sym) do |value|
|
41
|
+
send("#{name}_will_change!") unless instance_variable_get("@#{name}") == value
|
42
|
+
super(value)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/soulless/model.rb
CHANGED
@@ -4,8 +4,9 @@ module Soulless
|
|
4
4
|
base.class_eval do
|
5
5
|
extend ActiveModel::Naming
|
6
6
|
extend ActiveModel::Translation
|
7
|
-
include ActiveModel::Validations
|
8
7
|
include ActiveModel::Conversion
|
8
|
+
include ActiveModel::Dirty
|
9
|
+
include ActiveModel::Validations
|
9
10
|
|
10
11
|
class << self
|
11
12
|
def i18n_scope
|
@@ -20,6 +21,7 @@ module Soulless
|
|
20
21
|
def save
|
21
22
|
if valid?
|
22
23
|
persist!
|
24
|
+
changes_applied
|
23
25
|
true
|
24
26
|
else
|
25
27
|
false
|
data/lib/soulless/version.rb
CHANGED
data/lib/soulless.rb
CHANGED
@@ -1,22 +1,11 @@
|
|
1
1
|
require 'virtus'
|
2
2
|
require 'securerandom'
|
3
|
-
require 'active_support
|
4
|
-
require '
|
5
|
-
require 'active_support/core_ext/module/delegation'
|
6
|
-
require 'active_support/callbacks'
|
7
|
-
require 'active_support/concern'
|
8
|
-
require 'active_support/inflector'
|
9
|
-
require 'active_model/naming'
|
10
|
-
require 'active_model/translation'
|
11
|
-
require 'active_model/callbacks'
|
12
|
-
require 'active_model/validator'
|
13
|
-
require 'active_model/errors'
|
14
|
-
require 'active_model/validations'
|
15
|
-
require 'active_model/conversion'
|
16
|
-
require 'active_model/version'
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_model'
|
17
5
|
|
18
|
-
require 'soulless/model'
|
19
6
|
require 'soulless/associations'
|
7
|
+
require 'soulless/dirty'
|
8
|
+
require 'soulless/model'
|
20
9
|
require 'soulless/validations'
|
21
10
|
require 'soulless/version'
|
22
11
|
|
@@ -30,6 +19,7 @@ module Soulless
|
|
30
19
|
object.send(:include, Model)
|
31
20
|
object.send(:include, Associations)
|
32
21
|
object.send(:include, Validations)
|
22
|
+
object.send(:include, Dirty)
|
33
23
|
end
|
34
24
|
mod
|
35
25
|
end
|
data/spec/dirty_spec.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Soulless::Dirty do
|
4
|
+
before(:each) do
|
5
|
+
@dummy_class = DummyClass.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should support dirty attributes' do
|
9
|
+
defined?(:changed?).should be_true
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should record attribute changes' do
|
13
|
+
@dummy_class.name_changed?.should be_false
|
14
|
+
@dummy_class.name = 'Yaw'
|
15
|
+
@dummy_class.name_changed?.should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should correctly record changes to objects with initialized values' do
|
19
|
+
@dummy_class = DummyClass.new(name: 'Biff')
|
20
|
+
@dummy_class.name_changed?.should be_false
|
21
|
+
@dummy_class.name = 'Anthony'
|
22
|
+
@dummy_class.name_changed?.should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should record changes in a has_one association' do
|
26
|
+
@dummy_association = DummyAssociation.new(spouse: { name: 'Megan' })
|
27
|
+
@dummy_association.spouse.name_changed?.should be_false
|
28
|
+
@dummy_association.spouse.name = 'Megan Jr'
|
29
|
+
@dummy_association.spouse.name_changed?.should be_true
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should record changes in a has_many association' do
|
33
|
+
@dummy_association = DummyAssociation.new(friends: [{ name: 'Yaw' }])
|
34
|
+
@dummy_association.friends[0].name_changed?.should be_false
|
35
|
+
@dummy_association.friends[0].name = 'Biff'
|
36
|
+
@dummy_association.friends[0].name_changed?.should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should reset its dirty state when saved' do
|
40
|
+
@dummy_class.name = 'Biff'
|
41
|
+
@dummy_class.save
|
42
|
+
@dummy_class.changed?.should be_false
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should not reset its dirty state if validations fail' do
|
46
|
+
@dummy_class.name = nil
|
47
|
+
@dummy_class.save
|
48
|
+
@dummy_class.changed?.should be_true
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should record changed made before #save was called in previous_changes' do
|
52
|
+
@dummy_class.name = 'Biff'
|
53
|
+
@dummy_class.save
|
54
|
+
@dummy_class.previous_changes.should_not be_empty
|
55
|
+
end
|
56
|
+
end
|
data/spec/soulless_spec.rb
CHANGED
@@ -16,6 +16,11 @@ describe Soulless do
|
|
16
16
|
@dummy_class.saved.should be_true
|
17
17
|
end
|
18
18
|
|
19
|
+
it 'should call #persist! when #update_attributes is called' do
|
20
|
+
@dummy_class.update_attributes(name: 'Biff')
|
21
|
+
@dummy_class.saved.should be_true
|
22
|
+
end
|
23
|
+
|
19
24
|
it 'should not call #persist! if attributes are invalid' do
|
20
25
|
@dummy_class.name = nil
|
21
26
|
@dummy_class.save.should be_false
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: soulless
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anthony Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -123,6 +123,7 @@ files:
|
|
123
123
|
- Rakefile
|
124
124
|
- lib/soulless.rb
|
125
125
|
- lib/soulless/associations.rb
|
126
|
+
- lib/soulless/dirty.rb
|
126
127
|
- lib/soulless/locale/en.yml
|
127
128
|
- lib/soulless/model.rb
|
128
129
|
- lib/soulless/validations.rb
|
@@ -132,6 +133,7 @@ files:
|
|
132
133
|
- soulless.gemspec
|
133
134
|
- spec/associated_validator_spec.rb
|
134
135
|
- spec/associations_spec.rb
|
136
|
+
- spec/dirty_spec.rb
|
135
137
|
- spec/dummy/.gitignore
|
136
138
|
- spec/dummy/README.rdoc
|
137
139
|
- spec/dummy/Rakefile
|
@@ -214,6 +216,7 @@ summary: Create Rails style models without the database.
|
|
214
216
|
test_files:
|
215
217
|
- spec/associated_validator_spec.rb
|
216
218
|
- spec/associations_spec.rb
|
219
|
+
- spec/dirty_spec.rb
|
217
220
|
- spec/dummy/.gitignore
|
218
221
|
- spec/dummy/README.rdoc
|
219
222
|
- spec/dummy/Rakefile
|