soulless 0.6.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +12 -18
  3. data/.rspec +1 -1
  4. data/.travis.yml +7 -12
  5. data/CODE_OF_CONDUCT.md +49 -0
  6. data/Gemfile +17 -13
  7. data/LICENSE.txt +17 -18
  8. data/README.md +8 -181
  9. data/Rakefile +4 -8
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/docker-compose.yml +11 -0
  13. data/lib/soulless/attributes.rb +33 -0
  14. data/lib/soulless/callbacks.rb +13 -0
  15. data/lib/soulless/dirty.rb +10 -8
  16. data/lib/soulless/inheritance.rb +120 -124
  17. data/lib/soulless/model.rb +24 -63
  18. data/lib/soulless/validations/uniqueness_validator.rb +7 -8
  19. data/lib/soulless/validations.rb +1 -2
  20. data/lib/soulless/version.rb +1 -1
  21. data/lib/soulless.rb +5 -23
  22. data/soulless.gemspec +12 -13
  23. metadata +30 -173
  24. data/lib/soulless/accessors.rb +0 -51
  25. data/lib/soulless/associations.rb +0 -35
  26. data/lib/soulless/locale/en.yml +0 -30
  27. data/lib/soulless/railtie.rb +0 -7
  28. data/lib/soulless/validations/associated_validator.rb +0 -17
  29. data/spec/associated_validator_spec.rb +0 -31
  30. data/spec/associations_spec.rb +0 -65
  31. data/spec/dirty_spec.rb +0 -54
  32. data/spec/dummy/.gitignore +0 -17
  33. data/spec/dummy/README.rdoc +0 -28
  34. data/spec/dummy/Rakefile +0 -6
  35. data/spec/dummy/app/assets/images/.keep +0 -0
  36. data/spec/dummy/app/assets/javascripts/application.js +0 -16
  37. data/spec/dummy/app/assets/stylesheets/application.css +0 -13
  38. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  39. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  40. data/spec/dummy/app/forms/dummy_form.rb +0 -7
  41. data/spec/dummy/app/helpers/application_helper.rb +0 -2
  42. data/spec/dummy/app/mailers/.keep +0 -0
  43. data/spec/dummy/app/models/.keep +0 -0
  44. data/spec/dummy/app/models/concerns/.keep +0 -0
  45. data/spec/dummy/app/models/dummy_model.rb +0 -6
  46. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  47. data/spec/dummy/bin/bundle +0 -3
  48. data/spec/dummy/bin/rails +0 -4
  49. data/spec/dummy/bin/rake +0 -4
  50. data/spec/dummy/config/application.rb +0 -28
  51. data/spec/dummy/config/boot.rb +0 -6
  52. data/spec/dummy/config/database.yml +0 -25
  53. data/spec/dummy/config/environment.rb +0 -5
  54. data/spec/dummy/config/environments/development.rb +0 -29
  55. data/spec/dummy/config/environments/production.rb +0 -80
  56. data/spec/dummy/config/environments/test.rb +0 -36
  57. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  58. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  59. data/spec/dummy/config/initializers/inflections.rb +0 -16
  60. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  61. data/spec/dummy/config/initializers/secret_token.rb +0 -12
  62. data/spec/dummy/config/initializers/session_store.rb +0 -3
  63. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  64. data/spec/dummy/config/locales/en.yml +0 -23
  65. data/spec/dummy/config/routes.rb +0 -56
  66. data/spec/dummy/config.ru +0 -4
  67. data/spec/dummy/db/migrate/20131106221200_create_dummy_models.rb +0 -11
  68. data/spec/dummy/db/schema.rb +0 -24
  69. data/spec/dummy/db/seeds.rb +0 -7
  70. data/spec/dummy/db/test.sqlite3 +0 -0
  71. data/spec/dummy/lib/assets/.keep +0 -0
  72. data/spec/dummy/lib/tasks/.keep +0 -0
  73. data/spec/dummy/log/.keep +0 -0
  74. data/spec/dummy/public/404.html +0 -58
  75. data/spec/dummy/public/422.html +0 -58
  76. data/spec/dummy/public/500.html +0 -57
  77. data/spec/dummy/public/favicon.ico +0 -0
  78. data/spec/dummy/public/robots.txt +0 -5
  79. data/spec/dummy/vendor/assets/javascripts/.keep +0 -0
  80. data/spec/dummy/vendor/assets/stylesheets/.keep +0 -0
  81. data/spec/inheritance_spec.rb +0 -51
  82. data/spec/soulless_spec.rb +0 -61
  83. data/spec/spec_helper.rb +0 -38
  84. data/spec/support/dummy_association.rb +0 -30
  85. data/spec/support/dummy_class.rb +0 -20
  86. data/spec/support/dummy_model_inheritance.rb +0 -10
  87. data/spec/support/dummy_soulless_inheritance.rb +0 -10
  88. data/spec/support/en.yml +0 -8
  89. data/spec/uniqueness_validator_spec.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46d038cfbf26cbc9feeae03cbd119375fdf31454
