Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ rvm:

services:
- postgresql
- elasticsearch

addons:
postgresql: "9.5"
Expand Down
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ gem 'byebug', platform: :mri
# for corss-site communication
gem 'rest-client'

# Elasticsearch
gem 'elasticsearch-model'
gem 'elasticsearch-rails'

group :development, :test do
gem 'ffaker'
gem 'factory_girl_rails'
Expand Down
27 changes: 23 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
GIT
remote: https://github.com/seuros/capistrano-puma.git
revision: 1d7cca2e431c23943ebcde19588169ed12025833
remote: git://github.com/seuros/capistrano-puma.git
revision: 00708fa18a029cb34f46aef60f920106c0c00107
specs:
capistrano3-puma (3.1.0)
capistrano (~> 3.7)
capistrano-bundler
puma (~> 3.4)

GIT
remote: https://github.com/shouya/cant_cant_cant.git
remote: git://github.com/shouya/cant_cant_cant.git
revision: 2dc86d3238febe461cfea48b8eeef38d0482c6d5
specs:
cant_cant_cant (0.1.10)
Expand Down Expand Up @@ -114,6 +114,19 @@ GEM
docile (1.1.5)
domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
elasticsearch (5.0.4)
elasticsearch-api (= 5.0.4)
elasticsearch-transport (= 5.0.4)
elasticsearch-api (5.0.4)
multi_json
elasticsearch-model (5.0.1)
activesupport (> 3)
elasticsearch (~> 5)
hashie
elasticsearch-rails (5.0.1)
elasticsearch-transport (5.0.4)
faraday
multi_json
enumerize (2.1.0)
activesupport (>= 3.2)
erubis (2.7.0)
Expand All @@ -123,6 +136,8 @@ GEM
factory_girl_rails (4.8.0)
factory_girl (~> 4.8.0)
railties (>= 3.0.0)
faraday (0.12.1)
multipart-post (>= 1.2, < 3)
ffaker (2.5.0)
ffi (1.9.18)
formatador (0.2.5)
Expand All @@ -142,6 +157,7 @@ GEM
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
hashie (3.5.5)
http-cookie (1.0.3)
domain_name (~> 0.5)
i18n (0.8.1)
Expand Down Expand Up @@ -186,6 +202,7 @@ GEM
mini_portile2 (2.1.0)
minitest (5.10.1)
multi_json (1.12.1)
multipart-post (2.0.0)
nenv (0.3.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
Expand Down Expand Up @@ -359,6 +376,8 @@ DEPENDENCIES
carrierwave
codeclimate-test-reporter
coffee-rails (~> 4.2)
elasticsearch-model
elasticsearch-rails
enumerize
factory_girl_rails
ffaker
Expand Down Expand Up @@ -396,4 +415,4 @@ DEPENDENCIES
web-console

BUNDLED WITH
1.13.6
1.14.6
8 changes: 7 additions & 1 deletion app/controllers/api/v1/admin/posts_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module API::V1::Admin
class PostsController < AdminController
resource_description { short '管理介面文章/視頻 API' }
before_action find_record, only: %i(destroy show update publish)
before_action find_record, only: %i(destroy show update publish toggle_recommended)

api :GET, '/admin/posts', 'List or filter on posts'
param :title, String, desc: '标题'
Expand Down Expand Up @@ -62,6 +62,12 @@ def unpublish
updated
end

api :POST, '/admin/posts/:post_id/toggle_recommended', 'toggle推荐文章'
def toggle_recommended
@post.toggle!(:recommended)
updated
end

def close
@post.close!
updated
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/api/v1/admin/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@ def permissions
}
end
end

api :GET, '/admin/info', 'Get current user\' info'
def info
success current_user_state
end
end
end
29 changes: 28 additions & 1 deletion app/controllers/api/v1/comments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ module API::V1
class CommentsController < APIController
resource_description { short '評論' }
before_action :find_commentable
before_action :find_comment, only: %i(like unlike)

api :GET, '/(posts|ads)/:id/comments',
'List all comments under given post or ad'
def index
success do
success(user_id: current_user_id) do
paginated(@commentable.comments.normal)
end
end
Expand All @@ -21,13 +22,39 @@ def create
created(comment)
end

api :POST, '/posts/:post_id/comments/:comment_id/like', 'like specfic comment'
param :post_id, Integer, desc: 'post id', required: true
param :comment_id, Integer, desc: 'comment id', required: true
def like
if @comment.like(current_user_id)
render json: { message: 'success' }
else
render json: { error: 'already liked' }
end
end

api :POST, '/posts/:post_id/comments/:comment_id/unlike', 'unlike specfic comment'
param :post_id, Integer, desc: 'post id', required: true
param :comment_id, Integer, desc: 'comment id', required: true
def unlike
if @comment.unlike(current_user_id)
render json: { message: 'success' }
else
render json: { error: 'already unliked' }
end
end

private

def find_commentable
@commentable = Post.find_by(id: params[:post_id]) ||
Ad. find_by(id: params[:ad_id])
end

def find_comment
@comment = Comment.find_by(id: params[:comment_id])
end

