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 +1 -0
- data/.specification.example +92 -0
- data/VERSION +1 -1
- data/lib/model_logic.rb +35 -1
- data/rails_generators/publishing_logic_fields/USAGE +2 -0
- data/rails_generators/publishing_logic_fields/publishing_logic_fields_generator.rb +4 -3
- data/rails_generators/publishing_logic_fields/templates/db/migrate/add_publishing_logic_fields.rb.erb +13 -0
- data/spec/lib/model_logic_spec.rb +151 -3
- metadata +5 -2
data/.gitignore
CHANGED
@@ -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.
|
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
|
-
|
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
|
@@ -1,13 +1,14 @@
|
|
1
|
-
class
|
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
|
-
|
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 => "
|
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
|
-
|
13
|
-
|
14
|
-
Factory.create(:fun_item)
|
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.
|
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-
|
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
|