postablr 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +22 -0
- data/Rakefile +40 -0
- data/app/assets/javascripts/postablr/application.js +15 -0
- data/app/assets/javascripts/postablr/blog.js +2 -0
- data/app/assets/javascripts/postablr/entries.js +2 -0
- data/app/assets/stylesheets/postablr/application.css +13 -0
- data/app/assets/stylesheets/postablr/blog.css +4 -0
- data/app/assets/stylesheets/postablr/entries.css +4 -0
- data/app/controllers/postablr/application_controller.rb +4 -0
- data/app/controllers/postablr/blog_controller.rb +21 -0
- data/app/controllers/postablr/entries_controller.rb +43 -0
- data/app/helpers/postablr/application_helper.rb +4 -0
- data/app/helpers/postablr/blog_helper.rb +27 -0
- data/app/helpers/postablr/entries_helper.rb +4 -0
- data/app/helpers/postablr/truncate_html_helper.rb +52 -0
- data/app/models/postablr/ar_publish.rb +172 -0
- data/app/models/postablr/entry.rb +37 -0
- data/app/models/postablr/entry/audio.rb +23 -0
- data/app/models/postablr/entry/image.rb +17 -0
- data/app/models/postablr/entry/link.rb +8 -0
- data/app/models/postablr/entry/post.rb +8 -0
- data/app/models/postablr/entry/quote.rb +7 -0
- data/app/models/postablr/entry/video.rb +29 -0
- data/app/uploaders/entry_audio_uploader.rb +55 -0
- data/app/uploaders/entry_photo_uploader.rb +42 -0
- data/app/views/layouts/postablr/application.html.erb +14 -0
- data/app/views/postablr/blog/_entry_display.haml +3 -0
- data/app/views/postablr/blog/comments/_comment.haml +10 -0
- data/app/views/postablr/blog/comments/_form.haml +6 -0
- data/app/views/postablr/blog/comments/create.js.haml +5 -0
- data/app/views/postablr/blog/comments/new.html.haml +0 -0
- data/app/views/postablr/blog/comments/new.js.haml +2 -0
- data/app/views/postablr/blog/entries/show.haml +39 -0
- data/app/views/postablr/blog/show.html.haml +46 -0
- data/app/views/postablr/blog/show/_aside.haml +19 -0
- data/app/views/postablr/blog/show/_audio.haml +13 -0
- data/app/views/postablr/blog/show/_image.haml +13 -0
- data/app/views/postablr/blog/show/_link.haml +11 -0
- data/app/views/postablr/blog/show/_post.haml +14 -0
- data/app/views/postablr/blog/show/_quote.haml +12 -0
- data/app/views/postablr/blog/show/_video.haml +16 -0
- data/app/views/postablr/entries/_entries_menu.haml +14 -0
- data/app/views/postablr/entries/_entry.haml +4 -0
- data/app/views/postablr/entries/_form.haml +58 -0
- data/app/views/postablr/entries/edit.haml +1 -0
- data/app/views/postablr/entries/fields/_audio.haml +4 -0
- data/app/views/postablr/entries/fields/_image.haml +2 -0
- data/app/views/postablr/entries/fields/_link.haml +3 -0
- data/app/views/postablr/entries/fields/_post.haml +3 -0
- data/app/views/postablr/entries/fields/_quote.haml +3 -0
- data/app/views/postablr/entries/fields/_video.haml +2 -0
- data/app/views/postablr/entries/index.html.haml +11 -0
- data/app/views/postablr/entries/index.js.haml +2 -0
- data/app/views/postablr/entries/list/_audio.haml +14 -0
- data/app/views/postablr/entries/list/_image.haml +12 -0
- data/app/views/postablr/entries/list/_link.haml +11 -0
- data/app/views/postablr/entries/list/_post.haml +14 -0
- data/app/views/postablr/entries/list/_quote.haml +11 -0
- data/app/views/postablr/entries/list/_video.haml +17 -0
- data/app/views/postablr/entries/new.html.haml +2 -0
- data/app/views/postablr/entries/show.html.haml +5 -0
- data/config/routes.rb +20 -0
- data/db/migrate/20121222195404_create_postablr_entries.rb +18 -0
- data/db/migrate/20121222195417_create_postablr_entry_videos.rb +16 -0
- data/db/migrate/20121222200141_create_postablr_entry_quotes.rb +10 -0
- data/db/migrate/20121222200237_create_postablr_entry_posts.rb +10 -0
- data/db/migrate/20121222200303_create_postablr_entry_links.rb +10 -0
- data/db/migrate/20121222200402_create_postablr_entry_images.rb +12 -0
- data/db/migrate/20121222200810_create_postablr_entry_audios.rb +12 -0
- data/lib/postablr.rb +4 -0
- data/lib/postablr/engine.rb +11 -0
- data/lib/postablr/version.rb +3 -0
- data/lib/tasks/postablr_tasks.rake +4 -0
- data/test/factories/postablr_entries.rb +16 -0
- data/test/factories/postablr_entry_audios.rb +9 -0
- data/test/factories/postablr_entry_images.rb +10 -0
- data/test/factories/postablr_entry_links.rb +8 -0
- data/test/factories/postablr_entry_posts.rb +9 -0
- data/test/factories/postablr_entry_quotes.rb +8 -0
- data/test/factories/postablr_entry_videos.rb +14 -0
- metadata +358 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
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.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Postablr
|
2
|
+
|
3
|
+
Postablr is a mountable blog engine for rails 3
|
4
|
+
|
5
|
+
but is a work in progress, don´t use in production!
|
6
|
+
|
7
|
+
## Niceties
|
8
|
+
|
9
|
+
+ Devise compatible
|
10
|
+
+ Tumblr style for post types (image, text, video, quote)
|
11
|
+
+ Sanitize html
|
12
|
+
|
13
|
+
+ TODO
|
14
|
+
+ tagging support - depend on acts_as_taggable_on
|
15
|
+
+ Rich text editor support
|
16
|
+
+ blogs support if many blogs in site
|
17
|
+
|
18
|
+
# instalation
|
19
|
+
|
20
|
+
gem install postablr
|
21
|
+
|
22
|
+
rake postablr:install:migrations
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Postablr'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
Bundler::GemHelper.install_tasks
|
29
|
+
|
30
|
+
require 'rake/testtask'
|
31
|
+
|
32
|
+
Rake::TestTask.new(:test) do |t|
|
33
|
+
t.libs << 'lib'
|
34
|
+
t.libs << 'test'
|
35
|
+
t.pattern = 'test/**/*_test.rb'
|
36
|
+
t.verbose = false
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
task :default => :test
|
@@ -0,0 +1,15 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// the compiled file.
|
9
|
+
//
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
12
|
+
//
|
13
|
+
//= require jquery
|
14
|
+
//= require jquery_ujs
|
15
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_dependency "postablr/application_controller"
|
2
|
+
|
3
|
+
module Postablr
|
4
|
+
class BlogController < ApplicationController
|
5
|
+
|
6
|
+
def show
|
7
|
+
@entries = Postablr::Entry.includes(:postable).published.order("postablr_entries.postable_type.created_at desc").page(params[:page]).per(6)
|
8
|
+
end
|
9
|
+
|
10
|
+
def filter
|
11
|
+
@entries = Postablr::Entry.includes(:postable).published.where("postablr_entries.postable_type =?", "Entry::#{params[:filter].capitalize}").order("postablr_entries.created_at desc").page(params[:page]).per(6)
|
12
|
+
render :show
|
13
|
+
end
|
14
|
+
|
15
|
+
def tags_get
|
16
|
+
@q = params[:tag]
|
17
|
+
@tags = ActsAsTaggableOn::Tag.where{( name =~ "#{@q}%")}
|
18
|
+
render :json=> @tags.collect{ |tag| {"caption"=> tag.name, "value"=>tag.id.to_s } }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_dependency "postablr/application_controller"
|
2
|
+
|
3
|
+
module Postablr
|
4
|
+
class EntriesController < ApplicationController
|
5
|
+
|
6
|
+
before_filter :authenticate_user!
|
7
|
+
|
8
|
+
inherit_resources
|
9
|
+
|
10
|
+
respond_to :js
|
11
|
+
|
12
|
+
def new
|
13
|
+
@entry = current_user.entries.new
|
14
|
+
@entry.postable = "Postablr::Entry::#{params[:type].capitalize}".constantize.send(:new)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create
|
18
|
+
@entry = current_user.entries.new(params[:entry].except("postable_attributes"))
|
19
|
+
@entry.tag_list = ActsAsTaggableOn::Tag.find(params[:tag_list_input]).map(&:name) unless params[:tag_list_input].blank?
|
20
|
+
@entry.postable = "Postablr::Entry::#{params[:type].capitalize}".constantize.new(params[:entry][:postable_attributes])
|
21
|
+
create!{
|
22
|
+
if @entry.errors.blank?
|
23
|
+
entry_url(@entry)
|
24
|
+
end
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def update
|
29
|
+
@entry = current_user.entries.find(params[:post_id])
|
30
|
+
@entry.tag_list = ActsAsTaggableOn::Tag.find(params[:tag_list_input]).map(&:name) unless params[:tag_list_input].blank?
|
31
|
+
update!{ entry_url(@entry) if @entry.errors.blank? }
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
def begin_of_association_chain
|
36
|
+
current_user
|
37
|
+
end
|
38
|
+
|
39
|
+
def collection
|
40
|
+
@entries ||= end_of_association_chain.order("created_at desc") #.page(params[:page]).per(6)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Postablr
|
2
|
+
module BlogHelper
|
3
|
+
def sanitize_clean(html, truncate = false, link=nil)
|
4
|
+
unless truncate
|
5
|
+
Sanitize.clean(html, Sanitize::Config::RESTRICTED)
|
6
|
+
else
|
7
|
+
truncate_html(clean_html( html ), truncate , link )
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def sanitize_strict(html, truncate = false, link=nil)
|
12
|
+
unless truncate
|
13
|
+
Sanitize.clean(html, Sanitize::Config::RESTRICTED)
|
14
|
+
else
|
15
|
+
truncate_html(Sanitize.clean(html, Sanitize::Config::RESTRICTED), truncate , link )
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def clean_html(html)
|
20
|
+
Sanitize.clean(html, Sanitize::Config::BASIC)
|
21
|
+
end
|
22
|
+
|
23
|
+
def sanitize_relaxed(html)
|
24
|
+
Sanitize.clean(html, Sanitize::Config::RELAXED)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require "rubygems"
|
3
|
+
require "nokogiri"
|
4
|
+
|
5
|
+
module Postablr::TruncateHtmlHelper
|
6
|
+
|
7
|
+
def truncate_html(text, max_length = 10, ellipsis = "...")
|
8
|
+
doc = Nokogiri::HTML::DocumentFragment.parse text
|
9
|
+
# remove syntax highlighting
|
10
|
+
doc.css("div.CodeRay").each do |node|
|
11
|
+
node.remove
|
12
|
+
end
|
13
|
+
content_length = doc.inner_text.length
|
14
|
+
if content_length > max_length
|
15
|
+
doc = doc.truncate(max_length)
|
16
|
+
more = Nokogiri::HTML::DocumentFragment.parse ellipsis
|
17
|
+
doc.children.last.add_child(more.children)
|
18
|
+
doc.to_html.html_safe
|
19
|
+
else
|
20
|
+
text.to_s
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
module NokogiriTruncator
|
27
|
+
module NodeWithChildren
|
28
|
+
def truncate(max_length)
|
29
|
+
return self if inner_text.length <= max_length
|
30
|
+
truncated_node = self.dup
|
31
|
+
truncated_node.children.remove
|
32
|
+
|
33
|
+
self.children.each do |node|
|
34
|
+
remaining_length = max_length - truncated_node.inner_text.length
|
35
|
+
break if remaining_length <= 0
|
36
|
+
truncated_node.add_child node.truncate(remaining_length)
|
37
|
+
end
|
38
|
+
truncated_node
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module TextNode
|
43
|
+
def truncate(max_length)
|
44
|
+
Nokogiri::XML::Text.new(content[0..(max_length - 1)], parent)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
Nokogiri::HTML::DocumentFragment.send(:include, NokogiriTruncator::NodeWithChildren)
|
51
|
+
Nokogiri::XML::Element.send(:include, NokogiriTruncator::NodeWithChildren)
|
52
|
+
Nokogiri::XML::Text.send(:include, NokogiriTruncator::TextNode)
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
# extracted from https://github.com/ismasan/ar_publish_control
|
3
|
+
module Postablr
|
4
|
+
module ArPublish
|
5
|
+
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
#extend ClassMethods
|
10
|
+
@statuses = [:published, :draft, :upcoming, :expired]
|
11
|
+
|
12
|
+
after_initialize :fill_default_publish
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
# == Configuration options
|
17
|
+
#
|
18
|
+
# Right now this plugin has only one configuration option. Models with no publication dates
|
19
|
+
# are by default published, not unpublished. If you want to hide your model when it has no
|
20
|
+
# explicit publication date set, you can turn off this behaviour with the
|
21
|
+
# +publish_by_default+ (defaults to <tt>true</tt>) option like so:
|
22
|
+
#
|
23
|
+
# class Post < ActiveRecord::Base
|
24
|
+
# publish_control :publish_by_default => false
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# == Database Schema
|
28
|
+
#
|
29
|
+
# The model that you're publishing needs to have two special date attributes:
|
30
|
+
#
|
31
|
+
# * publish_at
|
32
|
+
# * unpublish_at
|
33
|
+
#
|
34
|
+
# These attributes have no further requirements or required validations; they
|
35
|
+
# just need to be <tt>datetime</tt>-columns.
|
36
|
+
#
|
37
|
+
# You can use a migration like this to add these columns to your model:
|
38
|
+
#
|
39
|
+
# class AddPublicationDatesToPosts < ActiveRecord::Migration
|
40
|
+
# def self.up
|
41
|
+
# add_column :posts, :publish_at, :datetime
|
42
|
+
# add_column :posts, :unpublish_at, :datetime
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# def self.down
|
46
|
+
# remove_column :posts, :publish_at
|
47
|
+
# remove_column :posts, :unpublish_at
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
def publish_control(options = { :publish_by_default => true })
|
52
|
+
# don't allow multiple calls
|
53
|
+
#return if self.included_modules.include?(ArPublishControl::Publishable::InstanceMethods)
|
54
|
+
#send :include, ArPublishControl::Publishable::InstanceMethods
|
55
|
+
|
56
|
+
scope :published, lambda{{:conditions => published_conditions}}
|
57
|
+
scope :unpublished, lambda{{:conditions => unpublished_conditions}}
|
58
|
+
scope :upcoming, lambda{{:conditions => upcoming_conditions}}
|
59
|
+
scope :expired, lambda {{:conditions => expired_conditions}}
|
60
|
+
scope :draft, :conditions => {:is_published => false}
|
61
|
+
|
62
|
+
scope :published_only, lambda {|*args|
|
63
|
+
bool = (args.first.nil? ? true : (args.first)) # nil = true by default
|
64
|
+
bool ? {:conditions => published_conditions} : {}
|
65
|
+
}
|
66
|
+
|
67
|
+
validate :validate_publish_date_consistency
|
68
|
+
before_create :publish_by_default if options[:publish_by_default]
|
69
|
+
end
|
70
|
+
|
71
|
+
# Takes a block whose containing SQL queries are limited to
|
72
|
+
# published objects. You can pass a boolean flag indicating
|
73
|
+
# whether this scope should be applied or not--for example,
|
74
|
+
# you might want to disable it when the user is an administrator.
|
75
|
+
# By default the scope is applied.
|
76
|
+
#
|
77
|
+
# Example usage:
|
78
|
+
#
|
79
|
+
# Post.published_only(!logged_in?)
|
80
|
+
# @post.comments.published_only(!logged_in?)
|
81
|
+
#
|
82
|
+
|
83
|
+
protected
|
84
|
+
|
85
|
+
# returns a string for use in SQL to filter the query to unpublished results only
|
86
|
+
# Meant for internal use only
|
87
|
+
def unpublished_conditions
|
88
|
+
t = Time.now
|
89
|
+
["(#{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]
|
90
|
+
end
|
91
|
+
|
92
|
+
# return a string for use in SQL to filter the query to published results only
|
93
|
+
# Meant for internal use only
|
94
|
+
def published_conditions
|
95
|
+
t = Time.now
|
96
|
+
["(#{table_name}.is_published = ? AND #{table_name}.publish_at <= ?) AND (#{table_name}.unpublish_at IS NULL OR #{table_name}.unpublish_at > ?)",true,t,t]
|
97
|
+
end
|
98
|
+
|
99
|
+
def upcoming_conditions
|
100
|
+
t = Time.now
|
101
|
+
["(#{table_name}.is_published = ? AND #{table_name}.publish_at > ?)",true,t]
|
102
|
+
end
|
103
|
+
|
104
|
+
def expired_conditions
|
105
|
+
t = Time.now
|
106
|
+
["(#{table_name}.unpublish_at IS NOT NULL AND #{table_name}.unpublish_at < ?)",t]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
def fill_default_publish
|
112
|
+
self.publish_at = Time.now if self.publish_at.nil?
|
113
|
+
end
|
114
|
+
|
115
|
+
# ActiveRecrod callback fired on +before_create+ to make
|
116
|
+
# sure a new object always gets a publication date; if
|
117
|
+
# none is supplied it defaults to the creation date.
|
118
|
+
def publish_by_default
|
119
|
+
self.is_published = true if is_published.nil?
|
120
|
+
end
|
121
|
+
|
122
|
+
# Validate that unpublish_at is greater than publish_at
|
123
|
+
# publish_at must not be nil
|
124
|
+
def validate_publish_date_consistency
|
125
|
+
if unpublish_at && publish_at && unpublish_at <= publish_at
|
126
|
+
errors.add(:unpublish_at,"should be greater than publication date or empty")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Return whether the current object is published or not
|
131
|
+
def published?
|
132
|
+
(is_published? && (publish_at <=> Time.now) <= 0) && (unpublish_at.nil? || (unpublish_at <=> Time.now) >= 0)
|
133
|
+
end
|
134
|
+
|
135
|
+
def upcoming?
|
136
|
+
(is_published? && publish_at > Time.now)
|
137
|
+
end
|
138
|
+
|
139
|
+
def expired?
|
140
|
+
(!unpublish_at.nil? && unpublish_at < Time.now)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Indefinitely publish the current object right now
|
144
|
+
def publish
|
145
|
+
return if published?
|
146
|
+
self.is_published = true
|
147
|
+
self.publish_at = Time.now
|
148
|
+
self.unpublish_at = nil
|
149
|
+
end
|
150
|
+
|
151
|
+
# Same as publish, but immediatly saves the object.
|
152
|
+
# Raises an error when saving fails.
|
153
|
+
def publish!
|
154
|
+
publish
|
155
|
+
save!
|
156
|
+
end
|
157
|
+
|
158
|
+
# Immediatly unpublish the current object
|
159
|
+
def unpublish
|
160
|
+
return unless published?
|
161
|
+
self.is_published = false
|
162
|
+
end
|
163
|
+
|
164
|
+
# Same as unpublish, but immediatly saves the object.
|
165
|
+
# Raises an error when saving files.
|
166
|
+
def unpublish!
|
167
|
+
unpublish
|
168
|
+
save!
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
end
|