soulless 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c3da6f6da8006ae59da0d6b1266c2d2882042d15
4
- data.tar.gz: 59054e7d56f394f0f81bad19f22fd1029efa7198
3
+ metadata.gz: 9c1f160a2c6aaa4efd1cd39b4c5b73683137fce6
4
+ data.tar.gz: beb42ee6b2e877e084709d20a51ffb20b13616ee
5
5
  SHA512:
6
- metadata.gz: b36b03a5ccd3f4e6700caa0b072a8ccf819d4d42c5d4076ef6641ef7a99a35ed335e24dc6a53e115f53abde94e872b1d569919e29d19cc2131ae9b20306ddb46
7
- data.tar.gz: 9ff554ead5d5fe0eaed31d8841e5dbaccc0bdae59dc4afa2f9bcd9b9a25be1c146e7a0436bbc8a7829e96e1a1cd085bb019e7638cd9510f91d4a13b00f7f6b99
6
+ metadata.gz: dd8f3ae03fe3d0a168e1c9b62b4bfb1659fb35898f3c0e960db0ec79be30dfb40f003d9ec8d7db942362b4eb58b9f94bdf337a04e035734c002ac5e1456e5560
7
+ data.tar.gz: 556ccdfa0bdceaad7062ca2b83191cc6c8b57452f61f2c0288b892e73380fccfda272d8dd4b0dafb278fd66768782b4784ee16cc8c47910d840caf35d2d5ada6
data/README.md CHANGED
@@ -183,6 +183,22 @@ class Person
183
183
  end
184
184
  ```
185
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
+
186
202
  When you need to make sure an association is valid before processing the object use ```validates_associated```.
187
203
 
188
204
  ```ruby
@@ -196,6 +212,8 @@ class Person
196
212
  validates :name, presence: true
197
213
  end
198
214
 
215
+ validates_associated :spouse
216
+
199
217
  ...
200
218
 
201
219
  end
@@ -0,0 +1,51 @@
1
+ module Soulless
2
+ module Accessors
3
+ private
4
+ def init_accessors(attributes)
5
+ setup_attribute_methods(attributes)
6
+ define_attribute_accessors(attributes)
7
+ end
8
+
9
+ def setup_attribute_methods(attributes)
10
+ self.class.define_attribute_methods(attributes)
11
+ end
12
+
13
+ def define_attribute_accessors(attributes)
14
+ attributes.each do |attribute|
15
+ define_reader(attribute)
16
+ define_writer(attribute)
17
+ end
18
+ end
19
+
20
+ def define_reader(attribute)
21
+ self.class.send(:define_method, "#{attribute}".to_sym) do
22
+ instance_variable_get("@#{attribute}")
23
+ end
24
+ end
25
+
26
+ def define_writer(attribute)
27
+ self.class.send(:define_method, "#{attribute}=".to_sym) do |value|
28
+ define_dirty_writer(attribute, value)
29
+ super(value)
30
+ define_association_writer(attribute)
31
+ end
32
+ end
33
+
34
+ def define_dirty_writer(attribute, value)
35
+ send("#{attribute}_will_change!") unless instance_variable_get("@#{attribute}") == value
36
+ end
37
+
38
+ def define_association_writer(attribute)
39
+ association_attributes = self.class.association_attributes
40
+ if association_attributes && association_attributes.include?(attribute)
41
+ association = send(attribute)
42
+ return if association.nil?
43
+ if association.kind_of?(Array)
44
+ association.each { |child| child.parent = self }
45
+ else
46
+ association.parent = self
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,7 +1,13 @@
1
1
  module Soulless
2
2
  module Associations
3
3
  def self.included(base)
4
- base.instance_eval do |object|
4
+ base.instance_eval do
5
+ @association_attributes = []
6
+
7
+ class << self
8
+ attr_reader :association_attributes
9
+ end
10
+
5
11
  def has_one(name, superclass = Object, &block)
6
12
  klass = define_virtus_class(name, superclass, &block)
7
13
  send(:attribute, name, klass)
