publishing_logic 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -20,3 +20,4 @@ pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
22
  publishing_logic.gemspec
23
+ .specification
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: publishing_logic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Unboxed Consulting
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-09 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
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.9
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: cucumber
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: Publishing logic for ActiveRecord models
36
+ email: enquiries@unboxedconsulting.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.rdoc
44
+ files:
45
+ - .document
46
+ - .gitignore
47
+ - LICENSE
48
+ - README.rdoc
49
+ - Rakefile
50
+ - VERSION
51
+ - features/publishing_logic.feature
52
+ - features/step_definitions/publishing_logic_steps.rb
53
+ - features/support/env.rb
54
+ - lib/model_logic.rb
55
+ - lib/publishing_logic.rb
56
+ - rails_generators/publishing_logic_fields/publishing_logic_fields_generator.rb
57
+ - spec/lib/model_logic_spec.rb
58
+ - spec/publishing_logic_spec.rb
59
+ - spec/spec.opts
60
+ - spec/spec_helper.rb
61
+ has_rdoc: true
62
+ homepage: http://github.com/tomtt/publishing_logic
63
+ licenses: []
64
+
65
+ post_install_message:
66
+ rdoc_options:
67
+ - --charset=UTF-8
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ requirements: []
83
+
84
+ rubyforge_project:
85
+ rubygems_version: 1.3.5
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Publishing logic for ActiveRecord models
89
+ test_files:
90
+ - spec/lib/model_logic_spec.rb
91
+ - spec/publishing_logic_spec.rb
92
+ - spec/spec_helper.rb
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.1.0
data/lib/model_logic.rb CHANGED
@@ -1,7 +1,41 @@
1
1
  module PublishingLogic
2
2
  module ModelLogic
3
+ PUBLISHED_CONDITIONS = <<EOT
4
+ publishing_enabled = true AND
5
+ (published_until is null or published_until > ?) AND
6
+ (published_at is null or published_at < ?)
7
+ EOT
8
+
3
9
  def published?
4
- true
10
+ return false if published_at && Time.now < published_at
11
+ return false if published_until && Time.now > published_until
12
+ publishing_enabled?
5
13
  end
14
+
15
+ def self.included(base)
16
+ base.extend(ClassMethods)
17
+ base.instance_eval do
18
+ named_scope :published, lambda {{ :conditions => [PUBLISHED_CONDITIONS, Time.now.utc, Time.now.utc] }} do
19
+ def newest
20
+ find(:first, :order => "published_at DESC")
21
+ end
22
+
23
+ def oldest
24
+ find(:last, :order => "published_at DESC")
25
+ end
26
+ end
27
+
28
+ # If objects have identical published_at values, order by created_at. If these are
29
+ # identical as well, then order by id. This is done to ensure there is a unique
30
+ # ordering of objects, ordering by newest and oldest should result in arrays that are
31
+ # the inverse of the other.
32
+ named_scope :by_date_oldest_first, :order => 'published_at ASC, created_at ASC, id ASC'
33
+ named_scope :by_date_newest_first, :order => 'published_at DESC, created_at DESC, id DESC'
34
+ end
35
+ end
36
+
37
+ module ClassMethods
38
+ end
39
+
6
40
  end
7
41
  end
@@ -0,0 +1,2 @@
1
+ Real usage: ./script/generate publishing_logic_fields model_name [options]
2
+ Note: The generator will fail if the model does not exist
@@ -1,13 +1,14 @@
1
- class PublishingLogicGenerator < Rails::Generator::NamedBase
1
+ class PublishingLogicFieldsGenerator < Rails::Generator::NamedBase
2
2
  def initialize(args, options)
3
3
  super(args, options)
4
4
  end
5
5
 
6
6
  def manifest
7
7
  record do |m|
8
- m.migration_template 'publishing_logic_fields.rb', 'db/migrate', :assigns => {
8
+ class_name.camelize.constantize # Raise an error if model does not yet exist
9
+ m.migration_template 'db/migrate/add_publishing_logic_fields.rb.erb', 'db/migrate', :assigns => {
9
10
  :migration_name => "AddPublishingLogicFieldsTo#{class_name.pluralize.gsub(/::/, '')}"
10
- }, :migration_file_name => "add_publishing_logic_field_to_#{file_path.gsub(/\//, '_').pluralize}"
11
+ }, :migration_file_name => "add_publishing_logic_fields_to_#{file_path.gsub(/\//, '_').pluralize}"
11
12
  end
