rails
This commit is contained in:
parent
42e6f42a7a
commit
08b7b72909
10
Gemfile
10
Gemfile
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
- errors = @article.errors.full_messages
|
||||
- if errors.any?
|
||||
.alert.alert-danger
|
||||
%a.close{"data-dismiss"=>"alert"} ×
|
||||
%span
|
||||
= errors.first
|
||||
- elsif flash[:error].present?
|
||||
.alert.alert-danger
|
||||
%a.close{"data-dismiss"=>"alert"} ×
|
||||
%span
|
||||
= flash[:error]
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
%h3 编辑博文
|
||||
= render partial: 'error'
|
||||
= render partial: 'form'
|
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,2 @@
|
|||
:plain
|
||||
$('#article-list').html("#{escape_javascript(render partial: 'articles')}");
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
%h3 撰写博文
|
||||
= render partial: 'error'
|
||||
= render partial: 'form'
|
|
@ -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
|
||||
后可评论
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
:plain
|
||||
$('#comments_content').html("#{escape_javascript(render partial: 'comments')}");
|
|
@ -0,0 +1 @@
|
|||
6a220677438f874ca75763b1525ada21139d0f3a30f25b929d33222bef3bd8a0368bc03e87d1b495e2aedd297398bf470c693318bed3c72a27be5b31725aab0b
|
|
@ -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"] %>
|
|
@ -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"] %>
|
Loading…
Reference in New Issue