@@ -14,9 +20,11 @@ module Soulless
14
20
 
15
21
  private
16
22
  def define_virtus_class(name, superclass, &block)
23
+ @association_attributes << name
17
24
  klass_name = name.to_s.singularize.classify + '_' + SecureRandom.hex
18
25
  klass = const_set(klass_name, Class.new(superclass))
19
26
  klass.send(:include, Soulless.model) unless klass.included_modules.include?(Model)
27
+ klass.send(:attr_accessor, :parent)
20
28
  klass.instance_eval(&block) if block_given?
21
29
  klass.model_name.instance_variable_set(:@i18n_key, klass.model_name.i18n_key.to_s.gsub(/_[^_]+$/, '').underscore.to_sym)
22
30
  klass
@@ -1,48 +1,13 @@
1
1
  module Soulless
2
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
3
+ private
4
+ def init_dirty
5
+ @changed_attributes = {}
6
+ end
7
+
8
+ def changes_applied
9
+ @previously_changed = changed
10
+ @changed_attributes = {}
46
11
  end
47
12
  end
48
13
  end
@@ -14,6 +14,12 @@ module Soulless
14
14
  end
15
15
  end
16
16
 
17
+ def initialize(params = {})
18
+ super
19
+ init_dirty
20
+ init_accessors(attribute_set.map { |a| a.name })
21
+ end
22
+
17
23
  def persisted?
18
24
  false
19
25
  end
@@ -1,3 +1,3 @@
1
1
  module Soulless
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/soulless.rb CHANGED
@@ -3,6 +3,7 @@ require 'securerandom'
3
3
  require 'active_support'
4
4
  require 'active_model'
5
5
 
6
+ require 'soulless/accessors'
6
7
  require 'soulless/associations'
7
8
  require 'soulless/dirty'
8
9
  require 'soulless/model'
@@ -20,6 +21,7 @@ module Soulless
20
21
  object.send(:include, Associations)
21
22
  object.send(:include, Validations)
22
23
  object.send(:include, Dirty)
24
+ object.send(:include, Accessors)
23
25
  end
24
26
  mod
25
27
  end
@@ -29,6 +29,16 @@ describe Soulless::Associations do
29
29
  @dummy_class.dummy_clone.save
30
30
  @dummy_class.dummy_clone.errors[:name][0].should == 'this is a test'
31
31
  end
32
+
33
+ it 'should have a parent assigned during initialization' do
34
+ @dummy_class = DummyAssociation.new(spouse: { name: 'Megan' })
35
+ @dummy_class.spouse.parent.should == @dummy_class
36
+ end
37
+
38
+ it 'should have a parent assigned when set after initialization' do
39
+ @dummy_class.spouse = { name: 'Megan' }
40
+ @dummy_class.spouse.parent.should == @dummy_class
41
+ end
32
42
  end
33
43
 
34
44
  describe 'has_many' do
@@ -41,5 +51,15 @@ describe Soulless::Associations do
41
51
  @dummy_class.dummy_clones = [{ name: 'Biff' }]
42
52
  @dummy_class.dummy_clones[0].class.name.should match(/\ADummyAssociation::DummyClone/)
43
53
  end
54
+
55
+ it 'should have a parent assigned during initialization' do
56
+ @dummy_class = DummyAssociation.new(friends: [{ name: 'Yaw' }])
57
+ @dummy_class.friends[0].parent.should == @dummy_class
58
+ end
59
+
60
+ it 'should have a parent assigned when set after initialization' do
61
+ @dummy_class.friends = [{ name: 'Yaw' }]
62
+ @dummy_class.friends[0].parent.should == @dummy_class
63
+ end
44
64
  end
45
65
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: soulless
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Smith
@@ -122,6 +122,7 @@ files:
122
122
  - README.md
123
123
  - Rakefile
124
124
  - lib/soulless.rb
125
+ - lib/soulless/accessors.rb
125
126
  - lib/soulless/associations.rb
126
127
  - lib/soulless/dirty.rb
127
128
  - lib/soulless/locale/en.yml