passive_record 0.1.0 → 0.1.1

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: bae7d40e8ae674093246626a73f247c24cfdd442
4
- data.tar.gz: d02d5675a5ec0857d1e15e24a7fb7149a880d362
3
+ metadata.gz: e925955215f05a8a105989c34bbd462e730676b9
4
+ data.tar.gz: cdc707806939051ec202a2962bef24f88ef4921b
5
5
  SHA512:
6
- metadata.gz: b0a66bb01e629e8b313aad8febe2085ad4b00a36af23e925393068501d01c988fe3b001d20822c640b4fcdbe7224b192bc93f23cacd78dbbbbbe743cb29d40c5
7
- data.tar.gz: 23ccde9e6bc44c98080e854746b4078edf4585c4b59e53a278754c234e1c7d99add543e04dc7d5199ab699fd5e887d1f3e8a42a2025c19e416e3c63c9141f090
6
+ metadata.gz: 1da3e90a67086a5b536549d46663c6afeb50791f334ddaee2edaf4a4670980fa25ffe10dd49183d4d037dcb261cf0872fa157651c7e2a77c99e15830625d14c3
7
+ data.tar.gz: 0559e101eff6e7e1dde11ae84bcdedc4f75096889670ce2d1e388afab1a5c63405f8a5b9c685f3e71c28de957b33662b94464c8b9b29a9a171dded3a0208bbe3
data/README.md CHANGED
@@ -15,7 +15,8 @@ We implement a simplified subset of AR's interface in pure Ruby.
15
15
  ## Why?
16
16
 
17
17
  Do you need to track objects by ID and look them up again,
18
- or look them up based on attributes, or even utilize some limited relational semantics,
18
+ or look them up based on attributes,
19
+ or even utilize some relational semantics,
19
20
  but have no real need for persistence?
20
21
 
21
22
  PassiveRecord may be right for you.
@@ -23,10 +24,12 @@ PassiveRecord may be right for you.
23
24
 
24
25
  ## Features
25
26
 
26
- - Just 'include PassiveRecord' to activate a PORO in the system
27
27
  - New objects are tracked and assigned IDs
28
- - Query on attributes and simple relations (belongs_to, has_one, has_many)
28
+ - Build relationships with belongs_to, has_one and has_many
29
+ - Query on attributes and associations
30
+ - Supports many-to-many and self-referential relationships
29
31
  - No database required!
32
+ - Just `include PassiveRecord` to activate a PORO in the system
30
33
 
31
34
  ## Examples
32
35
 
@@ -70,6 +73,7 @@ PassiveRecord may be right for you.
70
73
 
71
74
  $ gem install passive_record
72
75
 
76
+
73
77
  ## Synopsis
74
78
 
75
79
  $ passive_record
@@ -6,6 +6,7 @@ require 'passive_record/core/identifier'
6
6
  require 'passive_record/core/query'
7
7
 
8
8
  require 'passive_record/associations'
9
+ require 'passive_record/hooks'
9
10
 
10
11
  module PassiveRecord
11
12
  def self.included(base)
@@ -52,6 +53,7 @@ module PassiveRecord
52
53
  module ClassMethods
53
54
  include PassiveRecord::Core
54
55
  include PassiveRecord::Associations
56
+ include PassiveRecord::Hooks
55
57
 
56
58
  include Enumerable
57
59
  extend Forwardable
@@ -76,17 +78,21 @@ module PassiveRecord
76
78
  end
77
79
 
78
80
  def create(attrs={})
79
- registrable = new #(*args)
81
+ instance = new
80
82
 
81
- registrable.singleton_class.class_eval { attr_accessor :id }
82
- registrable.send(:"id=", Identifier.generate)
83
- register(registrable)
83
+ instance.singleton_class.class_eval { attr_accessor :id }
84
+ instance.send(:"id=", Identifier.generate)
85
+ register(instance)
84
86
 
85
87
  attrs.each do |(k,v)|
86
- registrable.send("#{k}=", v)
88
+ instance.send("#{k}=", v)
87
89
  end
88
90
 
89
- registrable
91
+ after_create_hooks.each do |hook|
92
+ hook.run(instance)
93
+ end
94
+
95
+ instance
90
96
  end
91
97
 
92
98
  protected
