This commit is contained in:
HuangQi 2016-01-05 18:28:51 +08:00
parent 42e6f42a7a
commit 08b7b72909
26 changed files with 445 additions and 14 deletions

10
Gemfile
View File

@ -1,4 +1,4 @@
source 'https://rubygems.org'
source 'https://ruby.taobao.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
@ -26,7 +26,7 @@ gem 'settingslogic'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Use jquery as the JavaScript library
gem 'jquery-rails'
#gem 'jquery-rails'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
@ -38,9 +38,9 @@ gem 'bootstrap-sass'
gem 'font-awesome-sass-rails', '~> 3.0.2.2'
gem 'twitter-bootstrap-rails-confirm', github: 'fxhover/twitter-bootstrap-rails-confirm', branch: 'bootstrap3'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
#gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
#gem 'jbuilder', '~> 2.0'
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
@ -68,6 +68,6 @@ group :development, :test do
gem 'web-console', '~> 2.0'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
#gem 'spring'
end

View File

@ -12,7 +12,7 @@ GIT
markdown-toolbar (1.0.1)
GEM
remote: https://rubygems.org/
remote: https://ruby.taobao.org/
specs:
actionmailer (4.2.3)
actionpack (= 4.2.3)
@ -227,4 +227,4 @@ DEPENDENCIES
web-console (~> 2.0)
BUNDLED WITH
1.10.6
1.11.2

73
Gemfile~ Normal file
View File

@ -0,0 +1,73 @@
source 'https://ruby.taobao.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.3'
# Use mysql as the database for Active Record
gem 'mysql2'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.1.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
gem 'therubyracer', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails'
#Use kaminari page
gem 'kaminari'
#Use settingslogic
gem 'settingslogic'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Use jquery as the JavaScript library
#gem 'jquery-rails'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
# Use haml template
gem 'haml-rails'
# Use bootstrap css
gem 'bootstrap-sass'
gem 'font-awesome-sass-rails', '~> 3.0.2.2'
gem 'twitter-bootstrap-rails-confirm', github: 'fxhover/twitter-bootstrap-rails-confirm', branch: 'bootstrap3'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
#gem 'jbuilder', '~> 2.0'
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring', group: :development
# Use Unicorn as the app server
# gem 'unicorn'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
group :development do
gem 'thin'
end
#Avatar
gem 'gravatar_image_tag'
#markdown
gem 'markdown-toolbar', git: 'https://github.com/fuksito/markdown-toolbar.git'
gem 'redcarpet'
gem 'simple_fileupload'
gem 'remotipart'
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
# Access an IRB console on exception pages or by using <%= console %> in views
gem 'web-console', '~> 2.0'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
#gem 'spring'
end

View File

@ -1,19 +1,58 @@
class ArticlesController < ApplicationController
def index
res = Article
order = 'updated_at desc'
if params[:sort].present?
order = case params[:sort]
when 'star'
'star_count desc'
when 'comments'
'comments_count desc'
else
'updated_at desc'
end
end
if params[:c].present?
category = Category.find params[:c]
res = res.where("category_id=#{category.id}") if category
end
res = res.where("title like ?", "%#{params[:keyword]}%") if params[:keyword].present?
@articles = res.order(order).page(params[:page]).per(Settings.blog.aritcle_page_size)
respond_to do |format|
format.html
format.js
end
end
def new
@article = Article.new
end
def create
@article = Article.new params.require(:article).permit(:title, :tags, :source, :content)
@article.user_id = @current_user.id
if params[:article].present? && params[:article][:category_id].present?
@article.category_id = params[:article][:category_id]
elsif params[:article].present? && params[:article][:category_name].present?
category = Category.find_or_create params[:article][:category_name]
@article.category_id = category.id
end
if @article.save
redirect_to article_path(@article)
else
render 'new'
end
end
def show
@article.add_view request.remote_ip, @current_user, params.inspect
@comment = @article.comments.new
@comments = @article.comments.order('updated_at asc').page(params[:page]).per(Settings.blog.comments_page_size)
respond_to do |format|
format.html
format.js
end
end
def edit
@ -21,11 +60,27 @@ class ArticlesController < ApplicationController
end
def update
attributes = params.require(:article).permit(:title, :tags, :source, :content)
if params[:article].present? && params[:article][:category_id].present?
attributes[:category_id] = params[:article][:category_id]
elsif params[:article].present? && params[:article][:category_name].present?
category = Category.find_or_create params[:article][:category_name]
attributes[:category_id] = category.id
end
if @article.update_attributes attributes
redirect_to article_path(@article)
else
render 'edit'
end
end
def destroy
if @article.destroy
redirect_to articles_path
else
flash[:error] = '删除失败'
redirect_to article_path(@article)
end
end
def star
@ -41,4 +96,4 @@ class ArticlesController < ApplicationController
def article
end
end
end

View File

