locomotive_plugins 1.0.0.beta3 → 1.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
@@ -117,11 +117,14 @@ module Locomotive
117
117
 
118
118
  # Initialize by supplying the current config parameters. Note that this
119
119
  # method should not be overridden for custom initialization of plugin
120
- # objects. Instead, override the initialize_plugin method
120
+ # objects. Instead, override the initialize_plugin method. If given a
121
+ # block, the block will be called with `self` as an argument before the
122
+ # `initialize_plugin` method is called. This is used by LocomotiveCMS to
123
+ # perform some custom initialization before the plugin's initialization is
124
+ # called.
121
125
  def initialize(config)
122
126
  self.config = config
123
- self.load_or_create_db_model_container!
124
- self.save_db_model_container
127
+ yield self if block_given?
125
128
  self.initialize_plugin
126
129
  end
127
130
 
@@ -5,6 +5,14 @@ module Locomotive
5
5
  # container has the actual relationships to the database objects
6
6
  class DBModelContainer
7
7
  include Mongoid::Document
8
+
9
+ field :container_name
10
+
11
+ def self.for_name(container_name)
12
+ where(container_name: container_name).first || \
13
+ new(container_name: container_name)
14
+ end
15
+
8
16
  end
9
17
  end
10
18
  end
@@ -33,18 +33,21 @@ module Locomotive
33
33
  protected
34
34
 
35
35
  def create_has_many_relationship(name, klass)
