soulless 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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