postablr 0.0.1
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/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
|