36
- self.db_model_container_class.embeds_many(name,
37
- class_name: klass.to_s, inverse_of: :db_model_container)
38
- klass.embedded_in(:db_model_container,
36
+ self.db_model_container_class.has_many(name,
37
+ class_name: klass.to_s, inverse_of: :db_model_container,
38
+ autosave: true, dependent: :destroy)
39
+ klass.belongs_to(:db_model_container,
39
40
  class_name: db_model_container_class.to_s, inverse_of: name)
40
41
 
41
- self.define_passthrough_methods_to_container(name, "#{name}=")
42
+ self.define_passthrough_methods_to_container(name, "#{name}=",
43
+ "#{name}_ids", "#{name}_ids=")
42
44
  end
43
45
 
44
46
  def create_has_one_relationship(name, klass)
45
- self.db_model_container_class.embeds_one(name,
46
- class_name: klass.to_s, inverse_of: :db_model_container)
47
- klass.embedded_in(:db_model_container,
47
+ self.db_model_container_class.has_one(name,
48
+ class_name: klass.to_s, inverse_of: :db_model_container,
49
+ autosave: true, dependent: :destroy)
50
+ klass.belongs_to(:db_model_container,
48
51
  class_name: db_model_container_class.to_s, inverse_of: name)
49
52
 
50
53
  self.define_passthrough_methods_to_container(name, "#{name}=",
@@ -52,13 +55,13 @@ module Locomotive
52
55
  end
53
56
 
54
57
  def define_passthrough_methods_to_container(*methods)
55
- class_eval <<-EOF
56
- %w{#{methods.join(' ')}}.each do |meth|
58
+ class_eval do
59
+ methods.each do |meth|
57
60
  define_method(meth) do |*args|
58
- @db_model_container.send(meth, *args)
61
+ db_model_container.send(meth, *args)
59
62
  end
60
63
  end
61
- EOF
64
+ end
62
65
  end
63
66
 
64
67
  end
@@ -70,14 +73,36 @@ module Locomotive
70
73
 
71
74
  # Get the DB Model container
72
75
  def db_model_container
73
- @db_model_container || load_or_create_db_model_container!
76
+ @db_model_containers ||= {}
77
+ name = self.current_db_model_container_name
78
+ @db_model_containers[name] ||= load_db_model_container(name)
79
+ end
80
+
81
+ # Set the current DB Model container
82
+ def use_db_model_container(name)
83
+ @current_db_model_container_name = name
84
+ end
85
+
86
+ # Reset to the default DB Model container
87
+ def reset_current_db_model_container
88
+ self.use_db_model_container(nil)
89
+ end
90
+
91
+ # Set the current DB Model container for the duration of the block
92
+ def with_db_model_container(name, &block)
93
+ old_name = self.current_db_model_container_name
94
+ self.use_db_model_container(name)
95
+ block.call
96
+ self.use_db_model_container(old_name)
74
97
  end
75
98
 
99
+ # The name of the current container being used
100
+ attr_reader :current_db_model_container_name
101
+
76
102
  protected
77
103
 
78
- def load_or_create_db_model_container!
79
- @db_model_container = self.class.db_model_container_class.first \
80
- || self.class.db_model_container_class.new
104
+ def load_db_model_container(name)
105
+ self.class.db_model_container_class.for_name(name)
81
106
  end
82
107
 
83
108
  end
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LocomotivePlugins
2
- VERSION = '1.0.0.beta3'
2
+ VERSION = '1.0.0.beta4'
3
3
  end
@@ -31,7 +31,7 @@ module Locomotive
31
31
  @plugin_with_db_model.items.where(name: /Item/)[1].name.should == 'Second Item'
32
32
  end
33
33
 
34
- it 'should embed DBModel items in a document for the plugin class' do
34
+ it 'should reference DBModel items in a document for the plugin class' do
35
35
  @plugin_with_db_model.visit_count.db_model_container.kind_of?(
36
36
  PluginWithDBModel::DBModelContainer).should be_true
37
37
  @plugin_with_db_model.items.first.db_model_container.kind_of?(
@@ -39,7 +39,10 @@ module Locomotive
39
39
 
40
40
  @plugin_with_db_model.visit_count.relations[
41
41
  'db_model_container'].relation.should \
42
- == Mongoid::Relations::Embedded::In
42
+ == Mongoid::Relations::Referenced::In
43
+ @plugin_with_db_model.items.relations[
44
+ 'db_model_container'].relation.should \
45
+ == Mongoid::Relations::Referenced::In
43
46
  end
44
47
 
45
48
  it 'should run all validations for DBModel items' do
@@ -51,6 +54,153 @@ module Locomotive
51
54
  }
52
55
  end
53
56
 
57
+ it 'should destroy the contained objects when the container is destroyed' do
58
+ vc = @plugin_with_db_model.visit_count
59
+ i0 = @plugin_with_db_model.items[0]
60
+ i1 = @plugin_with_db_model.items[1]
61
+
62
+ DBModel.all.for_ids(vc.id, i0.id, i1.id).count.should == 3
63
+
64
+ @plugin_with_db_model.db_model_container.destroy
65
+
66
+ DBModel.all.for_ids(vc.id, i0.id, i1.id).count.should == 0
67
+ end
68
+
69
+ it 'should allow relationships between DBModels' do
70
+ plugin = PluginWithDBModelRelationships.new({})
71
+
72
+ t1 = plugin.teachers.build(name: 'Mr. Adams')
73
+ t2 = plugin.teachers.build(name: 'Ms. Boudreau')
74
+
75
+ s1 = plugin.students.build(name: 'Alex', teacher: t1)
76
+ s2 = plugin.students.build(name: 'Billy', teacher: t1)
77
+ s3 = plugin.students.build(name: 'Caitlyn', teacher: t2)
78
+
79
+ plugin.save_db_model_container.should be_true
80
+
81
+ # Reload from database
82
+ plugin = PluginWithDBModelRelationships.new({})
83
+
84
+ # Check all the names and relationships to make sure they were
85
+ # persisted
86
+ teachers = plugin.teachers.to_a
87
+ students = plugin.students.to_a
88
+
89
+ teachers[0].name.should == 'Mr. Adams'
90
+ teachers[0].students.count.should == 2
91
+ teachers[0].students.should include(s1)
92
+ teachers[0].students.should include(s2)
93
+
94
+ teachers[1].name.should == 'Ms. Boudreau'
95
+ teachers[1].students.count.should == 1
96
+ teachers[1].students.should include(s3)
97
+
98
+ s1.name.should == 'Alex'
99
+ s1.teacher.should == t1
100
+ s2.name.should == 'Billy'
101
+ s2.teacher.should == t1
102
+ s3.name.should == 'Caitlyn'
103
+ s3.teacher.should == t2
104
+ end
105
+
106
+ context 'with multiple containers' do
107
+
108
+ it 'should save the data in the correct container' do
109
+ plugin = PluginWithDBModel.new({})
110
+
111
+ plugin.with_db_model_container('my_container') do
112
+ plugin.build_visit_count(count: 10)
113
+ end
114
+
115
+ plugin.use_db_model_container('my_other_container')
116
+ plugin.build_visit_count(count: 20)
117
+ plugin.save_db_model_container.should be_true
118
+ plugin.reset_current_db_model_container
119
+
120
+ plugin.use_db_model_container('my_container')
121
+ plugin.db_model_container.changed?.should be_true
122
+ plugin.save_db_model_container.should be_true
123
+ plugin.db_model_container.changed?.should be_false
124
+
125
+ # Reload from the database
126
+ @plugin_with_db_model = PluginWithDBModel.new({})
127
+
128
+ # Make sure everything is in the right container and make sure we can
129
+ # access the containers how we want
130
+ @plugin_with_db_model.with_db_model_container('my_other_container') do
131
+ @plugin_with_db_model.current_db_model_container_name.should ==
132
+ 'my_other_container'
133
+ @plugin_with_db_model.visit_count.count.should == 20
134
+ end
135
+
136
+ @plugin_with_db_model.use_db_model_container('my_container')
137
+ @plugin_with_db_model.current_db_model_container_name.should ==
138
+ 'my_container'
139
+ @plugin_with_db_model.visit_count.count.should == 10
140
+
141
+ @plugin_with_db_model.reset_current_db_model_container
142
+ @plugin_with_db_model.current_db_model_container_name.should be_nil
143
+ @plugin_with_db_model.visit_count.count.should == 5
144
+ end
145
+
146
+ it 'should revert the current container name after using with_db_model_container' do
147
+ @plugin_with_db_model.use_db_model_container('fake_container')
148
+ @plugin_with_db_model.current_db_model_container_name.should ==
149
+ 'fake_container'
150
+
151
+ @plugin_with_db_model.with_db_model_container('my_container') do
152
+ @plugin_with_db_model.current_db_model_container_name.should ==
153
+ 'my_container'
154
+ end
155
+
156
+ @plugin_with_db_model.current_db_model_container_name.should ==
157
+ 'fake_container'
158
+ end
159
+
160
+ it 'should only load each container once' do
161
+ container_names = %w{my_container my_other_container}
162
+
163
+ # The default container has already been loaded
164
+ @plugin_with_db_model.expects(:load_db_model_container).with(nil).never
165
+
166
+ # The others should only be called once. Just return something
167
+ # non-nil
168
+ container_names.each do |name|
169
+ @plugin_with_db_model.expects(:load_db_model_container).with(
170
+ name).returns(1).once
171
+ end
172
+
173
+ 3.times do
174
+ container_names.each do |name|
175
+ @plugin_with_db_model.with_db_model_container(name) do
176
+ # Access the container
177
+ @plugin_with_db_model.db_model_container
178
+ end
179
+ end
180
+ end
181
+ end
182
+
183
+ it 'should not share containers between plugin objects' do
184
+ p0 = PluginWithDBModel.new({})
185
+ p1 = PluginWithDBModelRelationships.new({})
186
+
187
+ # Default container
188
+ p0.save_db_model_container.should be_true
189
+ p1.save_db_model_container.should be_true
190
+ p0.db_model_container.should_not == p1.db_model_container
191
+
192
+ # Named container
193
+ p0.with_db_model_container('my_container') do
194
+ p1.with_db_model_container('my_container') do
195
+ p0.save_db_model_container.should be_true
196
+ p1.save_db_model_container.should be_true
197
+ p0.db_model_container.should_not == p1.db_model_container
198
+ end
199
+ end
200
+ end
201
+
202
+ end
203
+
54
204
  end
55
205
  end
56
206
  end
@@ -14,6 +14,13 @@ module Locomotive
14
14
  @plugin.custom_attribute.should == 'Value'
15
15
  end
16
16
 
17
+ it 'should call the gven block before custom initialization methods' do
18
+ @plugin = MyPlugin.new(@config) do |obj|
19
+ obj.custom_attribute.should be_nil
20
+ end
21
+ @plugin.custom_attribute.should_not be_nil
22
+ end
23
+
17
24
  it 'should store a list of before_filters' do
18
25
  @plugin.before_filters.count.should == 2
19
26
  @plugin.before_filters[0].should == :my_method1
@@ -0,0 +1,22 @@
1
+
2
+ module Locomotive
3
+ class PluginWithDBModelRelationships
4
+ include Locomotive::Plugin
5
+
6
+ class Teacher < Locomotive::Plugin::DBModel
7
+ field :name
8
+ has_many :students,
9
+ class_name: 'Locomotive::PluginWithDBModelRelationships::Student'
10
+ end
11
+
12
+ class Student < Locomotive::Plugin::DBModel
13
+ field :name
14
+ belongs_to :teacher,
15
+ class_name: 'Locomotive::PluginWithDBModelRelationships::Teacher'
16
+ end
17
+
18
+ has_many :teachers, Teacher
19
+ has_many :students, Student
20
+
21
+ end
22
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: locomotive_plugins
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta3
4
+ version: 1.0.0.beta4
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-07 00:00:00.000000000 Z
12
+ date: 2012-12-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: locomotive_liquid
@@ -133,6 +133,7 @@ files:
133
133
  - spec/support/plugins/plugin_with_filter.rb
134
134
  - spec/support/plugins/plugin_with_many_filter_modules.rb
135
135
  - spec/support/plugins/my_plugin.rb
136
+ - spec/support/plugins/plugin_with_db_model_relationships.rb
136
137
  - spec/support/plugins/plugin_with_db_model.rb
137
138
  - spec/support/factories.rb
138
139
  - spec/fixtures/config_template.haml