@@ -0,0 +1,37 @@
1
+ module PassiveRecord
2
+ module Hooks
3
+ class Hook
4
+ def initialize(*meth_syms,&blk)
5
+ @methods_to_call = meth_syms
6
+ @block_to_invoke = blk
7
+ end
8
+
9
+ def run(instance)
10
+ @methods_to_call.each do |meth|
11
+ instance.send(meth)
12
+ end
13
+
14
+ unless @block_to_invoke.nil?
15
+ instance.instance_eval(&@block_to_invoke)
16
+ end
17
+ end
18
+ end
19
+
20
+ def hooks
21
+ @hooks ||= {}
22
+ end
23
+
24
+ def after_hooks
25
+ hooks[:after] ||= {}
26
+ end
27
+
28
+ def after_create_hooks
29
+ after_hooks[:create] ||= []
30
+ end
31
+
32
+ def after_create(*meth_syms, &blk)
33
+ hook = Hook.new(*meth_syms,&blk)
34
+ after_create_hooks.push(hook)
35
+ end
36
+ end
37
+ end
@@ -1,4 +1,4 @@
1
1
  module PassiveRecord
2
2
  # passive_record version
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
  end
@@ -11,95 +11,115 @@ describe Model do
11
11
  end
12
12
  end
13
13
 
14
- describe "#count" do
15
- it 'should indicate the size of the models list' do
16
- expect { SimpleModel.create }.to change { SimpleModel.count }.by(1)
14
+ context 'should be enumerable over models' do
15
+ describe "#count" do
16
+ it 'should indicate the size of the models list' do
17
+ expect { SimpleModel.create }.to change { SimpleModel.count }.by(1)
18
+ end
17
19
  end
18
20
  end
19
21
 
20
- describe "#find_by" do
21
- it 'should be retrievable by query' do
22
- expect(SimpleModel.find_by(foo: 'foo_value')).to eq(model)
22
+ context 'querying by attributes' do
23
+ describe "#find_by" do
24
+ it 'should be retrievable by query' do
25
+ expect(SimpleModel.find_by(foo: 'foo_value')).to eq(model)
26
+ end
23
27
  end
24
28
  end
25
- end
26
29
 
27
- context 'one-to-one relationships' do
28
- let(:child) { Child.create }
29
- let(:another_child) { Child.create }
30
+ xcontext 'querying by associations'
31
+ end
30
32
 
31
- it 'should create children' do
32
- expect { child.create_dog }.to change { Dog.count }.by(1)
33
- expect(child.dog).to eq(Dog.first)
34
- end
33
+ context 'hooks' do
34
+ context 'after create hooks' do
35
+ it 'should use a symbol to invoke a method' do
36
+ expect(Child.create.name).to eq("Alice")
37
+ end
35
38
 
36
- it 'should have inverse relationships' do
37
- dog = child.create_dog
38
- expect(dog.child).to eq(child)
39
- another_dog = another_child.create_dog
40
- expect(another_dog.child).to eq(another_child)
39
+ it 'should use a block' do
40
+ expect(Parent.create.created_at).to be_a(Time)
41
+ end
41
42
  end
42
43
  end
43
44
 
44
- context 'one-to-many relationships' do
45
- let(:parent) { Parent.create }
45
+ context 'associations' do
46
+ context 'one-to-one relationships' do
47
+ let(:child) { Child.create }
48
+ let(:another_child) { Child.create }
46
49
 
47
- it 'should create children' do
48
- expect { parent.create_child }.to change{ Child.count }.by(1)
49
- expect(parent.children).to all(be_a(Child))
50
+ it 'should create children' do
51
+ expect { child.create_dog }.to change { Dog.count }.by(1)
52
+ expect(child.dog).to eq(Dog.first)
53
+ end
54
+
55
+ it 'should have inverse relationships' do
56
+ dog = child.create_dog
57
+ expect(dog.child).to eq(child)
58
+ another_dog = another_child.create_dog
59
+ expect(another_dog.child).to eq(another_child)
60
+ end
50
61
  end
51
62
 
52
- it 'should create inverse relationships' do
53
- child = parent.create_child
54
- expect(child.parent).to eq(parent)
63
+ context 'one-to-many relationships' do
64
+ let(:parent) { Parent.create }
65
+
66
+ it 'should create children' do
67
+ expect { parent.create_child }.to change{ Child.count }.by(1)
68
+ expect(parent.children).to all(be_a(Child))
69
+ end
70
+
71
+ it 'should create inverse relationships' do
72
+ child = parent.create_child
73
+ expect(child.parent).to eq(parent)
55
74
 
56
- another_child = parent.create_child
57
- expect(another_child.parent).to eq(parent)
75
+ another_child = parent.create_child
76
+ expect(another_child.parent).to eq(parent)
58
77
 
