active_blog 0.0.2 → 0.5.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/README.markdown +11 -1
- data/app/assets/javascripts/active_blog/active_admin.js +23 -0
- data/app/assets/stylesheets/active_blog/active_admin.css.scss +21 -0
- data/app/assets/stylesheets/active_blog/application.css +2 -1
- data/app/assets/stylesheets/active_blog/blog_posts.css +8 -0
- data/app/controllers/active_blog/blog_posts_controller.rb +33 -2
- data/app/helpers/active_blog/application_helper.rb +27 -4
- data/app/helpers/active_blog/blog_posts_helper.rb +27 -1
- data/app/models/active_blog/blog_post.rb +30 -38
- data/app/views/active_blog/active_admin/_blog_post_form.html.erb +16 -0
- data/app/views/active_blog/active_admin/_blog_post_show.html.erb +18 -0
- data/app/views/active_blog/active_admin/_show.html.erb +2 -0
- data/app/views/active_blog/blog_posts/_blog_post.html.erb +32 -0
- data/app/views/active_blog/blog_posts/_blog_post_schema.html.erb +5 -0
- data/app/views/active_blog/blog_posts/_sidebar.html.erb +11 -0
- data/app/views/active_blog/blog_posts/archives.html.erb +12 -0
- data/app/views/active_blog/blog_posts/atom.xml.builder +21 -0
- data/app/views/active_blog/blog_posts/index.html.erb +18 -13
- data/app/views/active_blog/blog_posts/preview.js.erb +1 -0
- data/app/views/active_blog/blog_posts/show.html.erb +7 -10
- data/db/migrate/20111116040223_create_active_blog_blog_posts.rb +3 -2
- data/lib/active_blog/ext/string.rb +39 -0
- data/lib/active_blog/mapper.rb +13 -2
- data/lib/active_blog/version.rb +1 -1
- data/lib/active_blog.rb +25 -4
- data/lib/generators/active_blog/install/install_generator.rb +4 -0
- data/lib/generators/active_blog/install/templates/README +17 -0
- data/lib/generators/active_blog/install/templates/active_blog.rb +18 -3
- data/lib/generators/active_blog/install/templates/blog_posts.rb +3 -8
- data/test/dummy/config/application.rb +1 -0
- data/test/dummy/config/routes.rb +2 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +5 -1
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +74 -0
- data/test/dummy/log/test.log +1252 -0
- data/test/functional/active_blog/blog_posts_controller_test.rb +9 -9
- data/test/functional/active_blog/routing_test.rb +25 -0
- data/test/unit/active_blog/blog_post_test.rb +32 -3
- data/test/unit/active_blog/sample_renderer_test.rb +22 -0
- metadata +40 -14
data/README.markdown
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# ActiveBlog is a work in progress.
|
2
2
|
|
3
|
-
ActiveBlog is Rails engine written to satisfy blogging requirements.
|
3
|
+
ActiveBlog is Rails engine written to satisfy *minimal* blogging requirements.
|
4
4
|
|
5
5
|
The ActiveBlog BlogPost model:
|
6
6
|
|
@@ -38,6 +38,8 @@ Run the generator
|
|
38
38
|
|
39
39
|
./script/rails generate active_blog:install
|
40
40
|
|
41
|
+
[Follow the installer's directions](https://github.com/mchung/active_blog/blob/master/lib/generators/active_blog/install/templates/README)
|
42
|
+
|
41
43
|
Install the migrations
|
42
44
|
|
43
45
|
rake db:migrate
|
@@ -49,3 +51,11 @@ Start your server with `foreman` or `rails s` and visit your new blog located at
|
|
49
51
|
To create a new blog post, visit the admin area located at:
|
50
52
|
|
51
53
|
http://localhost:5000/admin/active_blog_blog_posts
|
54
|
+
|
55
|
+
|
56
|
+
# TODO
|
57
|
+
|
58
|
+
* The ActiveAdmin BlogPost form should show realtime Markdown updates
|
59
|
+
* The ActiveAdmin BlogPost form should allow users to upload content to S3
|
60
|
+
* Tests
|
61
|
+
* Document Parent App Hooks (content_for :sidebar, content_for :title, content_for: head)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
$(document).ready(function() {
|
2
|
+
var $form = $('form.active_blog_blog_post');
|
3
|
+
|
4
|
+
$("#button-preview").bind("ajax:before", function() {
|
5
|
+
var action = $form.attr('action');
|
6
|
+
$form.attr('action', '/blog/-/preview');
|
7
|
+
$form.submit();
|
8
|
+
$form.attr('action', action);
|
9
|
+
return false;
|
10
|
+
});
|
11
|
+
|
12
|
+
$form.bind('submit', function() {
|
13
|
+
if ($form.attr('action') === '/blog/-/preview') {
|
14
|
+
console.log("In post " + this.action);
|
15
|
+
$.post(this.action, $(this).serialize(), null, "script");
|
16
|
+
return false;
|
17
|
+
}
|
18
|
+
});
|
19
|
+
|
20
|
+
// $("#new_active_blog_blog_post").live('keyup', function() {
|
21
|
+
// $("#button-preview").trigger('click');
|
22
|
+
// });
|
23
|
+
});
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#main_content {
|
2
|
+
margin: 0 auto;
|
3
|
+
#main_form, .panel.show.blog {
|
4
|
+
float: left;
|
5
|
+
width: 49%;
|
6
|
+
}
|
7
|
+
#live_preview, .buffer {
|
8
|
+
float: right;
|
9
|
+
width: 49%;
|
10
|
+
background-color: #efefef;
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
.panel {
|
15
|
+
h4 {
|
16
|
+
span {
|
17
|
+
font-size: 90%;
|
18
|
+
font-weight: bold;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
@@ -3,5 +3,6 @@
|
|
3
3
|
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
|
4
4
|
* the top of the compiled file, but it's generally better to create a new file per style scope.
|
5
5
|
*= require_self
|
6
|
-
*=
|
6
|
+
*= require 'active_blog/active_admin'
|
7
|
+
*= require 'active_blog/blog_posts'
|
7
8
|
*/
|
@@ -1,11 +1,42 @@
|
|
1
1
|
module ActiveBlog
|
2
2
|
class BlogPostsController < ApplicationController
|
3
|
+
|
4
|
+
before_filter :only => [:index, :show, :archives] do
|
5
|
+
@recent_blog_posts = BlogPost.live.recent
|
6
|
+
end
|
7
|
+
|
3
8
|
def index
|
4
|
-
@blog_posts = BlogPost.live.
|
9
|
+
@blog_posts = BlogPost.live.page(params[:page])
|
10
|
+
end
|
11
|
+
|
12
|
+
def archives
|
13
|
+
@blog_posts = BlogPost.all
|
5
14
|
end
|
6
|
-
|
15
|
+
|
7
16
|
def show
|
8
17
|
@blog_post = BlogPost.live.where(:cached_slug => params[:cached_slug]).first
|
18
|
+
if @blog_post
|
19
|
+
render
|
20
|
+
else
|
21
|
+
# TODO(mc): Should 404
|
22
|
+
redirect_to active_blog_path, :notice => "No blog post with that URL"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def preview
|
27
|
+
@blog_post = BlogPost.new(params[:active_blog_blog_post])
|
28
|
+
@blog_post_partial = render_to_string(:partial => 'active_blog/active_admin/blog_post_show')
|
29
|
+
|
30
|
+
respond_to do |format|
|
31
|
+
format.js
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def atom
|
36
|
+
@blog_posts = BlogPost.live.order('published_at DESC').limit(10)
|
37
|
+
respond_to do |format|
|
38
|
+
format.xml
|
39
|
+
end
|
9
40
|
end
|
10
41
|
end
|
11
42
|
end
|
@@ -1,16 +1,39 @@
|
|
1
1
|
module ActiveBlog
|
2
|
+
# These helpers are intended to be used by developers.
|
3
|
+
#
|
4
|
+
#
|
2
5
|
module ApplicationHelper
|
3
|
-
def
|
4
|
-
ActiveBlog.
|
6
|
+
def active_blog_title
|
7
|
+
ActiveBlog.title
|
5
8
|
end
|
6
9
|
|
7
|
-
def
|
8
|
-
|
10
|
+
def active_blog_description
|
11
|
+
ActiveBlog.description
|
12
|
+
end
|
13
|
+
|
14
|
+
def active_blog_sidebar(&block)
|
15
|
+
sidebar_content_for = ActiveBlog.content_for_sidebar
|
9
16
|
if sidebar_content_for
|
10
17
|
content_for sidebar_content_for do
|
11
18
|
yield
|
12
19
|
end
|
13
20
|
end
|
14
21
|
end
|
22
|
+
|
23
|
+
def active_blog_author_name
|
24
|
+
ActiveBlog.author_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def active_blog_author_uri
|
28
|
+
ActiveBlog.author_uri
|
29
|
+
end
|
30
|
+
|
31
|
+
def active_blog_author_email
|
32
|
+
ActiveBlog.author_email
|
33
|
+
end
|
34
|
+
|
35
|
+
def active_blog_atom_link_tag
|
36
|
+
auto_discovery_link_tag(:atom, "#{active_blog_feed_url}", {:title => "Subscribe to this blog"})
|
37
|
+
end
|
15
38
|
end
|
16
39
|
end
|
@@ -1,7 +1,33 @@
|
|
1
1
|
module ActiveBlog
|
2
2
|
module BlogPostsHelper
|
3
3
|
def markdown(text)
|
4
|
-
|
4
|
+
regular = { :hard_wrap => true, :autolink => true, :space_after_headers => true }
|
5
|
+
make_markdown(regular).render(text).html_safe
|
6
|
+
end
|
7
|
+
|
8
|
+
def markdown_for_schema(text)
|
9
|
+
truncate(strip_tags(markdown(text)).strip.gsub(/\n/, ' '), :length => 250)
|
10
|
+
end
|
11
|
+
|
12
|
+
def make_markdown(opts)
|
13
|
+
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, opts)
|
14
|
+
markdown
|
15
|
+
end
|
16
|
+
|
17
|
+
def schema_date(date)
|
18
|
+
date.strftime("%Y-%m-%d")
|
19
|
+
end
|
20
|
+
|
21
|
+
def schema_span_for(name, content)
|
22
|
+
content_tag(:span, "", :itemprop => name, :content => content)
|
23
|
+
end
|
24
|
+
|
25
|
+
def blog_post_path(blog_post)
|
26
|
+
if blog_post.new_record?
|
27
|
+
admin_blog_posts_path(blog_post)
|
28
|
+
else
|
29
|
+
admin_blog_post_path(blog_post)
|
30
|
+
end
|
5
31
|
end
|
6
32
|
end
|
7
33
|
end
|
@@ -1,51 +1,43 @@
|
|
1
1
|
module ActiveBlog
|
2
2
|
class BlogPost < ActiveRecord::Base
|
3
3
|
set_table_name 'active_blog_blog_posts'
|
4
|
-
|
5
|
-
|
4
|
+
paginates_per ActiveBlog.paginates_per
|
5
|
+
default_scope :order => 'published_at DESC'
|
6
|
+
|
7
|
+
scope :live, where('published_at < ? AND draft = ?', Time.zone.now, false)
|
8
|
+
scope :recent, limit(5)
|
9
|
+
|
10
|
+
validates_presence_of :title, :allow_blank => false, :allow_nil => false, :message => "can't be blank"
|
11
|
+
validates_presence_of :body, :allow_blank => false, :allow_nil => false, :message => "can't be blank"
|
12
|
+
validates_presence_of :cached_slug, :allow_blank => false, :allow_nil => false, :message => "can't be blank"
|
13
|
+
validates_uniqueness_of :cached_slug, :message => "must be unique"
|
14
|
+
validate :title_must_not_start_with_dash
|
15
|
+
validate :title_must_not_be
|
6
16
|
before_validation :build_cached_slug
|
17
|
+
after_initialize :init
|
18
|
+
|
19
|
+
# protected methods
|
7
20
|
|
8
|
-
scope :live, where("published_at < ? AND draft = ?", Time.now, false)
|
9
21
|
def build_cached_slug
|
10
|
-
|
22
|
+
# Don't build slug if it already exists.
|
23
|
+
if self.cached_slug.nil?
|
24
|
+
self.cached_slug = title.to_slug
|
25
|
+
end
|
11
26
|
end
|
12
27
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
# ==== Example
|
19
|
-
#
|
20
|
-
# "The World is Beautiful!".to_slug # => "the-world-is-beautiful"
|
21
|
-
#
|
22
|
-
# ==== Returns
|
23
|
-
# String:: A 'sluggified' version of this string
|
24
|
-
#
|
25
|
-
# --
|
26
|
-
# @api public
|
27
|
-
def to_slug(string)
|
28
|
-
# Perform transliteration to replace non-ascii characters with an ascii
|
29
|
-
# character
|
30
|
-
value = string.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n, '').to_s
|
31
|
-
|
32
|
-
# Remove single quotes from input
|
33
|
-
value.gsub!(/[']+/, '')
|
34
|
-
|
35
|
-
# Replace any non-word character (\W) with a space
|
36
|
-
value.gsub!(/\W+/, ' ')
|
37
|
-
|
38
|
-
# Remove any whitespace before and after the string
|
39
|
-
value.strip!
|
40
|
-
|
41
|
-
# All characters should be downcased
|
42
|
-
value.downcase!
|
28
|
+
def title_must_not_start_with_dash
|
29
|
+
if title.starts_with?('-')
|
30
|
+
errors.add(:title, 'cannot start with a dash')
|
31
|
+
end
|
32
|
+
end
|
43
33
|
|
44
|
-
|
45
|
-
|
34
|
+
def title_must_not_be
|
35
|
+
errors.add(:title, "cannot be named 'archives'") if title == 'archives'
|
36
|
+
end
|
46
37
|
|
47
|
-
|
48
|
-
|
38
|
+
def init
|
39
|
+
# Set now as the default published_at date. Only set if currently nil
|
40
|
+
self.published_at ||= Time.zone.now
|
49
41
|
end
|
50
42
|
end
|
51
43
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<div id="main_form">
|
2
|
+
<%= semantic_form_for(@blog_post, :url => blog_post_path(@blog_post)) do |f| %>
|
3
|
+
<%= f.inputs "Write a new blog post" do %>
|
4
|
+
<%= f.input :title, :as => :string, :required => true, :hint => "A great blog post title", :input_html => { :placeholder => "A great blog post title" } %>
|
5
|
+
<%= f.input :cached_slug, :as => :string, :label => "Slug", :hint => "#{active_blog_url}/...", :input_html => { :disabled => true } %>
|
6
|
+
<%= f.input :body, :as => :text, :label => "Blog post (Markdown)", :hint => "Use Markdown"%>
|
7
|
+
<%= f.input :draft, :as => :boolean, :label => "Draft?", :hint => "Drafts are not published" %>
|
8
|
+
<%= f.input :published_at, :label => "Publication date" %>
|
9
|
+
<% end %>
|
10
|
+
<%= f.buttons do %>
|
11
|
+
<%= f.commit_button %>
|
12
|
+
<li class="cancel"><%= link_to("Preview", active_blog_preview_path, { :id => "button-preview", :remote => true, "data-type" => "script"}) %>
|
13
|
+
<% end %>
|
14
|
+
<% end %>
|
15
|
+
</div>
|
16
|
+
<div id="live_preview"></div>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<div class="panel <%= @blog_post.new_record? ? "new" : "show" %> blog">
|
2
|
+
<h3><%= @blog_post.new_record? ? "Live Preview" : "Blog Entry" %></h3>
|
3
|
+
<div>
|
4
|
+
<h4><%= @blog_post.title || "[Title]" %>
|
5
|
+
<span>
|
6
|
+
<% if @blog_post.cached_slug %>
|
7
|
+
(<%= active_blog_post_url(:cached_slug => @blog_post.cached_slug) %>)
|
8
|
+
<% end %>
|
9
|
+
</span>
|
10
|
+
</h4>
|
11
|
+
</div>
|
12
|
+
<div>
|
13
|
+
|
14
|
+
</div>
|
15
|
+
<div>
|
16
|
+
<%= markdown(@blog_post.body || "Body") %>
|
17
|
+
</div>
|
18
|
+
</div>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<%#
|
2
|
+
This partial is used by #index and #show. It behaves differently by displaying different schema
|
3
|
+
types according to the caller.
|
4
|
+
|
5
|
+
Google Rich Snippets doesn't like nested schemas in certain cases.
|
6
|
+
%>
|
7
|
+
<div class="active_blog entry" <%= show ? '' : "itemscope itemtype='http://schema.org/BlogPosting'" %>>
|
8
|
+
<%- if show %>
|
9
|
+
<%= content_for :schema do %>
|
10
|
+
<%= render :partial => 'blog_post_schema', :locals => {:blog_post => blog_post} %>
|
11
|
+
<% end %>
|
12
|
+
<% else %>
|
13
|
+
<%= render :partial => 'blog_post_schema', :locals => {:blog_post => blog_post} %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<h6>
|
17
|
+
<%= blog_post.published_at.strftime("%B %e %G") %>
|
18
|
+
<% if blog_post.new_record? %>
|
19
|
+
<a href="" itemscope itemprop="url">∞</a>
|
20
|
+
<% else %>
|
21
|
+
<a href="<%= active_blog_post_path(blog_post.cached_slug) %>">∞</a>
|
22
|
+
<% end %>
|
23
|
+
</h6>
|
24
|
+
<h2>
|
25
|
+
<%= blog_post.title %>
|
26
|
+
</h2>
|
27
|
+
|
28
|
+
<div class="active_blog body">
|
29
|
+
<%= markdown(blog_post.body || "") %>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
<hr/>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<%= schema_span_for 'name', "#{blog_post.title} | #{active_blog_title}" %>
|
2
|
+
<%= schema_span_for 'description', markdown_for_schema(blog_post.body) %>
|
3
|
+
<%= schema_span_for 'datePublished', schema_date(blog_post.published_at) %>
|
4
|
+
<%= schema_span_for 'headline', blog_post.title %>
|
5
|
+
<%= schema_span_for 'url', active_blog_post_url(blog_post.cached_slug) %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%= active_blog_sidebar do %>
|
2
|
+
<div class='section active_blog sidebar'>
|
3
|
+
<h6>Recent posts</h6>
|
4
|
+
</div>
|
5
|
+
<ul class='unstyled recent'>
|
6
|
+
<% @recent_blog_posts.each do |recent_blog_post| %>
|
7
|
+
<li><a href='<%= active_blog_post_path(recent_blog_post.cached_slug) %>' title='<%= recent_blog_post.title %>'><%= recent_blog_post.title %></a></li>
|
8
|
+
<% end %>
|
9
|
+
</ul>
|
10
|
+
<%= link_to 'Archives', active_blog_archives_path %>
|
11
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%= content_for :title do %><%= "#{active_blog_title} » Archives" %><% end %>
|
2
|
+
<div class="section active_blog archives">
|
3
|
+
<h1>Archives</h1>
|
4
|
+
<p>By Date</p>
|
5
|
+
<ul>
|
6
|
+
<% @blog_posts.each do |blog_post| %>
|
7
|
+
<li><%= link_to blog_post.title, active_blog_post_path(blog_post.cached_slug) %>
|
8
|
+
<% end %>
|
9
|
+
</ul>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<%= render :partial => 'sidebar' %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
atom_feed({}) do |feed|
|
2
|
+
feed.title(active_blog_title)
|
3
|
+
feed.updated(@blog_posts[0].published_at) if @blog_posts.length > 0
|
4
|
+
|
5
|
+
@blog_posts.each do |post|
|
6
|
+
feed.entry(post, {
|
7
|
+
:published_at => post.published_at,
|
8
|
+
:updated_at => post.updated_at,
|
9
|
+
:url => active_blog_post_url(post.cached_slug)
|
10
|
+
}) do |entry|
|
11
|
+
entry.title(post.title)
|
12
|
+
entry.content(markdown(post.body), :type => 'html')
|
13
|
+
|
14
|
+
entry.author do |author|
|
15
|
+
author.name(active_blog_author_name) if active_blog_author_name
|
16
|
+
author.uri(active_blog_author_uri) if active_blog_author_uri
|
17
|
+
author.email(active_blog_author_email) if active_blog_author_email
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,17 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
<%=
|
1
|
+
<%= content_for :title do %><%= active_blog_title %><% end %>
|
2
|
+
<%= content_for :head do %><%= active_blog_atom_link_tag %><% end %>
|
3
|
+
<%= content_for :schema do %>
|
4
|
+
<%= schema_span_for 'name', active_blog_title %>
|
5
|
+
<%= schema_span_for 'description', active_blog_description %>
|
6
|
+
<%= schema_span_for 'url', active_blog_url %>
|
5
7
|
<% end %>
|
8
|
+
<div class="section active_blog index">
|
9
|
+
<h1><%= active_blog_title %></h1>
|
6
10
|
|
7
|
-
<% @blog_posts.
|
8
|
-
|
9
|
-
|
10
|
-
<%= markdown(blog.body) %>
|
11
|
-
<hr/>
|
12
|
-
<% end %>
|
11
|
+
<% if @blog_posts.empty? %>
|
12
|
+
<%= link_to "Write your first blog post", new_admin_blog_post_path %>
|
13
|
+
<% end %>
|
13
14
|
|
15
|
+
<div itemprop="blogPosts">
|
16
|
+
<%= render :partial => "blog_post", :collection => @blog_posts, :locals => {:show => false} %>
|
17
|
+
</div>
|
14
18
|
|
15
|
-
<%=
|
16
|
-
|
17
|
-
|
19
|
+
<%= paginate @blog_posts %>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<%= render :partial => "sidebar" %>
|
@@ -0,0 +1 @@
|
|
1
|
+
$('#live_preview').html('<%= escape_javascript(@blog_post_partial.html_safe) %>');
|
@@ -1,10 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
<
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
<%= blog_sidebar do %>
|
9
|
-
<br/>
|
10
|
-
<% end %>
|
1
|
+
<%= content_for :title do %><%= @blog_post.title %><% end %>
|
2
|
+
<%= content_for :schema_itemtype do %>http://schema.org/BlogPosting<% end %>
|
3
|
+
<div class="section active_blog show">
|
4
|
+
<h1><%= active_blog_title %></h1>
|
5
|
+
<%= render :partial => "blog_post", :locals => {:blog_post => @blog_post, :show => true} %>
|
6
|
+
</div>
|
7
|
+
<%= render :partial => "sidebar" %>
|
@@ -2,7 +2,7 @@ class CreateActiveBlogBlogPosts < ActiveRecord::Migration
|
|
2
2
|
def change
|
3
3
|
create_table :active_blog_blog_posts do |t|
|
4
4
|
t.string :title
|
5
|
-
t.
|
5
|
+
t.text :body
|
6
6
|
t.boolean :draft
|
7
7
|
t.datetime :published_at
|
8
8
|
t.string :cached_slug
|
@@ -12,5 +12,6 @@ class CreateActiveBlogBlogPosts < ActiveRecord::Migration
|
|
12
12
|
t.timestamps
|
13
13
|
end
|
14
14
|
add_index :active_blog_blog_posts, :id
|
15
|
+
add_index :active_blog_blog_posts, :cached_slug, :unique => true
|
15
16
|
end
|
16
|
-
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class String
|
2
|
+
# Generate a slug for the string +value+.
|
3
|
+
#
|
4
|
+
# A slug should consist of numbers (0-9), lowercase letters (a-z) and
|
5
|
+
# dashes (-). Any other characters should be filtered.
|
6
|
+
#
|
7
|
+
# ==== Example
|
8
|
+
#
|
9
|
+
# "The World is Beautiful!".to_slug # => "the-world-is-beautiful"
|
10
|
+
#
|
11
|
+
# ==== Returns
|
12
|
+
# String:: A 'sluggified' version of this string
|
13
|
+
#
|
14
|
+
# --
|
15
|
+
# @api public
|
16
|
+
def to_slug
|
17
|
+
# Perform transliteration to replace non-ascii characters with an ascii
|
18
|
+
# character
|
19
|
+
value = self.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n, '').to_s
|
20
|
+
|
21
|
+
# Remove single quotes from input
|
22
|
+
value.gsub!(/[']+/, '')
|
23
|
+
|
24
|
+
# Replace any non-word character (\W) with a space
|
25
|
+
value.gsub!(/\W+/, ' ')
|
26
|
+
|
27
|
+
# Remove any whitespace before and after the string
|
28
|
+
value.strip!
|
29
|
+
|
30
|
+
# All characters should be downcased
|
31
|
+
value.downcase!
|
32
|
+
|
33
|
+
# Replace spaces with dashes
|
34
|
+
value.gsub!(' ', '-')
|
35
|
+
|
36
|
+
# Return the resulting slug
|
37
|
+
value
|
38
|
+
end
|
39
|
+
end
|
data/lib/active_blog/mapper.rb
CHANGED
@@ -5,8 +5,19 @@ module ActionDispatch::Routing
|
|
5
5
|
#
|
6
6
|
#
|
7
7
|
scope mount_location do
|
8
|
-
|
9
|
-
|
8
|
+
resources :blog_posts, :module => 'active_blog', :path => '/', :only => [] do
|
9
|
+
get 'page/:page', :action => :index, :on => :collection
|
10
|
+
# match '/', :action => :index, :on => :collection, :as => :all
|
11
|
+
# match '/-/preview', :action => :preview, :on => :collection, :as => :preview, :via => [:post, :put]
|
12
|
+
# match '/-/feed', :action => :feed, :on => :collection, :as => :feed, :via => [:get]
|
13
|
+
# match '/:cached_slug', :action => :show, :on => :collection, :as => :post, :via => [:get]
|
14
|
+
end
|
15
|
+
match '/' => 'active_blog/blog_posts#index', :as => :active_blog, :via => [:get]
|
16
|
+
match '/-/preview' => 'active_blog/blog_posts#preview', :as => :active_blog_preview, :via => [:post, :put]
|
17
|
+
match '/atom.xml' => 'active_blog/blog_posts#atom', :as => :active_blog_feed, :via => [:get], :format => :xml
|
18
|
+
match '/archives' => 'active_blog/blog_posts#archives', :as => :active_blog_archives, :via => [:get]
|
19
|
+
# Always last.
|
20
|
+
match '/:cached_slug' => 'active_blog/blog_posts#show', :as => :active_blog_post, :via => [:get]
|
10
21
|
end
|
11
22
|
end
|
12
23
|
end
|
data/lib/active_blog/version.rb
CHANGED
data/lib/active_blog.rb
CHANGED
@@ -1,16 +1,37 @@
|
|
1
1
|
require 'active_blog/engine'
|
2
2
|
require 'active_blog/mapper'
|
3
3
|
require 'redcarpet'
|
4
|
+
require 'active_blog/ext/string'
|
4
5
|
|
5
6
|
module ActiveBlog
|
6
7
|
|
7
8
|
# The blog's title
|
8
|
-
mattr_accessor :
|
9
|
-
@@
|
9
|
+
mattr_accessor :title
|
10
|
+
@@title = 'New ActiveBlog!'
|
11
|
+
|
12
|
+
# The blog's description
|
13
|
+
mattr_accessor :description
|
14
|
+
@@description = "Here's where your description goes"
|
10
15
|
|
11
16
|
# Yield to your layout's sidebar, i.e. :sidebar
|
12
|
-
mattr_accessor :
|
13
|
-
@@
|
17
|
+
mattr_accessor :content_for_sidebar
|
18
|
+
@@content_for_sidebar = nil
|
19
|
+
|
20
|
+
# Blog author's name
|
21
|
+
mattr_accessor :author_name
|
22
|
+
@@author_name = nil
|
23
|
+
|
24
|
+
# Blog author's uri
|
25
|
+
mattr_accessor :author_uri
|
26
|
+
@@author_uri = nil
|
27
|
+
|
28
|
+
# Blog author's email
|
29
|
+
mattr_accessor :author_email
|
30
|
+
@@author_email = nil
|
31
|
+
|
32
|
+
# Blog posts per page
|
33
|
+
mattr_accessor :paginates_per
|
34
|
+
@@paginates_per = 10
|
14
35
|
|
15
36
|
def self.setup
|
16
37
|
yield self
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
TO COMPLETE YOUR INSTALLATION
|
3
|
+
|
4
|
+
1. Add the following line to application.css
|
5
|
+
|
6
|
+
*= require 'active_blog/application'
|
7
|
+
|
8
|
+
2. Add the following to active_admin.css
|
9
|
+
|
10
|
+
// ActiveBlog CSS Styles
|
11
|
+
@import "active_blog/active_admin";
|
12
|
+
|
13
|
+
3. Add the following to active_admin.js
|
14
|
+
|
15
|
+
//= require active_blog/active_admin
|
16
|
+
|
17
|
+
Thanks for installing ActiveBlog!
|