def comment_params
params.permit(:content, :parent_id)
end
Expand Down
23 changes: 21 additions & 2 deletions app/controllers/api/v1/posts_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module API::V1
class PostsController < APIController
resource_description { short '文章/視頻 API' }
before_action find_record, only: :show
before_action find_record, only: %i(show like unlike)

api :GET, '/posts', 'List all posts'
def index
Expand All @@ -10,7 +10,8 @@ def index

api :GET, '/posts/:id', 'Show specific post'
def show
success(@post)
@post.increment
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

increment is a bit ambiguous. What about using add_instance_counter_for :view in the model and invoke incr_view_count here?

success(@post, serializer: ::PostSerializer, user_id: current_user_id)
end

api :GET, '/posts/hot_in_week', 'Show a list of hot posts in recent 7-day'
Expand All @@ -23,5 +24,23 @@ def index_by_tag
tag = params[:tag]
success { Post.with_tag(tag).published }
end

api :POST, '/posts/:id/like', 'Like specfic post'
def like
if @post.like(current_user_id)
render json: { message: 'success' }
else
render json: { error: 'already liked' }
end
end

api :POST, '/posts/:id/unlike', 'Unlike specfic post'
def unlike
if @post.unlike(current_user_id)
render json: { message: 'success' }
else
render json: { error: 'already liked' }
end
end
end
end
4 changes: 3 additions & 1 deletion app/models/comment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
# depth :integer default(0)
# commentable_type :string
# commentable_id :integer
# author :string
# parent_id :integer
# created_at :datetime not null
# updated_at :datetime not null
Expand All @@ -27,8 +26,11 @@

class Comment < ApplicationRecord
include SmartFilterable
include Likeable
acts_as_paranoid

add_likeable

belongs_to :commentable, polymorphic: true

belongs_to :parent,
Expand Down
35 changes: 35 additions & 0 deletions app/models/concerns/likeable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module Likeable
extend ActiveSupport::Concern

include AccountAPIHelper

class_methods do
def add_likeable
define_method 'like' do |user_id|
unless find_like(user_id)
Like.create(user_id: user_id, target: self)
true
end
end

define_method 'unlike' do |user_id|
if find_like(user_id)
find_like(user_id).destroy
true
end
end

define_method 'find_like' do |user_id|
@first_like_cached ||= Like.find_by(user_id: user_id, target: self)
end
end
end

def liked
!!(Like.find_by(user_id: @instance_options[:user_id], target: object))
end

def like_count
Like.where(target: object).count
end
end
19 changes: 19 additions & 0 deletions app/models/like.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# == Schema Information
#
# Table name: likes
#
# id :integer not null, primary key
# user_id :string
# target_type :string
# target_id :string
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_likes_on_user_id_and_target_type_and_target_id (user_id,target_type,target_id)
#

class Like < ApplicationRecord
belongs_to :target, polymorphic: true
end
47 changes: 47 additions & 0 deletions app/models/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
# created_at :datetime not null
# updated_at :datetime not null
# deleted_at :datetime
# views :integer
# recommended :boolean default(FALSE)
#
# Indexes
#
Expand All @@ -38,9 +40,14 @@ class Post < ApplicationRecord
include SmartFilterable
include Countable
include ProcessPostMeta
include Likeable
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks

acts_as_paranoid

add_likeable

add_instance_counter_for :click
add_instance_counter_for :publishing
add_instance_counter_for :sharing
Expand Down Expand Up @@ -74,6 +81,11 @@ class Post < ApplicationRecord
scope :with_tag, ->(tag) { where('? = ANY(tags)', tag) }
scope :with_cover, -> { includes(:cover) }

mapping do
indexes :title, type: :string, analyzer: :smartcn
indexes :content_rendered, type: :string, analyzer: :smartcn
end

def article?
!video?
end
Expand Down Expand Up @@ -117,6 +129,41 @@ def close!
save
end

def increment(by = 1)
self.views ||= 0
self.views += by
save
end

def img_count
Nokogiri::HTML(content_rendered).css('img').length
end

def h2_list
Nokogiri::HTML(content_rendered).css('h2').map(&:text)
end

def related_posts(size = 4)
opts = {
query: {
more_like_this: {
fields: [:title, :content_rendered],
docs: [
{
_index: self.class.index_name,
_type: self.class.document_type,
_id: id
}
],
min_term_freq: 2,
min_doc_freq: 5
}
},
size: size
}
self.class.__elasticsearch__.search(opts).records.to_a
end

private

def render_content
Expand Down
9 changes: 8 additions & 1 deletion app/serializers/admin_short_post_serializer.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
class AdminShortPostSerializer < ApplicationSerializer
attributes :id, :title, :abstract, :state, :published_at
attributes :id,
:title,
:abstract,
:state,
:published_at,
:views,
:recommended

attribute :column_title do
object.column.title
end
Expand Down
1 change: 1 addition & 0 deletions app/serializers/application_serializer.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
class ApplicationSerializer < ActiveModel::Serializer
include RolePredicates
include Likeable
end
Loading