kematzy-dm-is-published 0.0.2

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) 2009-07-11 [kematzy gmail com]
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,54 @@
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.version = IO.read('VERSION') || '0.0.0'
9
+ gem.summary = %Q{A DataMapper plugin that provides an easy way to add different states to your models.}
10
+ # gem.description = gem.summary
11
+ gem.description = IO.read('README.rdoc') || gem.summary
12
+ gem.email = "kematzy@gmail.com"
13
+ gem.homepage = "http://github.com/kematzy/dm-is-published"
14
+ gem.authors = ["kematzy"]
15
+ gem.extra_rdoc_files = %w[ README.rdoc LICENSE TODO History.txt ]
16
+ gem.add_dependency('dm-core', '>= 0.10.0')
17
+ gem.add_dependency('dm-validations', '>= 0.10.0')
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
23
+ end
24
+
25
+ require 'spec/rake/spectask'
26
+ Spec::Rake::SpecTask.new(:spec) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.spec_files = FileList['spec/**/*_spec.rb']
29
+ end
30
+
31
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
32
+ spec.libs << 'lib' << 'spec'
33
+ spec.pattern = 'spec/**/*_spec.rb'
34
+ spec.rcov = true
35
+ end
36
+
37
+
38
+ task :default => :spec
39
+
40
+ require 'rake/rdoctask'
41
+ Rake::RDocTask.new do |rdoc|
42
+ if File.exist?('VERSION.yml')
43
+ config = YAML.load(File.read('VERSION.yml'))
44
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
45
+ else
46
+ version = ""
47
+ end
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "dm-is-published #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
54
+
data/TODO ADDED
File without changes
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,172 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{dm-is-published}
5
+ s.version = "0.0.2"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["kematzy"]
9
+ s.date = %q{2009-07-12}
10
+ s.description = %q{= dm-is-published
11
+
12
+ This plugin makes it very easy to add different states to your models, like 'draft' vs 'live'.
13
+ By default it also adds validations of the field value.
14
+
15
+ Originally inspired by the Rails plugin +acts_as_publishable+ by <b>fr.ivolo.us</b>.
16
+
17
+
18
+ == Installation
19
+
20
+ # Add GitHub to your RubyGems sources
21
+ $ gem sources -a http://gems.github.com
22
+
23
+ $ (sudo)? gem install kematzy-dm-is-published
24
+
25
+ <b>NB! Depends upon the whole DataMapper suite being installed, and has ONLY been tested with DM 0.10.0 (next branch).</b>
26
+
27
+
28
+ == Getting Started
29
+
30
+ First of all, for a better understanding of this gem, make sure you study
31
+ the '<tt>dm-is-published/spec/integration/published_spec.rb</tt>' file.
32
+
33
+ ----
34
+
35
+ Require +dm-is-published+ in your app.
36
+
37
+ require 'dm-core' # must be required first
38
+ require 'dm-is-published'
39
+
40
+ Lets say we have an Article class, and each Article can have a current state,
41
+ ie: whether it's Live, Draft or an Obituary awaiting the death of someone famous (real or rumored)
42
+
43
+
44
+ class Article
45
+ include DataMapper::Resource
46
+ property :id, Serial
47
+ property :title, String
48
+ ...<snip>
49
+
50
+ is :published
51
+
52
+ end
53
+
54
+ Once you have your Article model we can create our Articles just as normal
55
+
56
+ Article.create(:title => 'Example 1')
57
+
58
+
59
+ The instance of <tt>Article.get(1)</tt> now has the following things for free:
60
+
61
+ * a <tt>:publish_status</tt> attribute with the value <tt>'live'</tt>. Default choices are <tt>[ :live, :draft, :hidden ]</tt>.
62
+
63
+ * <tt>:is_live?, :is_draft? or :is_hidden?</tt> methods that returns true/false based upon the state.
64
+
65
+ * <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.
66
+
67
+ * <tt>:publishable?</tt> method that returns true for models where <tt>is :published </tt> has been declared,
68
+ but <b>false</b> for those where it has not been declared.
69
+
70
+
71
+ The Article class also gets a bit of new functionality:
72
+
73
+ Article.all(:draft) => finds all Articles with :publish_status = :draft
74
+
75
+
76
+ Article.all(:draft, :author => @author_joe ) => finds all Articles with :publish_status = :draft and author == Joe
77
+
78
+
79
+
80
+ Todo Need to write more documentation here..
81
+
82
+
83
+ == Usage Scenarios
84
+
85
+ In a Blog/Publishing scenario you could use it like this:
86
+
87
+ class Article
88
+ ...<snip>...
89
+
90
+ is :published :live, :draft, :hidden
91
+
92
+ end
93
+
94
+ Whereas in another scenario - like in a MenuItem model for a Restaurant - you could use it like this:
95
+
96
+ class MenuItem
97
+ ...<snip>...
98
+
99
+ is :published :on, :off # the item is either on the menu or not
100
+
101
+ end
102
+
103
+
104
+ == RTFM
105
+
106
+ 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.
107
+
108
+
109
+ == Errors / Bugs
110
+
111
+ If something is not behaving intuitively, it is a bug, and should be reported.
112
+ Report it here: http://datamapper.lighthouseapp.com/
113
+
114
+ === Credits
115
+
116
+ Copyright (c) 2009-07-11 [kematzy gmail com]
117
+
118
+ Loosely based on the ActsAsPublishable plugin by [http://fr.ivolo.us/posts/acts-as-publishable]
119
+
120
+ == Licence
121
+
122
+ Released under the MIT license.
123
+ }
124
+ s.email = %q{kematzy@gmail.com}
125
+ s.extra_rdoc_files = [
126
+ "History.txt",
127
+ "LICENSE",
128
+ "README.rdoc",
129
+ "TODO"
130
+ ]
131
+ s.files = [
132
+ ".gitignore",
133
+ "History.txt",
134
+ "LICENSE",
135
+ "README.rdoc",
136
+ "Rakefile",
137
+ "TODO",
138
+ "VERSION",
139
+ "dm-is-published.gemspec",
140
+ "lib/dm-is-published.rb",
141
+ "lib/dm-is-published/is/published.rb",
142
+ "lib/dm-is-published/is/version.rb",
143
+ "spec/integration/published_spec.rb",
144
+ "spec/spec.opts",
145
+ "spec/spec_helper.rb"
146
+ ]
147
+ s.homepage = %q{http://github.com/kematzy/dm-is-published}
148
+ s.rdoc_options = ["--charset=UTF-8"]
149
+ s.require_paths = ["lib"]
150
+ s.rubygems_version = %q{1.3.4}
151
+ s.summary = %q{A DataMapper plugin that provides an easy way to add different states to your models.}
152
+ s.test_files = [
153
+ "spec/integration/published_spec.rb",
154
+ "spec/spec_helper.rb"
155
+ ]
156
+
157
+ if s.respond_to? :specification_version then
158
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
159
+ s.specification_version = 3
160
+
161
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
162
+ s.add_runtime_dependency(%q<dm-core>, [">= 0.10.0"])
163
+ s.add_runtime_dependency(%q<dm-validations>, [">= 0.10.0"])
164
+ else
165
+ s.add_dependency(%q<dm-core>, [">= 0.10.0"])
166
+ s.add_dependency(%q<dm-validations>, [">= 0.10.0"])
167
+ end
168
+ else
169
+ s.add_dependency(%q<dm-core>, [">= 0.10.0"])
170
+ s.add_dependency(%q<dm-validations>, [">= 0.10.0"])
171
+ end
172
+ end
@@ -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.2'
5
+ end
6
+ end
7
+ end
@@ -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,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.2.6'
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,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kematzy-dm-is-published
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - kematzy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-12 00:00:00 -07: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: "= dm-is-published This plugin makes it very easy to add different states to your models, like 'draft' vs 'live'. By default it also adds validations of the field value. Originally inspired by the Rails plugin +acts_as_publishable+ by <b>fr.ivolo.us</b>. == Installation # Add GitHub to your RubyGems sources $ gem sources -a http://gems.github.com $ (sudo)? gem install kematzy-dm-is-published <b>NB! Depends upon the whole DataMapper suite being installed, and has ONLY been tested with DM 0.10.0 (next branch).</b> == Getting Started 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. ---- Require +dm-is-published+ in your app. require 'dm-core' # must be required first require 'dm-is-published' Lets say we have an Article class, and each Article can have a current state, ie: whether it's Live, Draft or an Obituary awaiting the death of someone famous (real or rumored) class Article include DataMapper::Resource property :id, Serial property :title, String ...<snip> is :published end Once you have your Article model we can create our Articles just as normal Article.create(:title => 'Example 1') The instance of <tt>Article.get(1)</tt> now has the following things for free: * a <tt>:publish_status</tt> attribute with the value <tt>'live'</tt>. Default choices are <tt>[ :live, :draft, :hidden ]</tt>. * <tt>:is_live?, :is_draft? or :is_hidden?</tt> methods that returns true/false based upon the state. * <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. * <tt>:publishable?</tt> method that returns true for models where <tt>is :published </tt> has been declared, but <b>false</b> for those where it has not been declared. The Article class also gets a bit of new functionality: Article.all(:draft) => finds all Articles with :publish_status = :draft Article.all(:draft, :author => @author_joe ) => finds all Articles with :publish_status = :draft and author == Joe Todo Need to write more documentation here.. == Usage Scenarios In a Blog/Publishing scenario you could use it like this: class Article ...<snip>... is :published :live, :draft, :hidden end Whereas in another scenario - like in a MenuItem model for a Restaurant - you could use it like this: class MenuItem ...<snip>... is :published :on, :off # the item is either on the menu or not end == RTFM 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. == Errors / Bugs If something is not behaving intuitively, it is a bug, and should be reported. Report it here: http://datamapper.lighthouseapp.com/ === Credits Copyright (c) 2009-07-11 [kematzy gmail com] Loosely based on the ActsAsPublishable plugin by [http://fr.ivolo.us/posts/acts-as-publishable] == Licence Released under the MIT license."
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
+ - dm-is-published.gemspec
55
+ - lib/dm-is-published.rb
56
+ - lib/dm-is-published/is/published.rb
57
+ - lib/dm-is-published/is/version.rb
58
+ - spec/integration/published_spec.rb
59
+ - spec/spec.opts
60
+ - spec/spec_helper.rb
61
+ has_rdoc: false
62
+ homepage: http://github.com/kematzy/dm-is-published
63
+ post_install_message:
64
+ rdoc_options:
65
+ - --charset=UTF-8
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.2.0
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: A DataMapper plugin that provides an easy way to add different states to your models.
87
+ test_files:
88
+ - spec/integration/published_spec.rb
89
+ - spec/spec_helper.rb