12
13
  end
13
14
  end
@@ -0,0 +1,13 @@
1
+ class <%= migration_name %> < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :<%= class_name.underscore.camelize.tableize %>, :publishing_enabled, :boolean
4
+ add_column :<%= class_name.underscore.camelize.tableize %>, :published_at, :datetime
5
+ add_column :<%= class_name.underscore.camelize.tableize %>, :published_until, :datetime
6
+ end
7
+
8
+ def self.down
9
+ remove_column :<%= class_name.underscore.camelize.tableize %>, :publishing_enabled
10
+ remove_column :<%= class_name.underscore.camelize.tableize %>, :published_at
11
+ remove_column :<%= class_name.underscore.camelize.tableize %>, :published_until
12
+ end
13
+ end
@@ -9,8 +9,156 @@ Factory.define :fun_item do |c|
9
9
  end
10
10
 
11
11
  describe PublishingLogic::ModelLogic do
12
- it "should be published by default" do
13
- # Factory.create(:fun_item, :publishing_enabled => true).should be_published
14
- Factory.create(:fun_item).should be_published
12
+ def create_objects_with_different_published_at_dates
13
+ @object2 = Factory.create(:fun_item, :publishing_enabled => true, :published_at => 2.days.ago)
14
+ @object1 = Factory.create(:fun_item, :publishing_enabled => true, :published_at => 1.days.ago)
15
+ @object3 = Factory.create(:fun_item, :publishing_enabled => true, :published_at => 3.days.ago)
16
+ end
17
+
18
+ describe "published?" do
19
+ describe "with publishing enabled" do
20
+ it "should be published by default" do
21
+ Factory.create(:fun_item,
22
+ :publishing_enabled => true,
23
+ :published_at => nil,
24
+ :published_until => nil).should be_published
25
+ end
26
+
27
+ it "should not be published if the published_at datetime is in the future" do
28
+ Factory.create(:fun_item,
29
+ :publishing_enabled => true,
30
+ :published_at => 5.seconds.from_now,
31
+ :published_until => nil).should_not be_published
32
+ end
33
+
34
+ it "should not be published if the published_until datetime is in the past" do
35
+ Factory.create(:fun_item,
36
+ :publishing_enabled => true,
37
+ :published_at => nil,
38
+ :published_until => 5.seconds.ago).should_not be_published
39
+ end
40
+ end
41
+ describe "with publishing disabled" do
42
+ it "should not be published" do
43
+ Factory.create(:fun_item,
44
+ :publishing_enabled => false,
45
+ :published_at => 1.days.ago,
46
+ :published_until => 10.days.from_now).should_not be_published
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "published named scope" do
52
+ it "should include published objects" do
53
+ fun_item = Factory.create(:fun_item, :publishing_enabled => true)
54
+ FunItem.published.should == [fun_item]
55
+ end
56
+
57
+ it "should not include any unpublished objects" do
58
+ fun_item = Factory.create(:fun_item, :publishing_enabled => false)
59
+ FunItem.published.should be_empty
60
+ end
61
+
62
+ # it "should not expose a published episode published an hour ago" do
63
+ # article = Factory.create(:episode, :is_hidden => false, :published_at => 1.hour.from_now, :published_until => nil)
64
+ # Episode.published.should == []
65
+ # end
66
+
67
+ it "should not include objects with a published_until in the past" do
68
+ Factory.create(:fun_item,
69
+ :publishing_enabled => true,
70
+ :published_until => 5.seconds.ago)
71
+ FunItem.published.should be_empty
72
+ end
73
+
74
+ it "should not include objects with a published_at in the future" do
75
+ Factory.create(:fun_item,
76
+ :publishing_enabled => true,
77
+ :published_at => 5.seconds.from_now)
78
+ FunItem.published.should be_empty
79
+ end
80
+
81
+ it "should get a new Time.now for each invocation of the named scope" do
82
+ item = Factory.create(:fun_item,
83
+ :publishing_enabled => true,
84
+ :published_until => 10.days.from_now)
85
+ mock_now = mock('now', :utc => 20.days.from_now, :to_f => 0)
86
+ Time.stub(:now).and_return mock_now
87
+ FunItem.published.should be_empty
88
+ end
89
+
90
+ it "should use the utc of the current time" do
91
+ # Make sure utc is used, which is hard to test as a behaviour
92
+ mock_now = mock('now')
93
+ Time.stub(:now).and_return mock_now
94
+ mock_now.should_receive(:utc).twice
95
+ FunItem.published
96
+ end
97
+
98
+ describe "newest" do
99
+ before do
100
+ create_objects_with_different_published_at_dates
101
+ end
102
+
103
+ it "should be the most recently published object" do
104
+ FunItem.published.newest.should == @object1
105
+ end
106
+ end
107
+ describe "oldest" do
108
+ it "should be the object published the longest ago" do
109
+ FunItem.published.oldest.should == @object3
110
+ end
111
+ end
112
+ end
113
+
114
+ describe "ordering by published_at" do
115
+ describe "by date oldest first" do
116
+ it "should return the items, oldest first" do
117
+ create_objects_with_different_published_at_dates
118
+ FunItem.by_date_oldest_first.map(&:id).should == [@object3,
119
+ @object2,
120
+ @object1].map(&:id)
121
+ end
122
+
123
+ it "should order by created_at date if published_ats are equal" do
124
+ create_objects_with_different_published_at_dates
125
+ @object2b = Factory.create(:fun_item,
126
+ :publishing_enabled => true,
127
+ :published_at => @object2.published_at,
128
+ :created_at => 3.days.ago)
129
+ FunItem.by_date_oldest_first.map(&:id).should == [@object3,
130
+ @object2b,
131
+ @object2,
132
+ @object1].map(&:id)
133
+ end
134
+ end
135
+
136
+ describe "by date newest first" do
137
+ it "should return the items, oldest first" do
138
+ create_objects_with_different_published_at_dates
139
+ FunItem.by_date_newest_first.map(&:id).should == [@object1,
140
+ @object2,
141
+ @object3].map(&:id)
142
+ end
143
+
144
+ it "should order by created_at date if published_ats are equal" do
145
+ create_objects_with_different_published_at_dates
146
+ @object2b = Factory.create(:fun_item,
147
+ :publishing_enabled => true,
148
+ :published_at => @object2.published_at,
149
+ :created_at => 3.days.from_now)
150
+ FunItem.by_date_newest_first.map(&:id).should == [@object1,
151
+ @object2b,
152
+ @object2,
153
+ @object3].map(&:id)
154
+ end
155
+ end
156
+
157
+ it "should have a newest first ordering that is the reverse of the oldest first ordering for identical objects" do
158
+ creation_time = 2.days.ago
159
+ publish_time = 1.days.ago
160
+ 5.times { Factory.create(:fun_item, :created_at => creation_time, :published_at => publish_time) }
161
+ FunItem.by_date_newest_first.map(&:id).should == FunItem.by_date_oldest_first.map(&:id).reverse
162
+ end
15
163
  end
16
164
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: publishing_logic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Unboxed Consulting
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-09 00:00:00 +00:00
12
+ date: 2009-12-10 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -44,6 +44,7 @@ extra_rdoc_files:
44
44
  files:
45
45
  - .document
46
46
  - .gitignore
47
+ - .specification.example
47
48
  - LICENSE
48
49
  - README.rdoc
49
50
  - Rakefile
@@ -53,7 +54,9 @@ files:
53
54
  - features/support/env.rb
54
55
  - lib/model_logic.rb
55
56
  - lib/publishing_logic.rb
57
+ - rails_generators/publishing_logic_fields/USAGE
56
58
  - rails_generators/publishing_logic_fields/publishing_logic_fields_generator.rb
59
+ - rails_generators/publishing_logic_fields/templates/db/migrate/add_publishing_logic_fields.rb.erb
57
60
  - spec/lib/model_logic_spec.rb
58
61
  - spec/publishing_logic_spec.rb
59
62
  - spec/spec.opts