@ -0,0 +1,83 @@
class ArticlesController < ApplicationController
def index
res = Article
order = 'updated_at desc'
if params[:sort].present?
order = case params[:sort]
when 'star'
'star_count desc'
when 'comments'
'comments_count desc'
else
'updated_at desc'
end
end
if params[:c].present?
category = Category.find params[:c]
res = res.where("category_id=#{category.id}") if category
end
res = res.where("title like ?", "%#{params[:keyword]}%") if params[:keyword].present?
@articles = res.order(order).page(params[:page]).per(Settings.blog.aritcle_page_size)
respond_to do |format|
format.html
format.js
end
end
def new
@article = Article.new
end
def create
@article = Article.new params.require(:article).permit(:title, :tags, :source, :content)
@article.user_id = @current_user.id
if params[:article].present? && params[:article][:category_id].present?
@article.category_id = params[:article][:category_id]
elsif params[:article].present? && params[:article][:category_name].present?
category = Category.find_or_create params[:article][:category_name]
@article.category_id = category.id
end
if @article.save
redirect_to article_path(@article)
else
render 'new'
end
end
def show
@article.add_view request.remote_ip, @current_user, params.inspect
@comment = @article.comments.new
@comments = @article.comments.order('updated_at asc').page(params[:page]).per(Settings.blog.comments_page_size)
respond_to do |format|
format.html
format.js
end
end
def edit
end
def update
end
def destroy
end
def star
end
protected
def check_current_user_is_admin
end
def article
end
end

View File

@ -12,5 +12,20 @@ class Article < ActiveRecord::Base
validates :content, length: {minimum: 10}
validate :validate_category
def validate_category
errors.add(:category_id, '分类不正确') unless Category.find(self.category_id)
rescue
errors.add(:category_id, '分类不正确')
return false
else
return true
end
def add_view(ip, current_user, param_string)
return false if (self.article_views.where("created_at >= '#{DateTime.now - 10.minute}' and ip='#{ip}'").count > 0)
view = self.article_views.new ip: ip, param_string: param_string
view.user_id = current_user.id if current_user
view.save
end
end

16
app/models/article.rb~ Normal file
View File

@ -0,0 +1,16 @@
class Article < ActiveRecord::Base
attr_accessor :category_name
belongs_to :category, counter_cache: 'articles_count'
belongs_to :user
has_many :article_stars
has_many :article_views
has_many :comments, class_name: 'ArticleComment'
validates :title, length: {minimum: 10, maximum: 50}
validates :tags, presence: true
validates :source, allow_blank: true, format: {with: /[a-zA-Z0-9-]+\.[a-zA-Z0-9]+/}
validates :content, length: {minimum: 10}
validate :validate_category
end

View File

@ -0,0 +1,11 @@
- errors = @article.errors.full_messages
- if errors.any?
.alert.alert-danger
%a.close{"data-dismiss"=>"alert"} &times;
%span
= errors.first
- elsif flash[:error].present?
.alert.alert-danger
%a.close{"data-dismiss"=>"alert"} &times;
%span
= flash[:error]

View File

View File

@ -0,0 +1,39 @@
= render partial: 'toolbar_upload_img', locals: {text_id: 'article_content'}
= form_for @article, role: 'form' do |f|
.form-group
%label{for: 'article_title'} 文章标题
= f.text_field :title, placeholder: '文章标题', class: 'form-control'
.form-group
%label{for: 'article_category_id'} 文章分类
= select_tag "article[category_id]", options_for_select(get_categories_options, @article.category_id), include_blank: true, class: 'form-control'
或者新建一个分类:
= f.text_field :category_name, placeholder: '分类名称', class: 'form-control'
.form-group
%label{for: 'article_tags'} 标签
= f.text_field :tags, placeholder: '文章标签,多个用英文“,”隔开', class: 'form-control'
.form-group
%label{for: 'article_source'} 文章来源
= f.text_field :source, placeholder: '文章来源,为空则为原创', class: 'form-control'
.form-group
%ul.nav.nav-tabs#preview_tab{role: "tablist"}
%li.active
= link_to '文章内容', '#edit', role: 'tab', 'data-toggle'=>'tab'
%li
= link_to '预览', '#preview', role: 'tab', 'data-toggle'=>'tab'
.tab-content
.tab-pane.active#edit
= f.text_area :content, placeholder: '文章内容', class: 'form-control'
.tab-pane#preview
.form-group
= f.submit '提交', class: 'btn btn-success btn-lg btn-block'
:javascript
$(function(){
$('#preview_tab a[href="#preview"]').click(function(e){
e.preventDefault();
$(this).tab('show');
preview('article_content', 'preview');
});
});

View File

View File

@ -0,0 +1,3 @@
%h3 编辑博文
= render partial: 'error'
= render partial: 'form'

View File

View File