59
- expect(child.id).not_to eq(another_child.id)
60
- expect(parent.children).to eq([child, another_child])
78
+ expect(child.id).not_to eq(another_child.id)
79
+ expect(parent.children).to eq([child, another_child])
80
+ end
61
81
  end
62
- end
63
82
 
64
- context 'one-to-many through relationships' do
65
- let(:parent) { Parent.create }
66
- let(:child) { parent.create_child }
67
- subject(:dogs) { parent.dogs }
83
+ context 'one-to-many through relationships' do
84
+ let(:parent) { Parent.create }
85
+ let(:child) { parent.create_child }
86
+ subject(:dogs) { parent.dogs }
68
87
 
69
- it 'should collect children of children' do
70
- child.create_dog
71
- expect(dogs).to all(be_a(Dog))
72
- expect(dogs.first).to eq(child.dog)
88
+ it 'should collect children of children' do
89
+ child.create_dog
90
+ expect(dogs).to all(be_a(Dog))
91
+ expect(dogs.first).to eq(child.dog)
92
+ end
73
93
  end
74
- end
75
94
 
76
- context 'many-to-many' do
77
- let(:patient) { Patient.create }
78
- let(:doctor) { Doctor.create }
79
- let!(:appointment) { Appointment.create(patient: patient, doctor: doctor) }
95
+ context 'many-to-many' do
96
+ let(:patient) { Patient.create }
97
+ let(:doctor) { Doctor.create }
98
+ let!(:appointment) { Appointment.create(patient: patient, doctor: doctor) }
80
99
 
81
- it 'should manage many-to-many relations' do
82
- expect(appointment.doctor).to eq(doctor)
83
- expect(appointment.patient).to eq(patient)
100
+ it 'should manage many-to-many relations' do
101
+ expect(appointment.doctor).to eq(doctor)
102
+ expect(appointment.patient).to eq(patient)
84
103
 
85
- expect(patient.doctors).to eq([doctor])
86
- expect(doctor.patients).to eq([patient])
104
+ expect(patient.doctors).to eq([doctor])
105
+ expect(doctor.patients).to eq([patient])
106
+ end
87
107
  end
88
- end
89
108
 
90
- context 'self-referential many-to-many' do
91
- let!(:user_a) { User.create }
92
- let!(:user_b) { User.create }
109
+ context 'self-referential many-to-many' do
110
+ let!(:user_a) { User.create }
111
+ let!(:user_b) { User.create }
93
112
 
94
- it 'should permit relations' do
95
- expect(user_a.friends).to be_empty
113
+ it 'should permit relations' do
114
+ expect(user_a.friends).to be_empty
96
115
 
97
- # need to create bidirectional friendship
98
- Friendship.create(user: user_a, friend: user_b)
99
- Friendship.create(user: user_b, friend: user_a)
116
+ # need to create bidirectional friendship
117
+ Friendship.create(user: user_a, friend: user_b)
118
+ Friendship.create(user: user_b, friend: user_a)
100
119
 
101
- expect(user_a.friends).to eq([user_b])
102
- expect(user_b.friends).to eq([user_a])
120
+ expect(user_a.friends).to eq([user_b])
121
+ expect(user_b.friends).to eq([user_a])
122
+ end
103
123
  end
104
124
  end
105
125
  end
data/spec/spec_helper.rb CHANGED
@@ -17,11 +17,19 @@ end
17
17
  class Child < Model
18
18
  has_one :dog
19
19
  belongs_to :parent
20
+
21
+ after_create :give_name
22
+
23
+ attr_reader :name
24
+ def give_name; @name = "Alice" end
20
25
  end
21
26
 
22
27
  class Parent < Model
23
28
  has_many :children
24
29
  has_many :dogs, :through => :children
30
+
31
+ attr_reader :created_at
32
+ after_create { @created_at = Time.now }
25
33
  end
26
34
 
27
35
  ###
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passive_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Weissman
@@ -141,6 +141,7 @@ files:
141
141
  - lib/passive_record/associations/has_one.rb
142
142
  - lib/passive_record/core/identifier.rb
143
143
  - lib/passive_record/core/query.rb
144
+ - lib/passive_record/hooks.rb
144
145
  - lib/passive_record/hstruct.rb
145
146
  - lib/passive_record/version.rb
146
147
  - passive_record.gemspec
@@ -171,4 +172,3 @@ signing_key:
171
172
  specification_version: 4
172
173
  summary: no-persistence relational algebra
173
174
  test_files: []
174
- has_rdoc: