dm-is-published 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ ## OS STUFF
2
+ .DS_Store
3
+
4
+ ## TM SPECIFIC
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## PROJECT::GENERAL
9
+ *.sw?
10
+ coverage
11
+ rdoc
12
+ pkg
13
+
14
+ ## PROJECT::SPECIFIC
15
+
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ === 0.0.1 / 2009-07-11
2
+
3
+ * Release!
4
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Kematzy [kematzy gmail com]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,113 @@
1
+ = dm-is-published
2
+
3
+ This plugin makes it very easy to add different states to your models, like 'draft' vs 'live'.
4
+ By default it also adds validations of the field value.
5
+
6
+ Originally inspired by the Rails plugin +acts_as_publishable+ by <b>fr.ivolo.us</b>.
7
+
8
+
9
+ == Installation
10
+
11
+ # Add GitHub to your RubyGems sources
12
+ $ gem sources -a http://gems.github.com
13
+
14
+ $ (sudo)? gem install kematzy-dm-is-published
15
+
16
+ <b>NB! Depends upon the whole DataMapper suite being installed, and has ONLY been tested with DM 0.10.0 (next branch).</b>
17
+
18
+
19
+ == Getting Started
20
+
21
+ First of all, for a better understanding of this gem, make sure you study
22
+ the '<tt>dm-is-published/spec/integration/published_spec.rb</tt>' file.
23
+
24
+ ----
25
+
26
+ Require +dm-is-published+ in your app.
27
+
28
+ require 'dm-core' # must be required first
29
+ require 'dm-is-published'
30
+
31
+ Lets say we have an Article class, and each Article can have a current state,
32
+ ie: whether it's Live, Draft or an Obituary awaiting the death of someone famous (real or rumored)
33
+
34
+
35
+ class Article
36
+ include DataMapper::Resource
37
+ property :id, Serial
38
+ property :title, String
39
+ ...<snip>
40
+
41
+ is :published
42
+
43
+ end
44
+
45
+ Once you have your Article model we can create our Articles just as normal
46
+
47
+ Article.create(:title => 'Example 1')
48
+
49
+
50
+ The instance of <tt>Article.get(1)</tt> now has the following things for free:
51
+
52
+ * a <tt>:publish_status</tt> attribute with the value <tt>'live'</tt>. Default choices are <tt>[ :live, :draft, :hidden ]</tt>.
53
+
54
+ * <tt>:is_live?, :is_draft? or :is_hidden?</tt> methods that returns true/false based upon the state.
55
+
56
+ * <tt>:save_as_live</tt>, <tt>:save_as_draft</tt> or <tt>:save_as_hidden</tt> converts the instance to the state and saves it.
57
+
58
+ * <tt>:publishable?</tt> method that returns true for models where <tt>is :published </tt> has been declared,
59
+ but <b>false</b> for those where it has not been declared.
60
+
61
+
62
+ The Article class also gets a bit of new functionality:
63
+
64
+ Article.all(:draft) => finds all Articles with :publish_status = :draft
65
+
66
+
67
+ Article.all(:draft, :author => @author_joe ) => finds all Articles with :publish_status = :draft and author == Joe
68
+
69
+
70
+
71
+ Todo Need to write more documentation here..
72
+
73
+
74
+ == Usage Scenarios
75
+
76
+ In a Blog/Publishing scenario you could use it like this:
77
+
78
+ class Article
79
+ ...<snip>...
80
+
81
+ is :published :live, :draft, :hidden
82
+
83
+ end
84
+
85
+ Whereas in another scenario - like in a MenuItem model for a Restaurant - you could use it like this:
86
+
87
+ class MenuItem
88
+ ...<snip>...
89
+
90
+ is :published :on, :off # the item is either on the menu or not
91
+
92
+ end
93
+
94
+
95
+ == RTFM
96
+
97
+ As I said above, for a better understanding of this gem/plugin, make sure you study the '<tt>dm-is-published/spec/integration/published_spec.rb</tt>' file.
98
+
99
+
100
+ == Errors / Bugs
101
+
102
+ If something is not behaving intuitively, it is a bug, and should be reported.
103
+ Report it here: http://datamapper.lighthouseapp.com/
104
+
105
+ === Credits
106
+
107
+ Copyright (c) 2008-05-07 [Kematzy at gmail]
108
+
109
+ Loosely based on the ActsAsPublishable plugin by [http://fr.ivolo.us/posts/acts-as-publishable]
110
+
111
+ == Licence
112
+
113
+ Released under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "dm-is-published"
8
+ gem.summary = %Q{A DataMapper plugin that provides an easy way to add different states to your models.}
9
+ gem.email = "kematzy@gmail.com"
10
+ gem.homepage = "http://github.com/kematzy/dm-is-published"
11
+ gem.authors = ["kematzy"]
12
+ gem.extra_rdoc_files = %w[ README.rdoc LICENSE TODO History.txt ]
13
+ gem.add_dependency('dm-core', '>= 0.10.0')
14
+ gem.add_dependency('dm-validations', '>= 0.10.0')
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
20
+ end
21
+
22
+ require 'spec/rake/spectask'
23
+ Spec::Rake::SpecTask.new(:spec) do |spec|
24
+ spec.libs << 'lib' << 'spec'
25
+ spec.spec_files = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.pattern = 'spec/**/*_spec.rb'
31
+ spec.rcov = true
32
+ end
33
+
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ if File.exist?('VERSION.yml')
40
+ config = YAML.load(File.read('VERSION.yml'))
41
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
42
+ else
43
+ version = ""
44
+ end
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "dm-is-published #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
51
+
data/TODO ADDED
File without changes
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,15 @@
1
+ # Needed to import datamapper and other gems
2
+ require 'rubygems'
3
+ require 'pathname'
4
+
5
+ # Add all external dependencies for the plugin here
6
+ gem 'dm-core', '~> 0.10.0'
7
+ require 'dm-core'
8
+ gem 'dm-validations', '~> 0.10.0'
9
+ require 'dm-validations'
10
+
11
+ # Require plugin-files
12
+ require Pathname(__FILE__).dirname.expand_path / 'dm-is-published' / 'is' / 'published.rb'
13
+
14
+ DataMapper::Model.append_extensions(DataMapper::Is::Published)
15
+ DataMapper::Model.append_inclusions(DataMapper::Is::Published::ResourceInstanceMethods)
@@ -0,0 +1,259 @@
1
+ module DataMapper
2
+ module Is
3
+
4
+ # = dm-is-published
5
+ #
6
+ # This plugin makes it very easy to add different states to your models, like 'draft' vs 'live'.
7
+ # By default it also adds validations of the field value.
8
+ #
9
+ # Originally inspired by the Rails plugin +acts_as_publishable+ by <b>fr.ivolo.us</b>.
10
+ #
11
+ #
12
+ # == Installation
13
+ #
14
+ # # Add GitHub to your RubyGems sources
15
+ # $ gem sources -a http://gems.github.com
16
+ #
17
+ # $ (sudo)? gem install kematzy-dm-is-published
18
+ #
19
+ # <b>NB! Depends upon the whole DataMapper suite being installed, and has ONLY been tested with DM 0.10.0 (next branch).</b>
20
+ #
21
+ #
22
+ # == Getting Started
23
+ #
24
+ # First of all, for a better understanding of this gem, make sure you study the '<tt>dm-is-published/spec/integration/published_spec.rb</tt>' file.
25
+ #
26
+ # ----
27
+ #
28
+ # Require +dm-is-published+ in your app.
29
+ #
30
+ # require 'dm-core' # must be required first
31
+ # require 'dm-is-published'
32
+ #
33
+ # Lets say we have an Article class, and each Article can have a current state,
34
+ # ie: whether it's Live, Draft or an Obituary awaiting the death of someone famous (real or rumored)
35
+ #
36
+ #
37
+ # class Article
38
+ # include DataMapper::Resource
39
+ # property :id, Serial
40
+ # property :title, String
41
+ # ...<snip>
42
+ #
43
+ # is :published
44
+ #
45
+ # end
46
+ #
47
+ # Once you have your Article model we can create our Articles just as normal
48
+ #
49
+ # Article.create(:title => 'Example 1')
50
+ #
51
+ #
52
+ # The instance of <tt>Article.get(1)</tt> now has the following things for free:
53
+ #
54
+ # * a <tt>:publish_status</tt> attribute with the value <tt>'live'</tt>. Default choices are <tt>[ :live, :draft, :hidden ]</tt>.
55
+ #
56
+ # * <tt>:is_live?, :is_draft? or :is_hidden?</tt> methods that returns true/false based upon the state.
57
+ #
58
+ # * <tt>:save_as_live</tt>, <tt>:save_as_draft</tt> or <tt>:save_as_hidden</tt> converts the instance to the state and saves it.
59
+ #
60
+ # * <tt>:publishable?</tt> method that returns true for models where <tt>is :published </tt> has been declared,
61
+ # but <b>false</b> for those where it has not been declared.
62
+ #
63
+ #
64
+ # The Article class also gets a bit of new functionality:
65
+ #
66
+ # Article.all(:draft) => finds all Articles with :publish_status = :draft
67
+ #
68
+ #
69
+ # Article.all(:draft, :author => @author_joe ) => finds all Articles with :publish_status = :draft and author == Joe
70
+ #
71
+ #
72
+ # Todo:: add more documentation here...
73
+ #
74
+ #
75
+ # == Usage Scenarios
76
+ #
77
+ # In a Blog/Publishing scenario you could use it like this:
78
+ #
79
+ # class Article
80
+ # ...<snip>...
81
+ #
82
+ # is :published :live, :draft, :hidden
83
+ # end
84
+ #
85
+ # Whereas in another scenario - like in a MenuItem model for a Restaurant - you could use it like this:
86
+ #
87
+ # class MenuItem
88
+ # ...<snip>...
89
+ #
90
+ # is :published :on, :off # the item is either on the menu or not
91
+ # end
92
+ #
93
+ #
94
+ # == RTFM
95
+ #
96
+ # As I said above, for a better understanding of this gem/plugin, make sure you study the '<tt>dm-is-published/spec/integration/published_spec.rb</tt>' file.
97
+ #
98
+ #
99
+ # == Errors / Bugs
100
+ #
101
+ # If something is not behaving intuitively, it is a bug, and should be reported.
102
+ # Report it here: http://datamapper.lighthouseapp.com/
103
+ #
104
+ # === Credits
105
+ #
106
+ # Copyright (c) 2008-05-07 [Kematzy at gmail]
107
+ #
108
+ # Loosely based on the ActsAsPublishable plugin by [http://fr.ivolo.us/posts/acts-as-publishable]
109
+ #
110
+ # == Licence
111
+ #
112
+ # Released under the MIT license.
113
+
114
+ module Published
115
+
116
+ ##
117
+ # method that adds a basic published status attribute to your model
118
+ #
119
+ # == params
120
+ #
121
+ # * +states+ - an array of 'states' as symbols or strings. ie: :live, :draft, :hidden
122
+ #
123
+ # ==== Examples
124
+ #
125
+ #
126
+ # is :published :on, :off
127
+ #
128
+ # is :published %w(a b c d)
129
+ #
130
+ #
131
+ # @api public
132
+ def is_published(*args)
133
+ # set default args if none passed in
134
+ args = [:live, :draft, :hidden] if args.blank?
135
+ args = args.first if args.first.is_a?(Array)
136
+
137
+ # the various publish states accepted.
138
+ @publish_states = args.collect{ |state| state.to_s.downcase.to_sym }
139
+ @publish_states_for_validation = args.collect{ |state| state.to_s.downcase }
140
+
141
+ extend DataMapper::Is::Published::ClassMethods
142
+ include DataMapper::Is::Published::InstanceMethods
143
+
144
+ # do we have a :publish_status declared
145
+ if properties.any?{ |p| p.name == :publish_status }
146
+
147
+ # set default value to first value in declaration or the given value
148
+ d = properties[:publish_status].default.blank? ? @publish_states.first.to_s : properties[:publish_status].default
149
+
150
+ # set the length to 10 if missing or if shorter than 5, otherwise use the given value
151
+ l = 5 if properties[:publish_status].length.blank?
152
+ l = (properties[:publish_status].length <= 10 ? 10 : properties[:publish_status].length)
153
+
154
+ property :publish_status, String, :length => l, :default => d.to_s
155
+ else
156
+ # no such property, so adding it with default values
157
+ property :publish_status, String, :length => 10, :default => @publish_states.first.to_s
158
+ end
159
+
160
+ # create the state specific instance methods
161
+ self.publish_states.each do |state|
162
+ define_method("is_#{state}?") do
163
+ self.publish_status == state.to_s
164
+ end
165
+ define_method("save_as_#{state}") do
166
+ self.publish_status = state.to_s
167
+ save
168
+ end
169
+ end
170
+
171
+ # ensure we are always saving publish_status values as strings
172
+ before :valid? do
173
+ self.publish_status = self.publish_status.to_s if self.respond_to?(:publish_status)
174
+ end
175
+
176
+ validates_within :publish_status,
177
+ :set => @publish_states_for_validation,
178
+ :message => "The publish_status value can only be one of these values: [ #{@publish_states_for_validation.join(', ')} ]"
179
+
180
+ end
181
+
182
+ module ClassMethods
183
+ attr_reader :publish_states, :publish_states_for_validation
184
+
185
+ ##
186
+ # Overriding the normal #all method to add some extra sugar.
187
+ #
188
+ # ==== Examples
189
+ #
190
+ # Article.all => returns all Articles as usual
191
+ #
192
+ # Article.all( :publish_status => :live ) => returns all Articles with :publish_status == :lve
193
+ #
194
+ # Article.all(:draft) => returns all Articles with :publish_status == :draft
195
+ #
196
+ # Article.all(:draft, :author => @author_joe ) => finds all Articles with :publish_status = :draft and author == Joe
197
+ #
198
+ #
199
+ # @api public/private
200
+ def all(*args)
201
+ # incoming can either be:
202
+ # -- nil (nothing passed in, so just use super )
203
+ # -- (Hash) => all(:key => "value") ( normal operations, so just pass on the Hash )
204
+ # -- (Symbol) => all(:draft) ( just get the symbol, )
205
+ # -- (Symbol, Hash ) => :draft, { extra options }
206
+ if args.empty?
207
+ return super
208
+ elsif args.first.is_a?(Hash)
209
+ return super(args.first)
210
+ else
211
+ # set the from args Array, remove first item if Symbol, and then check for 2nd item's presence
212
+ state, options = args.shift.to_s, (args.blank? ? {} : args.first) if args.first.is_a?(Symbol)
213
+ # puts " and state=[#{state}] and options=[#{options.class}] options.inspect=[#{options.inspect}] [#{__FILE__}:#{__LINE__}]"
214
+
215
+ return super({ :publish_status => state }.merge(options) )
216
+ end
217
+
218
+ end
219
+
220
+ end # ClassMethods
221
+
222
+ module InstanceMethods
223
+
224
+ ##
225
+ # Ensuring all models using this plugin responds to publishable? with true.
226
+ #
227
+ # ==== Examples
228
+ #
229
+ # @published_model.publishable? => true
230
+ #
231
+ # @api public
232
+ def publishable?
233
+ true
234
+ end
235
+
236
+ end # InstanceMethods
237
+
238
+ module ResourceInstanceMethods
239
+
240
+ ##
241
+ # Ensuring all models NOT using this plugin responds to publishable? with false.
242
+ #
243
+ # ==== Examples
244
+ #
245
+ # @unpublished_model.publishable? => false
246
+ #
247
+ # @api public
248
+ def publishable?
249
+ false
250
+ end
251
+
252
+ end #/module ResourceInstanceMethods
253
+
254
+ end # Published
255
+ end # Is
256
+
257
+ Model.append_extensions(Is::Published)
258
+
259
+ end # DataMapper
@@ -0,0 +1,7 @@
1
+ module DataMapper
2
+ module Is
3
+ module Published
4
+ VERSION = '0.0.1'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,303 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
+
4
+ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
5
+ describe 'DataMapper::Is::Published' do
6
+
7
+ class DefaultsArticle
8
+ include DataMapper::Resource
9
+ property :id, Serial
10
+ property :title, String
11
+
12
+ is :published
13
+ end
14
+
15
+ class Article
16
+ include DataMapper::Resource
17
+ property :id, Serial
18
+ property :title, String
19
+
20
+ is :published, :live, :draft, :prepared
21
+ end
22
+
23
+ class Image
24
+ include DataMapper::Resource
25
+ property :id, Serial
26
+ property :title, String
27
+
28
+ is :published, :yes, :no
29
+ end
30
+
31
+
32
+ before(:each) do
33
+ DefaultsArticle.auto_migrate!
34
+ Article.auto_migrate!
35
+ Image.auto_migrate!
36
+
37
+ %w(live draft hidden).each do |state|
38
+ DefaultsArticle.create(:title => "#{state.capitalize} DefaultsArticle", :publish_status => state )
39
+ end
40
+ %w(live draft prepared).each do |state|
41
+ Article.create(:title => "#{state.capitalize} Article", :publish_status => state )
42
+ end
43
+ %w(yes no).each do |state|
44
+ Image.create(:title => "#{state.capitalize} Image", :publish_status => state )
45
+ end
46
+
47
+ end
48
+
49
+
50
+ describe "Property :publish_status" do
51
+
52
+ class ArticleWithoutDefaultAndTooShortLength
53
+ include DataMapper::Resource
54
+ property :id, Serial
55
+ property :publish_status, String, :length => 2
56
+
57
+ is :published
58
+ end
59
+
60
+ class ArticleWithDefaultAndLongerLength
61
+ include DataMapper::Resource
62
+ property :id, Serial
63
+ property :publish_status, String, :length => 100, :default => 'hidden'
64
+
65
+ is :published
66
+ end
67
+
68
+ describe ":length => X" do
69
+
70
+ it "should set the :publish_status length to the default value of 5 if declared shorter" do
71
+ ArticleWithoutDefaultAndTooShortLength.properties[:publish_status].length.should == 10
72
+ end
73
+
74
+ it "should NOT set the :publish_status length to the default value of 5 if declared is longer" do
75
+ ArticleWithDefaultAndLongerLength.properties[:publish_status].length.should == 100
76
+ end
77
+
78
+ end #/ length
79
+
80
+ describe ":default => X" do
81
+
82
+ it "should set the :publish_status default value to the first item in the method declaration" do
83
+ ArticleWithoutDefaultAndTooShortLength.properties[:publish_status].default.should == 'live'
84
+ Article.properties[:publish_status].default.should == 'live'
85
+ Image.properties[:publish_status].default.should == 'yes'
86
+ end
87
+
88
+ it "should set the default value to the declared value" do
89
+ ArticleWithDefaultAndLongerLength.properties[:publish_status].default.should == 'hidden'
90
+ end
91
+
92
+ end #/ default
93
+
94
+ end #/ Property :publish_status
95
+
96
+ describe "Class Methods" do
97
+
98
+ describe "#publish_states" do
99
+
100
+ it "should return the states as an array of Symbols" do
101
+ DefaultsArticle.publish_states.should == [:live, :draft, :hidden]
102
+ Article.publish_states.should == [:live, :draft, :prepared]
103
+ Image.publish_states.should == [:yes, :no]
104
+ end
105
+
106
+ class ArticleWithDeclarationAsArray
107
+ include DataMapper::Resource
108
+ property :id, Serial
109
+ is :published, [:a, :b, :c]
110
+ end
111
+
112
+ it "should handle the states declared within [ Array ] brackets" do
113
+ ArticleWithDeclarationAsArray.publish_states.should == [:a, :b, :c]
114
+ end
115
+
116
+ class ArticleWithDeclarationAsArrayOfStrings
117
+ include DataMapper::Resource
118
+ property :id, Serial
119
+ is :published, %w(a b c)
120
+ end
121
+
122
+ it "should handle the states declared as %w(a b c) " do
123
+ ArticleWithDeclarationAsArrayOfStrings.publish_states.should == [:a, :b, :c]
124
+ end
125
+
126
+ end #/ #publish_states
127
+
128
+ describe "#publish_states_for_validation" do
129
+
130
+ it "should return the states as an array of Strings" do
131
+ DefaultsArticle.publish_states_for_validation.should == ["live", "draft", "hidden"]
132
+ Article.publish_states_for_validation.should == ["live", "draft", "prepared"]
133
+ Image.publish_states_for_validation.should == ["yes", "no"]
134
+ end
135
+
136
+ end #/ #publish_states
137
+
138
+ describe "#all" do
139
+
140
+ before(:each) do
141
+ 5.times do |n|
142
+ Article.create(:title => "Dummy Article #{n +1}")
143
+ end
144
+ end
145
+
146
+ it "should work as expected with Model.all" do
147
+ Article.all.size.should == 8
148
+ end
149
+
150
+ it "should work as expected with Model.all(:publish_status => state) (finding only those records with the state) " do
151
+ Article.all( :publish_status => :live ).size.should == 6
152
+ end
153
+
154
+ it "should work as expected with Model.all(:state) (finding only those records with the given state) " do
155
+ Article.all(:live).size.should == 6
156
+ end
157
+
158
+ it "should work as expected with Model.all(:state,{ conditions } ) (finding only the items with the given state and conditions) " do
159
+ Article.all(:live, :title => "Dummy Article 1" ).size.should == 1
160
+ end
161
+
162
+ end #/ #self.all
163
+
164
+ end #/ Class Methods
165
+
166
+ describe "Instance Methods" do
167
+
168
+ describe "#publish_status" do
169
+
170
+ it "should return the state as a String" do
171
+ Article.get(1).publish_status.should be_a_kind_of(String)
172
+ end
173
+
174
+ it "should set the default status as the first item in the list when is :published is defined " do
175
+ a = Article.create(:title => "Article with default publish_status" )
176
+ a.publish_status.should == 'live'
177
+ end
178
+
179
+ end #/ #publish_status
180
+
181
+ describe "#publishable?" do
182
+
183
+ it "should return true for a Model with is :published declared" do
184
+ Article.get(1).publishable?.should == true
185
+ end
186
+
187
+ it "should return false when Model does NOT have is :published declared" do
188
+ class UnPublishedModel
189
+ include DataMapper::Resource
190
+ property :id, Serial
191
+ end
192
+
193
+ UnPublishedModel.new.should respond_to(:publishable?)
194
+ UnPublishedModel.new.publishable?.should == false
195
+ end
196
+
197
+ end #/ #publishable?
198
+
199
+ describe "defined :is_STATE? methods" do
200
+
201
+ describe "#is_live?" do
202
+
203
+ it "should return true on live articles" do
204
+ Article.get(1).is_live?.should == true
205
+ end
206
+
207
+ it "should return false on all others" do
208
+ Article.get(2).is_live?.should == false
209
+ Article.get(3).is_live?.should == false
210
+ end
211
+
212
+ end #/ #is_live?
213
+
214
+ describe "#is_draft?" do
215
+
216
+ it "should return true on draft articles" do
217
+ Article.get(2).is_draft?.should == true
218
+ end
219
+
220
+ it "should return false on all others" do
221
+ Article.get(1).is_draft?.should == false
222
+ Article.get(3).is_draft?.should == false
223
+ end
224
+
225
+ end #/ #is_draft?
226
+
227
+ describe "#is_prepared?" do
228
+
229
+ it "should return true on prepared articles" do
230
+ Article.get(3).is_prepared?.should == true
231
+ end
232
+
233
+ it "should return false on all others" do
234
+ Article.get(1).is_prepared?.should == false
235
+ Article.get(2).is_prepared?.should == false
236
+ end
237
+
238
+ end #/ #is_prepared?
239
+
240
+ end #/ defined :is_STATE? methods
241
+
242
+ describe "defined :save_as_STATE? methods" do
243
+
244
+ Article.publish_states.each do |state|
245
+
246
+ describe "#save_as_#{state}" do
247
+
248
+ it "should save item as :#{state}" do
249
+ a = Article.new(:title => "Saved As #{state.to_s.capitalize} article" )
250
+ a.send("save_as_#{state}").should == true
251
+ a.publish_status.should == state.to_s
252
+ end
253
+
254
+ end #/ #save_as_
255
+
256
+ end
257
+
258
+ Image.publish_states.each do |state|
259
+
260
+ describe "#save_as_#{state}" do
261
+
262
+ it "should save item as :#{state}" do
263
+ a = Image.new(:title => "Saved As #{state.to_s.capitalize}" )
264
+ a.send("save_as_#{state}").should == true
265
+ a.publish_status.should == state.to_s
266
+ end
267
+
268
+ end #/ #save_as_
269
+
270
+ end
271
+
272
+ it "should enable changing the publish status" do
273
+ a = Article.get(1)
274
+ a.publish_status.should == 'live'
275
+ a.save_as_draft
276
+ a.reload
277
+ a.publish_status.should == 'draft'
278
+ end
279
+
280
+ end #/ defined :is_STATE? methods
281
+
282
+ end #/ Instance Methods
283
+
284
+ describe "Validations" do
285
+
286
+ it "should accept the defined states" do
287
+ %w(live draft prepared).each do |state|
288
+ a = Article.new(:title => "Accepted Validated Article", :publish_status => state )
289
+ a.save.should == true
290
+ a.errors.on(:publish_status).should == nil
291
+ end
292
+ end
293
+
294
+ it "should reject all other states and return a Validation error with the possible states in the message text" do
295
+ a = Article.new(:title => "Rejected Article", :publish_status => :invalid )
296
+ a.save.should == false
297
+ a.errors.on(:publish_status).should == ["The publish_status value can only be one of these values: [ live, draft, prepared ]"]
298
+ end
299
+
300
+ end #/ Validations
301
+
302
+ end
303
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,26 @@
1
+ require 'pathname'
2
+ require 'rubygems'
3
+
4
+ # gem 'rspec', '~>1.1.11'
5
+ require 'spec'
6
+
7
+ require Pathname(__FILE__).dirname.expand_path.parent + 'lib/dm-is-published'
8
+
9
+ def load_driver(name, default_uri)
10
+ return false if ENV['ADAPTER'] != name.to_s
11
+
12
+ begin
13
+ DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
14
+ DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
15
+ true
16
+ rescue LoadError => e
17
+ warn "Could not load do_#{name}: #{e}"
18
+ false
19
+ end
20
+ end
21
+
22
+ ENV['ADAPTER'] ||= 'sqlite3'
23
+
24
+ HAS_SQLITE3 = load_driver(:sqlite3, 'sqlite3::memory:')
25
+ HAS_MYSQL = load_driver(:mysql, 'mysql://localhost/dm_core_test')
26
+ HAS_POSTGRES = load_driver(:postgres, 'postgres://postgres@localhost/dm_core_test')
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dm-is-published
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - kematzy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-12 00:00:00 +08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: dm-core
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.10.0
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: dm-validations
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.10.0
34
+ version:
35
+ description:
36
+ email: kematzy@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - History.txt
43
+ - LICENSE
44
+ - README.rdoc
45
+ - TODO
46
+ files:
47
+ - .gitignore
48
+ - History.txt
49
+ - LICENSE
50
+ - README.rdoc
51
+ - Rakefile
52
+ - TODO
53
+ - VERSION
54
+ - lib/dm-is-published.rb
55
+ - lib/dm-is-published/is/published.rb
56
+ - lib/dm-is-published/is/version.rb
57
+ - spec/integration/published_spec.rb
58
+ - spec/spec.opts
59
+ - spec/spec_helper.rb
60
+ has_rdoc: true
61
+ homepage: http://github.com/kematzy/dm-is-published
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options:
66
+ - --charset=UTF-8
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ version:
81
+ requirements: []
82
+
83
+ rubyforge_project:
84
+ rubygems_version: 1.3.4
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: A DataMapper plugin that provides an easy way to add different states to your models.
88
+ test_files:
89
+ - spec/integration/published_spec.rb
90
+ - spec/spec_helper.rb