ar_publish_control 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-11-17
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,15 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ ar_publish_control.gemspec
7
+ lib/ar_publish_control.rb
8
+ script/console
9
+ script/destroy
10
+ script/generate
11
+ spec/ar_publish_control_spec.rb
12
+ spec/spec.opts
13
+ spec/spec_helper.rb
14
+ tasks/db.rake
15
+ tasks/rspec.rake
@@ -0,0 +1,7 @@
1
+
2
+ For more information on ar_publish_control, see http://ar_publish_control.rubyforge.org
3
+
4
+ NOTE: Change this information in PostInstall.txt
5
+ You can also delete it if you don't want it.
6
+
7
+
@@ -0,0 +1,166 @@
1
+ This is a gem version of http://github.com/avdgaag/acts_as_publishable ( a Rails plugin)
2
+ Thanks to Arjan van der Gaag for his original work in that plugin, which this gem is heavily based off.
3
+
4
+ His plugin is Copyright (c) 2007 Arjan van der Gaag, released under the MIT license
5
+
6
+ = ar_publish_control
7
+
8
+ http://github.com/ismasan/ar_publish_control
9
+
10
+ == DESCRIPTION:
11
+
12
+ Add start/end publishing dates to your ActiveRecord models.
13
+
14
+ == FEATURES/PROBLEMS:
15
+
16
+ Adds published, unpublished and published_only(boolean) named_scopes to your models.
17
+
18
+ == SYNOPSIS:
19
+
20
+ class Post < ActiveRecord::Base
21
+ publish_control
22
+ end
23
+
24
+ # creating
25
+ @post = Post.create(params[:post])
26
+
27
+ @post.publish!
28
+
29
+ # With start and end dates
30
+ @post.update_attributes :publish_at => Time.now, :unpublish_at => 2.weeks.from_now
31
+
32
+ # Or, in your views...
33
+ <% form_for @post do |f| %>
34
+ ...
35
+ <p>
36
+ <%= f.label :is_published, "Publish" %>
37
+ <%= f.check_box :is_published %>
38
+ </p>
39
+ <p>
40
+ <%= f.label :publish_at, "From" %>
41
+ <%= f.date_select :publish_at %>
42
+ </p>
43
+ <p>
44
+ <%= f.label :unpublish_at, "To" %>
45
+ <%= f.date_select :unpublish_at %>
46
+ </p>
47
+ ...
48
+ <% end %>
49
+
50
+ # in your controllers
51
+ def index
52
+ @posts = Post.published
53
+ end
54
+
55
+ def show
56
+ @post = Post.published.find(params[:id])
57
+ @post.published? # => true
58
+ end
59
+
60
+ # You can nest scopes:
61
+ @post = current_user.posts.published(params[:id])
62
+
63
+ @posts = current_user.posts.published.paginate(:page => params[:page])
64
+
65
+ # unpublished ones
66
+ @posts = Post.unpublished
67
+
68
+ # All posts if logged_in?, only published otherwise
69
+ @posts = Post.published_only?( !logged_in? ).paginate(:page => params[:page])
70
+
71
+ # Unpublish
72
+ @post.unpublish!
73
+ @post.unpublished? # => true
74
+
75
+ # You can access the ones marked as "published" but with a publish date in the future
76
+ @upcoming_post = Post.upcoming
77
+ @upcoming_post.first.upcoming? # => true
78
+
79
+ # You can fetch objects that have expired (ie. they have an unpublish_at date set in the past)
80
+ @expired_posts = Post.expired
81
+ @expired_posts.first.expired? # => true
82
+
83
+ # Finally, if you want those objects where is_published == false, regardless of dates
84
+ @drafts = Post.draft
85
+
86
+ All of these named_scopes can be chained with other finder conditions and paginated with will_paginate
87
+
88
+ == REQUIREMENTS:
89
+
90
+ ActiveRecord
91
+
92
+ == INSTALL:
93
+
94
+ If you haven't yet, add github.com to your gem sources (you only need to do that once):
95
+
96
+ gem sources -a http://gems.github.com
97
+
98
+ Now you can install the normal way:
99
+
100
+ sudo gem install ismasan-ar_publish_control
101
+
102
+ Add the necessary fields to you schema, in a migration:
103
+
104
+ class AddPublishableToPosts < ActiveRecord::Migration
105
+ def self.up
106
+ add_column :posts, :is_published, :boolean, :default => true
107
+ add_column :posts, :publish_at, :datetime
108
+ add_column :posts, :unpublish_at, :datetime
109
+ # update existing records if you have them
110
+ Post.update_all "publish_at = created_at"
111
+ end
112
+ def self.down
113
+ remove_column :posts, :is_published
114
+ remove_column :posts, :publish_at
115
+ remove_column :posts, :unpublish_at
116
+ end
117
+ end
118
+
119
+ rake db:migrate
120
+
121
+ Then, in your Rails app's environment:
122
+
123
+ config.gem 'ismasan-ar_publish_control',:lib => 'ar_publish_control',:source => "http://gems.github.com"
124
+
125
+ ...Or in Merb or elsewhere
126
+
127
+ require "ar_publish_control"
128
+
129
+ If you wan to unpack the gem to you app's "vendor" directory:
130
+
131
+ rake gems:unpack
132
+
133
+ == TEST
134
+
135
+ Test are in the spec directory (rspec). To run them, first initialize the test sqlite database
136
+
137
+ rake db:create
138
+
139
+ Now you can run the specs
140
+
141
+ rake spec
142
+
143
+ == LICENSE:
144
+
145
+ (The MIT License)
146
+
147
+ Copyright (c) 2008 Ismael Celis
148
+
149
+ Permission is hereby granted, free of charge, to any person obtaining
150
+ a copy of this software and associated documentation files (the
151
+ 'Software'), to deal in the Software without restriction, including
152
+ without limitation the rights to use, copy, modify, merge, publish,
153
+ distribute, sublicense, and/or sell copies of the Software, and to
154
+ permit persons to whom the Software is furnished to do so, subject to
155
+ the following conditions:
156
+
157
+ The above copyright notice and this permission notice shall be
158
+ included in all copies or substantial portions of the Software.
159
+
160
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
161
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
162
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
163
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
164
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
165
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
166
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/ar_publish_control'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('ar_publish_control', ArPublishControl::VERSION) do |p|
7
+ p.developer('Ismael Celis', 'ismaelct@gmail.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
10
+ p.rubyforge_name = p.name # TODO this is default value
11
+ # p.extra_deps = [
12
+ # ['activesupport','>= 2.0.2'],
13
+ # ]
14
+ p.extra_dev_deps = [
15
+ ['newgem', ">= #{::Newgem::VERSION}"]
16
+ ]
17
+
18
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
+ p.rsync_args = '-av --delete --ignore-errors'
22
+ end
23
+
24
+ require 'newgem/tasks' # load /tasks/*.rake
25
+ Dir['tasks/**/*.rake'].each { |t| load t }
26
+
27
+ # TODO - want other tests/tasks run by default? Add them to the list
28
+ # task :default => [:spec, :features]
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{ar_publish_control}
5
+ s.version = "0.0.9"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Ismael Celis"]
9
+ s.date = %q{2008-11-18}
10
+ s.description = %q{Publish control for ActiveRecord}
11
+ s.email = ["ismaelct@gmail.com"]
12
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc"]
13
+ s.files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc", "Rakefile", "ar_publish_control.gemspec", "lib/ar_publish_control.rb", "script/console", "script/destroy", "script/generate", "spec/ar_publish_control_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/db.rake", "tasks/rspec.rake"]
14
+ s.has_rdoc = false
15
+ s.homepage = %q{http://www.estadobeta.com}
16
+ s.post_install_message = %q{PostInstall.txt}
17
+ s.rdoc_options = ["--main", "README.rdoc"]
18
+ s.require_paths = ["lib"]
19
+ s.rubyforge_project = %q{ar_publish_control}
20
+ s.rubygems_version = %q{1.3.1}
21
+ s.summary = %q{Publish control for ActiveRecord, with start and optional end dates}
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 2
26
+
27
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
+ s.add_development_dependency(%q<newgem>, [">= 1.1.0"])
29
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
30
+ else
31
+ s.add_dependency(%q<newgem>, [">= 1.1.0"])
32
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
33
+ end
34
+ else
35
+ s.add_dependency(%q<newgem>, [">= 1.1.0"])
36
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
37
+ end
38
+ end
@@ -0,0 +1,229 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module ArPublishControl
5
+ VERSION = '0.0.9'
6
+ # This is a gem version of http://github.com/avdgaag/acts_as_publishable ( a Rails plugin)
7
+ # Thanks to Avdaag for his awesome, super readable code which I ripped off for this gem.
8
+ #
9
+ # Specify this act if you want to show or hide your object based on date/time settings. This act lets you
10
+ # specify two dates two form a range in which the model is publicly available; it is unavailable outside it.
11
+ #
12
+ # == Usage
13
+ #
14
+ # You can add this behaviour to your model like so:
15
+ #
16
+ # class Post < ActiveRecord::Base
17
+ # publish_control
18
+ # end
19
+ #
20
+ # Then you can use it as follows:
21
+ #
22
+ # post = Post.create(:title => 'Hello world')
23
+ # post.published? # => true
24
+ #
25
+ # post.publish!
26
+ # post.published? # => true
27
+ #
28
+ # post.unpublish!
29
+ # post.published? # => false
30
+ #
31
+ # You can use two named_scopes to find the published or unpublished objects.
32
+ # You can chain them with other scopes and use them on association collections:
33
+ #
34
+ # Post.all.count # => 15
35
+ # Post.published.count # => 10
36
+ # Post.unpublished.count # => 5 includes upcoming and expired
37
+ # Post.draft.count # => where is_published == false regardless of date
38
+ # @post.comments.published
39
+ #
40
+ # Post.recent.published
41
+ #
42
+ # Klass.unpublished includes all objects which is_published flag is set to false and/or are expired or upcoming.
43
+ # If you specifically want those where is_published == false regardless of dates, use Klass.draft
44
+ #
45
+ # There's a third named_scope that you can pass a boolean in order to find only published items or all of them
46
+ # This is useful in controller for permission-based publish control
47
+ #
48
+ # @post = Post.published.find(params[:id])
49
+ # @comments = @post.comments.only_published( logged_in? )
50
+ #
51
+ # Available statuses. This constant is useful for autogenerated routes, controller actions and view helpers
52
+ #
53
+ STATUSES = [:published, :draft, :upcoming, :expired]
54
+
55
+ module Publishable
56
+
57
+ def self.included(base) #:nodoc:
58
+ base.extend ClassMethods
59
+ end
60
+
61
+ module ClassMethods
62
+ # == Configuration options
63
+ #
64
+ # Right now this plugin has only one configuration option. Models with no publication dates
65
+ # are by default published, not unpublished. If you want to hide your model when it has no
66
+ # explicit publication date set, you can turn off this behaviour with the
67
+ # +publish_by_default+ (defaults to <tt>true</tt>) option like so:
68
+ #
69
+ # class Post < ActiveRecord::Base
70
+ # publish_control :publish_by_default => false
71
+ # end
72
+ #
73
+ # == Database Schema
74
+ #
75
+ # The model that you're publishing needs to have two special date attributes:
76
+ #
77
+ # * publish_at
78
+ # * unpublish_at
79
+ #
80
+ # These attributes have no further requirements or required validations; they
81
+ # just need to be <tt>datetime</tt>-columns.
82
+ #
83
+ # You can use a migration like this to add these columns to your model:
84
+ #
85
+ # class AddPublicationDatesToPosts < ActiveRecord::Migration
86
+ # def self.up
87
+ # add_column :posts, :publish_at, :datetime
88
+ # add_column :posts, :unpublish_at, :datetime
89
+ # end
90
+ #
91
+ # def self.down
92
+ # remove_column :posts, :publish_at
93
+ # remove_column :posts, :unpublish_at
94
+ # end
95
+ # end
96
+ #
97
+ def publish_control(options = { :publish_by_default => true })
98
+ # don't allow multiple calls
99
+ return if self.included_modules.include?(ArPublishControl::Publishable::InstanceMethods)
100
+ send :include, ArPublishControl::Publishable::InstanceMethods
101
+
102
+ named_scope :published, lambda{{:conditions => published_conditions}}
103
+ named_scope :unpublished, lambda{{:conditions => unpublished_conditions}}
104
+ named_scope :upcoming, lambda{{:conditions => upcoming_conditions}}
105
+ named_scope :expired, lambda {{:conditions => expired_conditions}}
106
+ named_scope :draft, :conditions => {:is_published => false}
107
+
108
+ named_scope :published_only, lambda {|*args|
109
+ bool = (args.first.nil? ? true : (args.first)) # nil = true by default
110
+ bool ? {:conditions => published_conditions} : {}
111
+ }
112
+
113
+ validate :validate_publish_date_consistency
114
+ before_create :publish_by_default if options[:publish_by_default]
115
+ end
116
+
117
+ # Takes a block whose containing SQL queries are limited to
118
+ # published objects. You can pass a boolean flag indicating
119
+ # whether this scope should be applied or not--for example,
120
+ # you might want to disable it when the user is an administrator.
121
+ # By default the scope is applied.
122
+ #
123
+ # Example usage:
124
+ #
125
+ # Post.published_only(!logged_in?)
126
+ # @post.comments.published_only(!logged_in?)
127
+ #
128
+
129
+ protected
130
+
131
+ # returns a string for use in SQL to filter the query to unpublished results only
132
+ # Meant for internal use only
133
+ def unpublished_conditions
134
+ t = Time.now
135
+ ["(#{table_name}.is_published = ? OR #{table_name}.publish_at > ?) OR (#{table_name}.unpublish_at IS NOT NULL AND #{table_name}.unpublish_at < ?)",false,t,t]
136
+ end
137
+
138
+ # return a string for use in SQL to filter the query to published results only
139
+ # Meant for internal use only
140
+ def published_conditions
141
+ t = Time.now
142
+ ["(#{table_name}.is_published = ? AND #{table_name}.publish_at <= ?) AND (#{table_name}.unpublish_at IS NULL OR #{table_name}.unpublish_at > ?)",true,t,t]
143
+ end
144
+
145
+ def upcoming_conditions
146
+ t = Time.now
147
+ ["(#{table_name}.is_published = ? AND #{table_name}.publish_at > ?)",true,t]
148
+ end
149
+
150
+ def expired_conditions
151
+ t = Time.now
152
+ ["(#{table_name}.unpublish_at IS NOT NULL AND #{table_name}.unpublish_at < ?)",t]
153
+ end
154
+ end
155
+
156
+ module InstanceMethods
157
+
158
+ def after_initialize
159
+ write_attribute(:publish_at, Time.now) if publish_at.nil?
160
+ end
161
+
162
+ # ActiveRecrod callback fired on +before_create+ to make
163
+ # sure a new object always gets a publication date; if
164
+ # none is supplied it defaults to the creation date.
165
+ def publish_by_default
166
+ write_attribute(:is_published, true) if is_published.nil?
167
+ end
168
+
169
+ # Validate that unpublish_at is greater than publish_at
170
+ # publish_at must not be nil
171
+ def validate_publish_date_consistency
172
+ if unpublish_at && publish_at && unpublish_at <= publish_at
173
+ errors.add(:unpublish_at,"should be greater than publication date or empty")
174
+ end
175
+ end
176
+
177
+ public
178
+
179
+ # Return whether the current object is published or not
180
+ def published?
181
+ (is_published? && (publish_at <=> Time.now) <= 0) && (unpublish_at.nil? || (unpublish_at <=> Time.now) >= 0)
182
+ end
183
+
184
+ def upcoming?
185
+ (is_published? && publish_at > Time.now)
186
+ end
187
+
188
+ def expired?
189
+ (!unpublish_at.nil? && unpublish_at < Time.now)
190
+ end
191
+
192
+ # Indefinitely publish the current object right now
193
+ def publish
194
+ return if published?
195
+ self.is_published = true
196
+ self.publish_at = Time.now
197
+ self.unpublish_at = nil
198
+ end
199
+
200
+ # Same as publish, but immediatly saves the object.
201
+ # Raises an error when saving fails.
202
+ def publish!
203
+ publish
204
+ save!
205
+ end
206
+
207
+ # Immediatly unpublish the current object
208
+ def unpublish
209
+ return unless published?
210
+ self.is_published = false
211
+ end
212
+
213
+ # Same as unpublish, but immediatly saves the object.
214
+ # Raises an error when saving files.
215
+ def unpublish!
216
+ unpublish
217
+ save!
218
+ end
219
+
220
+ end
221
+ end
222
+
223
+
224
+ end
225
+
226
+ require 'rubygems'
227
+ require 'active_record'
228
+
229
+ ActiveRecord::Base.send :include, ArPublishControl::Publishable
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/ar_publish_control.rb'}"
9
+ puts "Loading ar_publish_control gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,194 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe ArPublishControl do
4
+ it "should have array of available statuses" do
5
+ (ArPublishControl::STATUSES == [:published, :draft, :upcoming, :expired]).should be_true
6
+ end
7
+ end
8
+
9
+ describe Comment do
10
+ before(:each) do
11
+ Post.destroy_all
12
+ @published_post = Post.create do |p|
13
+ p.title = 'some post'
14
+ p.publish_at = 1.day.ago
15
+ p.unpublish_at = 2.days.from_now
16
+ end
17
+
18
+ @unpublished_post = Post.create do |p|
19
+ p.title = 'some other post'
20
+ p.publish_at = 1.day.from_now
21
+ p.unpublish_at = 2.days.from_now
22
+ end
23
+
24
+ @published_comment_in_published_post = @published_post.comments.create do |c|
25
+ c.body = 'some comment'
26
+ c.publish_at = 2.day.ago
27
+ c.unpublish_at = 2.days.from_now
28
+ end
29
+
30
+ @published_comment_in_unpublished_post = @unpublished_post.comments.create do |c|
31
+ c.body = 'some other comment'
32
+ c.publish_at = 1.day.ago
33
+ c.unpublish_at = 2.days.from_now
34
+ end
35
+
36
+ @unpublished_comment_in_published_post = @published_post.comments.create do |c|
37
+ c.body = 'some other comment 2'
38
+ c.publish_at = 1.day.from_now
39
+ c.unpublish_at = 2.days.from_now
40
+ end
41
+
42
+ @unupublished_comment_in_unpublished_post = @unpublished_post.comments.create do |c|
43
+ c.body = 'some other comment 3'
44
+ c.publish_at = 1.day.from_now
45
+ c.unpublish_at = 2.days.from_now
46
+ end
47
+
48
+ end
49
+
50
+ it "should find published comment at class level" do
51
+ Comment.published.size.should == 2
52
+ end
53
+
54
+ it "should find published comments in collection" do
55
+ @published_post.comments.published.size.should == 1
56
+ end
57
+
58
+ it "should find published comments in a collection with conditions" do
59
+ @published_post.published_comments.size.should == 1
60
+ end
61
+
62
+ it "should work with named scope at class level" do
63
+ Comment.published.size.should == 2
64
+ end
65
+
66
+ it "should work with named scope at collection level" do
67
+ @published_post.comments.published.size.should == 1
68
+ end
69
+
70
+ it "should find unpublished with named scope" do
71
+ Comment.unpublished.size.should == 2
72
+ @published_post.comments.unpublished.size.should == 1
73
+ end
74
+
75
+ it "should chain correctly with other scopes" do
76
+ Comment.published.desc.should == [@published_comment_in_unpublished_post,@published_comment_in_published_post]
77
+ end
78
+
79
+ it "should chain correctly with other scopes on collections" do
80
+ @unpublished_comment_in_published_post.publish_at = @published_comment_in_published_post.publish_at + 1.hour
81
+ @unpublished_comment_in_published_post.save
82
+ @published_post.comments.reload
83
+ @published_post.comments.published.desc.should == [@unpublished_comment_in_published_post,@published_comment_in_published_post]
84
+ end
85
+
86
+ it "should find all with conditional flag" do
87
+ Comment.published_only.size.should == 2
88
+ Comment.published_only(true).size.should == 2
89
+ @published_post.comments.published_only(true).first.should == @published_comment_in_published_post
90
+ @published_post.comments.published_only(true).include?(@unpublished_comment_in_published_post).should be_false
91
+ @published_post.comments.published_only(false).include?(@unpublished_comment_in_published_post).should be_true
92
+ @published_post.comments.published_only(false).include?(@published_comment_in_published_post).should be_true
93
+ end
94
+
95
+ it "should validate that unpublish_at is greater than publish_at" do
96
+ @published_comment_in_published_post.unpublish_at = @published_comment_in_published_post.publish_at - 1.minute
97
+ @published_comment_in_published_post.save
98
+ @published_comment_in_published_post.should_not be_valid
99
+ @published_comment_in_published_post.errors.on(:unpublish_at).should == "should be greater than publication date or empty"
100
+ end
101
+
102
+ end
103
+
104
+ # describe Post, 'with no dates' do
105
+ # it "should be published" do
106
+ # puts "DESTROYING #{Post.count}============="
107
+ # Post.destroy_all
108
+ # puts "====================================="
109
+ # post = Post.create(:title => 'some post aaaaaaaaaaaaaaaaaaaaaaaaaaaa')
110
+ # post.published?.should be_true
111
+ # Post.published.include?(post).should be_true
112
+ # end
113
+ # end
114
+
115
+ describe Post, "unpublished by default" do
116
+ before(:each) do
117
+ Article.destroy_all
118
+ @a1 = Article.create(:title=>'a1')
119
+ @invalid = Article.create(:title=>'a2', :publish_at => '')
120
+ end
121
+
122
+ it "should be valid" do
123
+ @a1.should be_valid
124
+ @a1.publish_at.should_not be_nil
125
+ @invalid.publish_at.should_not be_blank
126
+ end
127
+
128
+ it "should be unpublished by default" do
129
+ @a1.published?.should_not be_true
130
+ Article.published.size.should == 0
131
+ end
132
+
133
+ it "should publish" do
134
+ @a1.publish!
135
+ @a1.published?.should be_true
136
+ end
137
+ end
138
+
139
+ describe Post, 'upcoming' do
140
+ before(:each) do
141
+ Post.destroy_all
142
+ @p1 = Post.create(:title => 'p1',:is_published => true,:publish_at => 1.day.from_now) #upcoming
143
+ @p2 = Post.create(:title => 'p2',:is_published => true,:publish_at => 1.week.from_now)#upcoming
144
+ @p3 = Post.create(:title => 'p3',:is_published => false,:publish_at => 1.day.from_now)#unpublished
145
+ @p4 = Post.create(:title => 'p4',:is_published => true)#published
146
+ end
147
+
148
+ it "should have upcoming" do
149
+ @p1.upcoming?.should be_true
150
+ @p2.upcoming?.should be_true
151
+ @p3.upcoming?.should be_false
152
+ @p4.upcoming?.should be_false
153
+ Post.upcoming.size.should == 2
154
+ end
155
+ end
156
+
157
+ describe Post, 'expired' do
158
+ before(:each) do
159
+ Post.destroy_all
160
+ @p1 = Post.create(:title => 'p1',:is_published => true,:publish_at => 2.weeks.ago) #published
161
+ @p2 = Post.create(:title => 'p2',:is_published => true,:publish_at => 2.weeks.ago,:unpublish_at => 1.day.ago)#expired
162
+ @p3 = Post.create(:title => 'p3',:is_published => false,:publish_at => 3.days.ago,:unpublish_at => 2.hours.ago)#unpublished and expired
163
+ end
164
+
165
+ it "should have expired" do
166
+ @p1.expired?.should be_false
167
+ @p2.expired?.should be_true
168
+ @p3.expired?.should be_true
169
+ Post.expired.size.should == 2
170
+ end
171
+ end
172
+
173
+ describe Post, 'draft' do
174
+ before(:each) do
175
+ Post.destroy_all
176
+ @p1 = Post.create(:title => 'p1',:is_published => true,:publish_at => 2.weeks.ago) #published
177
+ @p2 = Post.create(:title => 'p2',:is_published => true,:publish_at => 2.weeks.ago,:unpublish_at => 1.day.ago)#expired
178
+ @p3 = Post.create(:title => 'p3',:is_published => false,:publish_at => 3.days.ago,:unpublish_at => 2.hours.ago)#unpublished and expired
179
+ end
180
+
181
+ it "should have draft" do
182
+ Post.draft.count.should == 1
183
+ Post.draft.first.should == @p3
184
+ end
185
+ end
186
+
187
+ describe "new record" do
188
+ it "should default to Time.now" do
189
+ # d = Time.now
190
+ # Time.stub!(:now).and_return d
191
+ a = Article.new
192
+ a.publish_at.should_not be_nil
193
+ end
194
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,47 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'ar_publish_control'
11
+
12
+ ActiveRecord::Base.establish_connection(
13
+ :adapter=>'sqlite3',
14
+ :dbfile=> File.join(File.dirname(__FILE__),'db','test.db')
15
+ )
16
+
17
+ #ActiveRecord::Base.connection.query_cache_enabled = false
18
+
19
+ LOGGER = Logger.new(File.dirname(__FILE__)+'/log/test.log')
20
+ ActiveRecord::Base.logger = LOGGER
21
+
22
+ class Comment < ActiveRecord::Base
23
+ belongs_to :post
24
+
25
+ named_scope :recent, lambda{|limit|
26
+ {:order => 'created_at desc',:limit => limit}
27
+ }
28
+
29
+ named_scope :desc, :order => 'publish_at desc'
30
+
31
+ publish_control
32
+
33
+ end
34
+
35
+ class Post < ActiveRecord::Base
36
+
37
+ has_many :comments, :dependent => :destroy
38
+
39
+ has_many :published_comments, :class_name => 'Comment', :conditions => Comment.published_conditions
40
+
41
+ publish_control
42
+
43
+ end
44
+
45
+ class Article < ActiveRecord::Base
46
+ publish_control :publish_by_default => false
47
+ end
@@ -0,0 +1,57 @@
1
+ database_config = {
2
+ :adapter=>'sqlite3',
3
+ :dbfile=> File.join(File.dirname(__FILE__),'..','spec','db','test.db')
4
+ }
5
+
6
+ ActiveRecord::Base.establish_connection(database_config)
7
+ # define a migration
8
+ class TestSchema < ActiveRecord::Migration
9
+ def self.up
10
+ create_table :posts do |t|
11
+ t.string :title
12
+ t.boolean :is_published
13
+ t.datetime :publish_at
14
+ t.datetime :unpublish_at
15
+ t.timestamps
16
+ end
17
+
18
+ create_table :articles do |t|
19
+ t.string :title
20
+ t.boolean :is_published
21
+ t.datetime :publish_at
22
+ t.datetime :unpublish_at
23
+ t.timestamps
24
+ end
25
+
26
+ create_table :comments do |t|
27
+ t.text :body
28
+ t.boolean :is_published
29
+ t.integer :post_id
30
+ t.datetime :publish_at
31
+ t.datetime :unpublish_at
32
+ t.timestamps
33
+ end
34
+ end
35
+
36
+ def self.down
37
+ drop_table :posts
38
+ drop_table :comments
39
+ drop_table :articles
40
+ end
41
+ end
42
+
43
+
44
+ namespace :db do
45
+ desc "migrate test schema"
46
+ task :create do
47
+ File.unlink(database_config[:dbfile])
48
+ ActiveRecord::Base.connection # this creates the DB
49
+ # run the migration
50
+ TestSchema.migrate(:up)
51
+ end
52
+
53
+ desc "Destroy test schema"
54
+ task :destroy do
55
+ TestSchema.migrate(:down)
56
+ end
57
+ end
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ar_publish_control
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.9
5
+ platform: ruby
6
+ authors:
7
+ - Ismael Celis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-05 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: newgem
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.3
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hoe
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.0
34
+ version:
35
+ description: Add start/end publishing dates to your ActiveRecord models.
36
+ email:
37
+ - ismaelct@gmail.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - History.txt
44
+ - Manifest.txt
45
+ - PostInstall.txt
46
+ - README.rdoc
47
+ files:
48
+ - History.txt
49
+ - Manifest.txt
50
+ - PostInstall.txt
51
+ - README.rdoc
52
+ - Rakefile
53
+ - ar_publish_control.gemspec
54
+ - lib/ar_publish_control.rb
55
+ - script/console
56
+ - script/destroy
57
+ - script/generate
58
+ - spec/ar_publish_control_spec.rb
59
+ - spec/spec.opts
60
+ - spec/spec_helper.rb
61
+ - tasks/db.rake
62
+ - tasks/rspec.rake
63
+ has_rdoc: true
64
+ homepage: http://github.com/ismasan/ar_publish_control
65
+ licenses: []
66
+
67
+ post_install_message: PostInstall.txt
68
+ rdoc_options:
69
+ - --main
70
+ - README.rdoc
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ requirements: []
86
+
87
+ rubyforge_project: ar_publish_control
88
+ rubygems_version: 1.3.5
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Add start/end publishing dates to your ActiveRecord models.
92
+ test_files: []
93
+