soulless 0.6.0 → 1.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.
- checksums.yaml +4 -4
- data/.gitignore +12 -18
- data/.rspec +1 -1
- data/.travis.yml +7 -12
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +17 -13
- data/LICENSE.txt +17 -18
- data/README.md +8 -181
- data/Rakefile +4 -8
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docker-compose.yml +11 -0
- data/lib/soulless/attributes.rb +33 -0
- data/lib/soulless/callbacks.rb +13 -0
- data/lib/soulless/dirty.rb +10 -8
- data/lib/soulless/inheritance.rb +120 -124
- data/lib/soulless/model.rb +24 -63
- data/lib/soulless/validations/uniqueness_validator.rb +7 -8
- data/lib/soulless/validations.rb +1 -2
- data/lib/soulless/version.rb +1 -1
- data/lib/soulless.rb +5 -23
- data/soulless.gemspec +12 -13
- metadata +30 -173
- data/lib/soulless/accessors.rb +0 -51
- data/lib/soulless/associations.rb +0 -35
- data/lib/soulless/locale/en.yml +0 -30
- data/lib/soulless/railtie.rb +0 -7
- data/lib/soulless/validations/associated_validator.rb +0 -17
- data/spec/associated_validator_spec.rb +0 -31
- data/spec/associations_spec.rb +0 -65
- data/spec/dirty_spec.rb +0 -54
- data/spec/dummy/.gitignore +0 -17
- data/spec/dummy/README.rdoc +0 -28
- data/spec/dummy/Rakefile +0 -6
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +0 -16
- data/spec/dummy/app/assets/stylesheets/application.css +0 -13
- data/spec/dummy/app/controllers/application_controller.rb +0 -5
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/forms/dummy_form.rb +0 -7
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/models/dummy_model.rb +0 -6
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/bin/bundle +0 -3
- data/spec/dummy/bin/rails +0 -4
- data/spec/dummy/bin/rake +0 -4
- data/spec/dummy/config/application.rb +0 -28
- data/spec/dummy/config/boot.rb +0 -6
- data/spec/dummy/config/database.yml +0 -25
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -29
- data/spec/dummy/config/environments/production.rb +0 -80
- data/spec/dummy/config/environments/test.rb +0 -36
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -4
- data/spec/dummy/config/initializers/inflections.rb +0 -16
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -12
- data/spec/dummy/config/initializers/session_store.rb +0 -3
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy/config/locales/en.yml +0 -23
- data/spec/dummy/config/routes.rb +0 -56
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/db/migrate/20131106221200_create_dummy_models.rb +0 -11
- data/spec/dummy/db/schema.rb +0 -24
- data/spec/dummy/db/seeds.rb +0 -7
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/lib/tasks/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +0 -58
- data/spec/dummy/public/422.html +0 -58
- data/spec/dummy/public/500.html +0 -57
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/robots.txt +0 -5
- data/spec/dummy/vendor/assets/javascripts/.keep +0 -0
- data/spec/dummy/vendor/assets/stylesheets/.keep +0 -0
- data/spec/inheritance_spec.rb +0 -51
- data/spec/soulless_spec.rb +0 -61
- data/spec/spec_helper.rb +0 -38
- data/spec/support/dummy_association.rb +0 -30
- data/spec/support/dummy_class.rb +0 -20
- data/spec/support/dummy_model_inheritance.rb +0 -10
- data/spec/support/dummy_soulless_inheritance.rb +0 -10
- data/spec/support/en.yml +0 -8
- data/spec/uniqueness_validator_spec.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: afcfdbb737a946c2f08e73de14f36121acf79300
|
4
|
+
data.tar.gz: 32c52dad7be7cd46dc5bc63176e24131b06f1909
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 711338a9d4b320d44cf6aff3f5bc340da6b520b31dafd049c1c7749d76df2053b543fd334e1ec95a964fa9e81460e5c41e1397a2a1286916ce3613b68c2bc5c3
|
7
|
+
data.tar.gz: 82d067106ed7b91d224ee12e0b89ddbd4b24fc020938e55e2bfd0c2c129089590cbe37d4c21bf8cc320105a4fcb42f5266f7057f4131789981990a079cb8dd90
|
data/.gitignore
CHANGED
@@ -1,20 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
lib/bundler/man
|
12
|
-
pkg
|
13
|
-
rdoc
|
14
|
-
spec/reports
|
15
|
-
test/tmp
|
16
|
-
test/version_tmp
|
17
|
-
tmp
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/Gemfile.lock
|
4
|
+
/_yardoc/
|
5
|
+
/coverage/
|
6
|
+
/doc/
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
10
|
+
.ruby*
|
18
11
|
.rbenv*
|
19
12
|
.rvmrc
|
20
|
-
.DS_Store
|
13
|
+
.DS_Store
|
14
|
+
*.sqlite3
|
data/.rspec
CHANGED
data/.travis.yml
CHANGED
@@ -1,21 +1,16 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
-
|
4
|
-
- 2.
|
5
|
-
- 2.1.0
|
3
|
+
- 2.2.2
|
4
|
+
- 2.3.0
|
6
5
|
- ruby-head
|
7
|
-
- jruby-19mode
|
8
6
|
- jruby-head
|
9
|
-
- rbx-2
|
10
7
|
env:
|
11
|
-
- "
|
12
|
-
- "
|
13
|
-
- "
|
14
|
-
script:
|
15
|
-
- cd spec/dummy; bundle exec rake db:migrate
|
16
|
-
- cd ../../; bundle exec rake spec
|
8
|
+
- "ACTIVE_RECORD_VERSION=4.2.0"
|
9
|
+
- "ACTIVE_RECORD_VERSION=~5.0.0"
|
10
|
+
- "ACTIVE_RECORD_VERSION=master"
|
17
11
|
matrix:
|
18
12
|
allow_failures:
|
19
|
-
- env: "
|
13
|
+
- env: "ACTIVE_RECORD_VERSION=master"
|
20
14
|
- rvm: ruby-head
|
21
15
|
- rvm: jruby-head
|
16
|
+
sudo: false
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at TODO: Write your email address. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
CHANGED
@@ -1,27 +1,31 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in
|
3
|
+
# Specify your gem's dependencies in soulless.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
|
6
|
+
active_record_version = case ENV['ACTIVE_RECORD_VERSION'] || 'default'
|
7
|
+
|
7
8
|
when 'master'
|
8
9
|
{ git: 'https://github.com/rails/rails.git' }
|
9
10
|
when 'default'
|
10
|
-
'~> 4.
|
11
|
+
'~> 4.2'
|
11
12
|
else
|
12
|
-
"~> #{ENV['
|
13
|
-
end
|
14
|
-
|
15
|
-
gem 'rails', rails_version
|
16
|
-
|
17
|
-
platforms :ruby do
|
18
|
-
gem 'sqlite3'
|
13
|
+
"~> #{ENV['ACTIVE_RECORD_VERSION']}"
|
19
14
|
end
|
20
15
|
|
21
|
-
|
22
|
-
gem
|
16
|
+
group :test do
|
17
|
+
gem 'coveralls', require: false
|
18
|
+
gem 'simplecov', require: false
|
23
19
|
end
|
24
20
|
|
25
21
|
group :development do
|
26
|
-
gem '
|
22
|
+
gem 'activerecord', '>= 4.2.0', '< 5.1'
|
23
|
+
|
24
|
+
platforms :ruby do
|
25
|
+
gem 'sqlite3'
|
26
|
+
end
|
27
|
+
|
28
|
+
platforms :jruby do
|
29
|
+
gem "activerecord-jdbcsqlite3-adapter"
|
30
|
+
end
|
27
31
|
end
|
data/LICENSE.txt
CHANGED
@@ -1,22 +1,21 @@
|
|
1
|
-
|
1
|
+
The MIT License (MIT)
|
2
2
|
|
3
|
-
|
3
|
+
Copyright (c) 2016 TODO: Write your name
|
4
4
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
the following conditions:
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
12
11
|
|
13
|
-
The above copyright notice and this permission notice shall be
|
14
|
-
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
15
14
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
OF
|
22
|
-
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -21,12 +21,10 @@ Or install it yourself as:
|
|
21
21
|
|
22
22
|
## Usage
|
23
23
|
|
24
|
-
Just define a plain-old-ruby-object,
|
24
|
+
Just define a plain-old-ruby-object, inherit from `Soulless::Model` and get crackin'!
|
25
25
|
|
26
26
|
```ruby
|
27
|
-
class UserSignupForm
|
28
|
-
include Soulless.model
|
29
|
-
|
27
|
+
class UserSignupForm < Soulless::Model
|
30
28
|
attribute :name, String
|
31
29
|
attribute :email, String
|
32
30
|
attribute :password, String
|
@@ -38,40 +36,6 @@ class UserSignupForm
|
|
38
36
|
|
39
37
|
validates :password, presence: true,
|
40
38
|
lenght: { is_at_least: 8 }
|
41
|
-
|
42
|
-
private
|
43
|
-
def persist!
|
44
|
-
# Define what to do when this form is ready to be saved.
|
45
|
-
end
|
46
|
-
end
|
47
|
-
```
|
48
|
-
|
49
|
-
### Processing an Object
|
50
|
-
|
51
|
-
Soulless let's _you_ define what happens when your object is ready to be processed.
|
52
|
-
|
53
|
-
```ruby
|
54
|
-
class UserSignupForm
|
55
|
-
|
56
|
-
...
|
57
|
-
|
58
|
-
private
|
59
|
-
def persist!
|
60
|
-
user = User.create!(name: name, email: email, password: password)
|
61
|
-
UserMailer.send_activation_code(user).deliver
|
62
|
-
user.charge_card!
|
63
|
-
end
|
64
|
-
end
|
65
|
-
```
|
66
|
-
|
67
|
-
Process your Soulless object by calling ```save```. Just like a Rails model!
|
68
|
-
|
69
|
-
```ruby
|
70
|
-
form = UserSignupForm.new(name: name, email: email, password: passord)
|
71
|
-
if form.save
|
72
|
-
# Called persist! and all is good!
|
73
|
-
else
|
74
|
-
# Looks like a validation failed. Try again.
|
75
39
|
end
|
76
40
|
```
|
77
41
|
|
@@ -133,106 +97,13 @@ Just let the validator know what ActiveRecord model to use when performing the v
|
|
133
97
|
|
134
98
|
If your Soulless object attribute doesn't match up to the ActiveRecord model attribute just map it using the ```attribute``` option.
|
135
99
|
|
136
|
-
### ```has_one``` and ```has_many``` Associations
|
137
|
-
|
138
|
-
When you need associations use ```has_one``` and ```has_many```. Look familiar?
|
139
|
-
|
140
|
-
```ruby
|
141
|
-
class Person
|
142
|
-
include Soulless.model
|
143
|
-
|
144
|
-
attribute :name, String
|
145
|
-
|
146
|
-
validates :name, presence: true
|
147
|
-
|
148
|
-
has_one :spouse do
|
149
|
-
attribute :name, String
|
150
|
-
end
|
151
|
-
|
152
|
-
has_many :friends do
|
153
|
-
attribute :name, String
|
154
|
-
end
|
155
|
-
end
|
156
|
-
```
|
157
|
-
|
158
|
-
You can set ```has_one``` and ```has_many``` attributes by setting their values hashes and hash arrays.
|
159
|
-
|
160
|
-
```ruby
|
161
|
-
person = Person.new(name: 'Anthony')
|
162
|
-
person.spouse = { name: 'Megan' }
|
163
|
-
person.friends = [{ name: 'Yaw' }, { name: 'Biff' }]
|
164
|
-
```
|
165
|
-
|
166
|
-
It's also possible for an association to inherit from a parent class and then extend functionality.
|
167
|
-
|
168
|
-
```ruby
|
169
|
-
class Person
|
170
|
-
include Soulless.model
|
171
|
-
|
172
|
-
attribute :name, String
|
173
|
-
|
174
|
-
validates :name, presence: true
|
175
|
-
|
176
|
-
has_one :spouse, Person do # inherits 'name' and validation from Person
|
177
|
-
attribute :anniversary, DateTime
|
178
|
-
|
179
|
-
validates :anniversary, presence: true
|
180
|
-
end
|
181
|
-
|
182
|
-
has_many :friends, Person # just inherit from Person, don't extend
|
183
|
-
end
|
184
|
-
```
|
185
|
-
|
186
|
-
Your association has access to it's ```parent``` object as well.
|
187
|
-
|
188
|
-
```ruby
|
189
|
-
class Person
|
190
|
-
include Soulless.model
|
191
|
-
|
192
|
-
attribute :name, String
|
193
|
-
|
194
|
-
validates :name, presence: true
|
195
|
-
|
196
|
-
has_one :children do
|
197
|
-
attribute :name, String, default: lambda { "#{parent.name} Jr." }
|
198
|
-
end
|
199
|
-
end
|
200
|
-
```
|
201
|
-
|
202
|
-
When you need to make sure an association is valid before processing the object use ```validates_associated```.
|
203
|
-
|
204
|
-
```ruby
|
205
|
-
class Person
|
206
|
-
|
207
|
-
...
|
208
|
-
|
209
|
-
has_one :spouse do
|
210
|
-
attribute :name, String
|
211
|
-
|
212
|
-
validates :name, presence: true
|
213
|
-
end
|
214
|
-
|
215
|
-
validates_associated :spouse
|
216
|
-
|
217
|
-
...
|
218
|
-
|
219
|
-
end
|
220
|
-
|
221
|
-
person = Person.new(name: 'Anthony')
|
222
|
-
person.spouse = { name: nil }
|
223
|
-
person.valid? # => false
|
224
|
-
person.errors[:spouse] # => ["is invalid"]
|
225
|
-
person.spouse.errors[:name] # => ["can't be blank"]
|
226
|
-
```
|
227
|
-
|
228
100
|
### Callbacks
|
229
101
|
|
230
|
-
Soulless supports the validation
|
231
|
-
|
102
|
+
Soulless supports the validation callback. You can use this callback as you
|
103
|
+
would on a Rails model.
|
232
104
|
|
233
105
|
```ruby
|
234
|
-
class Person
|
235
|
-
include Soulless.model
|
106
|
+
class Person < Soulless::Model
|
236
107
|
|
237
108
|
attribute :name, String
|
238
109
|
|
@@ -240,27 +111,15 @@ class Person
|
|
240
111
|
|
241
112
|
before_validation :change_name_to_bart_simpson
|
242
113
|
|
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
114
|
private
|
250
115
|
def change_name_to_bart_simpson
|
251
116
|
self.name = 'Bart Simpson'
|
252
117
|
end
|
253
|
-
|
254
|
-
def change_name_to_mickey_mouse
|
255
|
-
self.name = 'Mickey Mouse'
|
256
|
-
end
|
257
118
|
end
|
258
119
|
|
259
120
|
person = Person.new(name: 'Anthony')
|
260
121
|
person.valid?
|
261
122
|
person.name # => "Bart Simpson"
|
262
|
-
person.save
|
263
|
-
person.name # => "Mickey Mouse"
|
264
123
|
```
|
265
124
|
|
266
125
|
### Dirty Attributes
|
@@ -278,19 +137,6 @@ person.name_was # => "Anthony"
|
|
278
137
|
person.name_change # => ["Anthony", "Peter Parker"]
|
279
138
|
```
|
280
139
|
|
281
|
-
Works on ```has_one``` and ```has_many``` too.
|
282
|
-
|
283
|
-
```ruby
|
284
|
-
person.spouse.name = 'Gwen Stacy'
|
285
|
-
person.spouse.changed? # => true
|
286
|
-
person.spouse.changed # => ["name"]
|
287
|
-
person.spouse.changes # => { name: ["Mary Jane Watson", "Gwen Stacy"] }
|
288
|
-
person.spouse.name_changed? # => true
|
289
|
-
person.spouse.name_was # => "Mary Jane Watson"
|
290
|
-
person.spouse.name_change # => ["Mary Jane Watson", "Gwen Stacy"]
|
291
|
-
person.changed? # => false
|
292
|
-
```
|
293
|
-
|
294
140
|
### Inheritance
|
295
141
|
|
296
142
|
One of the biggest pitfalls of the form object pattern is duplication of code. It's not uncommon for a form object to define attributes and validations that are identical to the model it represets.
|
@@ -307,9 +153,7 @@ end
|
|
307
153
|
```
|
308
154
|
|
309
155
|
```ruby
|
310
|
-
class UserSignupForm
|
311
|
-
include Soulless.model
|
312
|
-
|
156
|
+
class UserSignupForm < Soulless::Model
|
313
157
|
inherit_from(User)
|
314
158
|
end
|
315
159
|
```
|
@@ -330,9 +174,7 @@ The ```#inherit_from(klass, options = {})``` method also allows you to provide o
|
|
330
174
|
If you don't want to inherit the ```email``` attribute define it using the ```exclude``` option.
|
331
175
|
|
332
176
|
```ruby
|
333
|
-
class UserSignupForm
|
334
|
-
include Soulless.model
|
335
|
-
|
177
|
+
class UserSignupForm < Soulless::Model
|
336
178
|
inherit_from(User, exclude: :email)
|
337
179
|
end
|
338
180
|
|
@@ -345,9 +187,7 @@ form.errors.messages # => { name: ["can't be blank"] }
|
|
345
187
|
You can also flip it around if you only want the ```name``` attribute by using the ```only``` option.
|
346
188
|
|
347
189
|
```ruby
|
348
|
-
class UserSignupForm
|
349
|
-
include Soulless.model
|
350
|
-
|
190
|
+
class UserSignupForm < Soulless::Model
|
351
191
|
inherit_from(User, only: :name)
|
352
192
|
end
|
353
193
|
|
@@ -387,19 +227,6 @@ en:
|
|
387
227
|
blank: "there's nothing here"
|
388
228
|
```
|
389
229
|
|
390
|
-
For attributes defined as ```has_one``` and ```has_many``` associations use the enclosing class as the locale key's namespace.
|
391
|
-
|
392
|
-
```yaml
|
393
|
-
en:
|
394
|
-
soulless:
|
395
|
-
errors:
|
396
|
-
models:
|
397
|
-
person/spouse:
|
398
|
-
attributes:
|
399
|
-
name:
|
400
|
-
blank: "there's nothing here"
|
401
|
-
```
|
402
|
-
|
403
230
|
## Contributing
|
404
231
|
|
405
232
|
1. Fork it
|
data/Rakefile
CHANGED
@@ -1,10 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
2
3
|
|
3
|
-
|
4
|
-
require 'rspec/core/rake_task'
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
|
6
|
-
|
7
|
-
spec.pattern = FileList['spec/**/*_spec.rb']
|
8
|
-
end
|
9
|
-
|
10
|
-
task default: :spec
|
6
|
+
task :default => :spec
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "soulless"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/docker-compose.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Soulless
|
2
|
+
module Attributes
|
3
|
+
module ClassMethods
|
4
|
+
def attribute(name, type = nil, options = {})
|
5
|
+
super(name, type, options) if super
|
6
|
+
|
7
|
+
define_attribute_methods(name)
|
8
|
+
|
9
|
+
define_reader(name)
|
10
|
+
define_writer(name)
|
11
|
+
end
|
12
|
+
|
13
|
+
def define_reader(attribute)
|
14
|
+
define_method(attribute.to_sym) do
|
15
|
+
attribute_set[attribute.to_sym].get(self)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def define_writer(attribute)
|
20
|
+
define_method("#{attribute}=".to_sym) do |value|
|
21
|
+
send("#{attribute}_will_change!") unless value == attribute_set[attribute.to_sym].get(self)
|
22
|
+
super(value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.prepended(base)
|
28
|
+
class << base
|
29
|
+
prepend ClassMethods
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/soulless/dirty.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
module Soulless
|
2
2
|
module Dirty
|
3
|
-
|
4
|
-
|
5
|
-
@changed_attributes = {}
|
3
|
+
def apply_changes
|
4
|
+
changes_applied
|
6
5
|
end
|
7
|
-
|
8
|
-
def
|
9
|
-
|
10
|
-
|
6
|
+
|
7
|
+
def reload_changes!
|
8
|
+
clear_changes_information
|
9
|
+
end
|
10
|
+
|
11
|
+
def rollback_changes!(attributes = changed)
|
12
|
+
restore_attributes(attributes)
|
11
13
|
end
|
12
14
|
end
|
13
|
-
end
|
15
|
+
end
|