@ -0,0 +1,26 @@
.row.inner.edge
.col-md-9.layout-main
.tab-nav
-# %h2.common-title 博文列表
%nav.sub-tab.row
%span.col-md-6.text-left
%h3 文章列表
%span.col-md-6.text-right.sort_navbar
- params_hash = params.dup
- params_hash.delete :page
%span.icon.icon-circle-arrow-down(data-toggle="tooltip" data-placement="bottom" title="排序")
= link_to '按时间', articles_path(params_hash.merge({sort: 'time'})), remote: true, class: "#{'current' if params[:sort].nil? || params[:sort] == 'time'}"
= link_to '按称赞', articles_path(params_hash.merge({sort: 'star'})), remote: true, class: "#{'current' if params[:sort].present? && params[:sort] == 'star'}"
= link_to '按评论', articles_path(params_hash.merge({sort: 'comments'})), remote: true, class: "#{'current' if params[:sort].present? && params[:sort] == 'comments'}"
.article-list#article-list
= render partial: 'articles'
.sidebar.col-md-3.layout-secondary.hidden-xs.hidden-sm
= render partial: 'article_sidebar'
:javascript
$(function(){
$('.sort_navbar a').click(function(){
$(this).addClass('current').siblings().removeClass('current');
});
});

View File

View File

@ -0,0 +1,2 @@
:plain
$('#article-list').html("#{escape_javascript(render partial: 'articles')}");

View File

View File

@ -0,0 +1,4 @@
%h3 撰写博文
= render partial: 'error'
= render partial: 'form'

View File

View File

@ -0,0 +1,57 @@
.article_show
= render partial: 'error'
%h3.article-title
- if @article.source.empty?
[原创]
= @article.title
- if current_user_is_admin?
= link_to edit_article_path(@article) do
%span.icon.icon-edit
= link_to article_path(@article), method: 'delete', "data-confirm"=> "确定删除吗?" do
%span.icon.icon-trash
%p
- get_tags(@article).each do |tag|
%span.label.label-default
= tag
%p
%span.icon
分类:
= link_to @article.category.name, articles_path(c: @article.category_id)
%span.icon.icon-time(data-toggle="tooltip" data-placement="bottom" title="发表时间")
= @article.updated_at.strftime('%Y-%m-%d %H:%M')
%span.icon.icon-eye-open(data-toggle="tooltip" data-placement="bottom" title="浏览")
= @article.view_count || 1
- if current_user_can_star?(@article)
= link_to star_article_path(@article), method: :post, remote: 'true' do
%span.icon.icon-thumbs-up#article_star(data-toggle="tooltip" data-placement="bottom" title="称赞")
= @article.star_count || 0
- else
%span.icon.icon-thumbs-up(data-toggle="tooltip" data-placement="bottom" title="称赞数")
= @article.star_count || 0
%span.icon.icon-comments(data-toggle="tooltip" data-placement="bottom" title="评论")
= @article.comments_count || 0
- unless @article.source.empty?
%p
转载:
= @article.source
.panel.panel-dfault
.panel-body
%p
= raw markdown_parser(@article.content)
%h3 评论:
#comments_content
= render partial: 'comments'
- if is_logined?
#comment_form
= render partial: 'comment_form'
- else
.jumbotron
%h2
= link_to '登录', login_path
后可评论

View File

View File

@ -0,0 +1,2 @@
:plain
$('#comments_content').html("#{escape_javascript(render partial: 'comments')}");

View File

View File

@ -0,0 +1 @@
6a220677438f874ca75763b1525ada21139d0f3a30f25b929d33222bef3bd8a0368bc03e87d1b495e2aedd297398bf470c693318bed3c72a27be5b31725aab0b

22
config/secrets.yml.example Executable file
View File

@ -0,0 +1,22 @@
# Be sure to restart your server when you modify this file.
# Your secret key is used for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rake secret` to generate a secure secret key.
# Make sure the secrets in this file are kept private
# if you're sharing your code publicly.
development:
secret_key_base: eef518ad815fbd36abb4a59e5ef6316f4ba52c1108b7bd78682354174108979016f101eecfcd2d6b6543a7b5795e73b17c4fc27d69146dd864445b6e6a0bfd08
test:
secret_key_base: 38e245a613b00c6701f3525867eb0c2e0b9d8f1395d54a2d7a3c1e3f35480fa331272f5cf1a74a130a60ed922131a00851c09a5819330652cd73e85378d0ca0a
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

22
config/secrets.yml.example~ Executable file
View File

@ -0,0 +1,22 @@
# Be sure to restart your server when you modify this file.
# Your secret key is used for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rake secret` to generate a secure secret key.
# Make sure the secrets in this file are kept private
# if you're sharing your code publicly.
development:
secret_key_base: 6938efe794286cdef1a2929153f78aa17f3005ab4e671e0ba21bf09057b448152f1725ca939d77d392bec467487e40e4d7e9e9ed9ba785e746e80c5dea106e0e
test:
secret_key_base: 38e245a613b00c6701f3525867eb0c2e0b9d8f1395d54a2d7a3c1e3f35480fa331272f5cf1a74a130a60ed922131a00851c09a5819330652cd73e85378d0ca0a
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>