4
- data.tar.gz: 983e7052834515c4f6b11365e1009526bd1ad60d
3
+ metadata.gz: afcfdbb737a946c2f08e73de14f36121acf79300
4
+ data.tar.gz: 32c52dad7be7cd46dc5bc63176e24131b06f1909
5
5
  SHA512:
6
- metadata.gz: 1990e836f0368dbd64ce0ad0d725c3595ecd7d154e76543bba3a2f463e1165880fb9631a85dace9e6a4ff7d0447e1b4906156b24dae515c41f34dbe8909320bd
7
- data.tar.gz: cbf63551bd3c48a725f7fd788acc2cff6efac2f64d6024d74a905002d87344363d6452609935a56035e17ce1804cb3e84fa9cd806e7ae99ee16fc4246977bce2
6
+ metadata.gz: 711338a9d4b320d44cf6aff3f5bc340da6b520b31dafd049c1c7749d76df2053b543fd334e1ec95a964fa9e81460e5c41e1397a2a1286916ce3613b68c2bc5c3
7
+ data.tar.gz: 82d067106ed7b91d224ee12e0b89ddbd4b24fc020938e55e2bfd0c2c129089590cbe37d4c21bf8cc320105a4fcb42f5266f7057f4131789981990a079cb8dd90
data/.gitignore CHANGED
@@ -1,20 +1,14 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
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
@@ -1,2 +1,2 @@
1
+ --format documentation
1
2
  --color
2
- --require spec_helper
data/.travis.yml CHANGED
@@ -1,21 +1,16 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
- - 2.0.0
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
- - "RAILS_VERSION=3.2.0"
12
- - "RAILS_VERSION=4.0.0"
13
- - "RAILS_VERSION=master"
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: "RAILS_VERSION=master"
13
+ - env: "ACTIVE_RECORD_VERSION=master"
20
14
  - rvm: ruby-head
21
15
  - rvm: jruby-head
16
+ sudo: false
@@ -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 ar_book_finder.gemspec
3
+ # Specify your gem's dependencies in soulless.gemspec
4
4
  gemspec
5
5
 
6
- rails_version = case ENV['RAILS_VERSION'] || 'default'
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.0'
11
+ '~> 4.2'
11
12
  else
12
- "~> #{ENV['RAILS_VERSION']}"
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
- platforms :jruby do
22
- gem "activerecord-jdbcsqlite3-adapter"
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 'coveralls', require: false
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
- Copyright (c) 2013 Anthony Smith
1
+ The MIT License (MIT)
2
2
 
3
- MIT License
3
+ Copyright (c) 2016 TODO: Write your name
4
4
 
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
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
- included in all copies or substantial portions of the Software.
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
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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, include Soulless and get crackin'!
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 and save callbacks. You can use these callbacks
231
- as you would on a Rails model.
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 'bundler/gem_tasks'
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
2
3
 
3
- require 'rspec/core'
4
- require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- RSpec::Core::RakeTask.new(:spec) do |spec|
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
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ version: '2'
2
+ services:
3
+ lib:
4
+ image: sticksnleaves/ruby-project:2.3
5
+ command: rspec
6
+ volumes:
7
+ - .:/usr/src/app
8
+ - lib.volume:/usr/local/bundle
9
+ volumes:
10
+ lib.volume:
11
+ driver: local
@@ -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
@@ -0,0 +1,13 @@
1
+ module Soulless
2
+ module Callbacks
3
+ def self.prepended(base)
4
+ base.define_model_callbacks :validation
5
+ end
6
+
7
+ def valid?(context = nil)
8
+ run_callbacks :validation do
9
+ super(context)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,13 +1,15 @@
1
1
  module Soulless
2
2
  module Dirty
3
- private
4
- def init_dirty
5
- @changed_attributes = {}
3
+ def apply_changes
4
+ changes_applied
6
5
  end
7
-
8
- def changes_applied
9
- @previously_changed = changed
10
- @changed_attributes = {}
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