locomotive_plugins 1.0.0.beta3 → 1.0.0.beta4

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.
@@ -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