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 Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ gem 'sinatra', require: false
gem 'whenever'
gem 'dotenv'
gem 'dotenv-deployment', require: 'dotenv/deployment'
gem 'redis-rails'

gem 'mysql2' # Don't worry, it's for Sphinx only!
gem 'thinking-sphinx'
Expand Down
17 changes: 17 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,22 @@ GEM
rdoc (4.2.2)
json (~> 1.4)
redis (3.3.1)
redis-actionpack (5.0.0)
actionpack (>= 4.0.0, < 6)
redis-rack (~> 2.0.0.pre)
redis-store (~> 1.2.0.pre)
redis-activesupport (5.0.1)
activesupport (>= 3, < 6)
redis-store (~> 1.2.0)
redis-rack (2.0.0.pre)
rack (> 1.5, < 3)
redis-store (~> 1.2.0.pre)
redis-rails (5.0.1)
redis-actionpack (~> 5.0.0)
redis-activesupport (~> 5.0.0)
redis-store (~> 1.2.0)
redis-store (1.2.0)
redis (>= 2.2)
remotipart (1.3.0)
request_store (1.3.1)
require_all (1.3.3)
Expand Down Expand Up @@ -524,6 +540,7 @@ DEPENDENCIES
rails (= 4.2.6)
rails_best_practices
rb-fsevent
redis-rails
remotipart
responders
rspec-rails (~> 3.0)
Expand Down
13 changes: 4 additions & 9 deletions app/controllers/concerns/rated.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module Rated
extend ActiveSupport::Concern
included do
before_action :find_rateable, only: [:rate_inc, :rate_dec, :rate_revoke]
before_action :protect_forbidden_rate, only: [:rate_inc, :rate_dec]
end

def rate_inc
Expand All @@ -18,8 +17,8 @@ def rate_dec
end

def rate_revoke
authorize @rateable, :rate_revoke?
return head :forbidden unless current_user? || rate_exists?
authorize @rateable, :rate?
return head :forbidden unless current_user? || own_rate_exists?
@rateable.revoke_rate!(current_user)
render json: json_data(true)
end
Expand All @@ -34,15 +33,11 @@ def current_user?
@rateable.user_id == current_user.id
end

def rate_exists?
def own_rate_exists?
Rating.exists?(rateable: @rateable, user_id: current_user.id)
end

def find_rateable
@rateable = controller_name.classify.constantize.find(params[:id])
end

def protect_forbidden_rate
head :forbidden if current_user? || rate_exists?
end
end
end
2 changes: 1 addition & 1 deletion app/jobs/mail_digest_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class MailDigestJob < ActiveJob::Base
queue_as :mailers

def perform
question_ids = Question.where(created_at: Time.now.yesterday.all_day).order(created_at: :desc).map(&:id)
question_ids = Question.where(created_at: Time.now.yesterday.all_day).order(:created_at).map(&:id)

User.find_each do |user|
CustomMailer.digest(user, question_ids).deliver_later
Expand Down
2 changes: 1 addition & 1 deletion app/models/answer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class Answer < ActiveRecord::Base
include Commentable

belongs_to :user
belongs_to :question
belongs_to :question, touch: true
has_many :attachments, as: :attachable, dependent: :destroy

accepts_nested_attributes_for :attachments, reject_if: :all_blank
Expand Down
2 changes: 1 addition & 1 deletion app/models/attachment.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class Attachment < ActiveRecord::Base
belongs_to :attachable, polymorphic: true
belongs_to :attachable, polymorphic: true, touch: true

mount_uploader :file, FileUploader

Expand Down
2 changes: 1 addition & 1 deletion app/models/comment.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :commentable, polymorphic: true
belongs_to :commentable, polymorphic: true, touch: true

validates :user_id, presence: true
validates :body, presence: true, length: (2..2_000)
Expand Down
2 changes: 1 addition & 1 deletion app/models/subscription.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :question
belongs_to :question, touch: true

validates :question_id, :user_id, presence: true

Expand Down
6 changes: 1 addition & 5 deletions app/policies/rateable_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,4 @@ module RateablePolicy
def rate?
admin? || user? && !owner?
end

def rate_revoke?
admin? || owner?
end
end
end
19 changes: 10 additions & 9 deletions app/views/comments/_comment.slim
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
p id="comment-#{comment.id}"
= comment.body
span.little style="color:gray"
'
' &mdash;
=> comment.user.email
' at
= l comment.created_at, format: :short
hr style="margin:0 0 8px 0"
- cache [:comment_form, comment] do
p id="comment-#{comment.id}"
= comment.body
span.little style="color:gray"
'
' &mdash;
=> comment.user.email
' at
= l comment.created_at, format: :short
hr style="margin:0 0 8px 0"
13 changes: 7 additions & 6 deletions app/views/comments/_list.slim
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
.comments id="#{commentable.entity}-comments-#{commentable.id}-container"
div id="#{commentable.entity}-comments-#{commentable.id}-header" style="#{commentable.comments.any? ? '' : 'display:none'}"
hr style="margin:2px 4px 0 4px"
h4 Comments:
div id="#{commentable.entity}-comments-#{commentable.id}" style="margin-left:40px"
- commentable.comments.each do |comment|
= render 'comments/comment', comment: comment
- cache [commentable, :comment_list] do
div id="#{commentable.entity}-comments-#{commentable.id}-header" style="#{commentable.comments.any? ? '' : 'display:none'}"
hr style="margin:2px 4px 0 4px"
h4 Comments:
div id="#{commentable.entity}-comments-#{commentable.id}" style="margin-left:40px"
- commentable.comments.each do |comment|
= render 'comments/comment', comment: comment
Copy link

Choose a reason for hiding this comment

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

Лучше кэш переместить внутрь самого паршла, чтобы можно было и в других местах его же использовать.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Пожалуй, да, и першаиал не имеет логики, и в свете предыдущей правки это логично.


- if policy(Comment).create?
div id="#{commentable.entity}-comments-#{commentable.id}-errors"
Expand Down
71 changes: 36 additions & 35 deletions app/views/questions/_answer.slim
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
div id="answer-#{answer.id}" class="#{answer.starred ? 'answer-starred' : ''}"
.row
.col-xs-12
- if answer.starred
p.best-answer
strong Best Answer:
.pull-right id="answer-buttons-#{answer.id}"
- if comet
javascript:
$("#answer-buttons-#{answer.id}").html(JST["answer_buttons"]({
question_id: "#{answer.question.id}",
question_user_id: "#{answer.question.user.id}",
answer_id: "#{answer.id}",
answer_user_id: "#{answer.user.id}"
}));
- else
- if policy(answer).destroy?
=> link_to 'Delete', answer_path(answer), id: "delete-answer-#{answer.id}", class: "btn btn-danger btn-sm", method: :delete, remote: true
- if policy(answer).edit?
=> link_to 'Edit', '#', id: "edit-answer-link-#{answer.id}", class: "btn btn-info btn-sm edit-answer-link", data: {answer_id: answer.id}
- if policy(answer).star?
= link_to 'Star', star_answer_path(answer), id: "star-answer-link-#{answer.id}", class: "btn btn-warning btn-sm star-answer-link", data: {answer_id: answer.id}, method: :patch, remote: true
= render 'shared/rating', rateable: answer
blockquote
= answer.body
= render 'questions/attachments', attachable: answer
= render 'comments/list', commentable: answer, comet: false
- if policy(answer).update?
div
= form_for answer, remote: true do |f|
= f.label :body, 'Answer'
.little id="answer-errors-#{answer.id}"
= f.text_area :body, class: 'form-control'
= f.submit 'Save', class: "btn btn-info btn-sm pull-right"
hr
- cache [answer, policy(answer).edit?, policy(answer).destroy?, policy(answer).star?, comet]
Copy link

Choose a reason for hiding this comment

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

Идея хорошая, но в данном случае разве нельзя ограничится чем-то одним из edit? и destroy?.
Хотя, если они ровны, на количество ключей не повлияет все равно.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Да можно в принципе, ключи типа "Answer и 3 boolean-а" нигде не используются больше, но это скорее с целью предусмотреть "на будущее", если вдруг они станут не равны -- формально мы же их так и проверяем разными в паршиале. Тем более, что длина ключа особо не влияет ни на что, так что решил формально учесть, как было, например, с политикой на подписку.

div id="answer-#{answer.id}" class="#{answer.starred ? 'answer-starred' : ''}"
.row
.col-xs-12
- if answer.starred
p.best-answer
strong Best Answer:
.pull-right id="answer-buttons-#{answer.id}"
- if comet
javascript:
$("#answer-buttons-#{answer.id}").html(JST["answer_buttons"]({
question_id: "#{answer.question.id}",
question_user_id: "#{answer.question.user.id}",
answer_id: "#{answer.id}",
answer_user_id: "#{answer.user.id}"
}));
- else
- if policy(answer).destroy?
=> link_to 'Delete', answer_path(answer), id: "delete-answer-#{answer.id}", class: 'btn btn-danger btn-sm', method: :delete, remote: true
- if policy(answer).edit?
=> link_to 'Edit', '#', id: "edit-answer-link-#{answer.id}", class: 'btn btn-info btn-sm edit-answer-link', data: {answer_id: answer.id}
- if policy(answer).star?
= link_to 'Star', star_answer_path(answer), id: "star-answer-link-#{answer.id}", class: 'btn btn-warning btn-sm star-answer-link', data: {answer_id: answer.id}, method: :patch, remote: true
= render 'shared/rating', rateable: answer
blockquote
= answer.body
= render 'questions/attachments', attachable: answer
= render 'comments/list', commentable: answer, comet: false
- if policy(answer).edit?
div
= form_for answer, remote: true do |f|
= f.label :body, 'Answer'
.little id="answer-errors-#{answer.id}"
= f.text_area :body, class: 'form-control'
= f.submit 'Save', class: 'btn btn-info btn-sm pull-right'
hr
11 changes: 6 additions & 5 deletions app/views/questions/_attachments.slim
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
hr
p
| Attachments:
- attachable.attachments.each do |a|
div id="attachment-#{a.id}"
=> glyph :paperclip
=> link_to a.file.filename, a.file.url
= link_to '&times;'.html_safe, attachment_path(a), remote: true, method: :delete, id: "delete-attachment-#{a.id}", style: 'font-size:1.3em;font-weight:bold;color:red'
- attachable.attachments.each do |attachment|
- cache attachment do
div id="attachment-#{attachment.id}"
=> glyph :paperclip
=> link_to attachment.file.filename, attachment.file.url
= link_to '&times;'.html_safe, attachment_path(attachment), remote: true, method: :delete, id: "delete-attachment-#{attachment.id}", style: 'font-size:1.3em;font-weight:bold;color:red'
62 changes: 32 additions & 30 deletions app/views/questions/_question.slim
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
div id="question-#{question.id}"
row
.col-sm-10
p.lead
= link_to question_path(question)
= question.topic
- if policy(question).update?
div
= form_for question, remote: true do |f|
.little id="question-errors-#{question.id}"
= f.label :topic, 'Topic'
= f.text_field :topic, class: 'form-control'
= f.label :body, 'Question'
= f.text_area :body, class: 'form-control'
= f.submit 'Save', class: "btn btn-info btn-sm pull-right"
.col-sm-2
.pull-right id="question-buttons-#{question.id}"
- if comet
javascript:
$("#question-buttons-#{question.id}").html(JST["question_buttons"]({
question_id: "#{question.id}",
question_user_id: "#{question.user.id}"
}));
- else
- if policy(question).edit?
= link_to 'Edit', '#', id: "edit-question-link-#{question.id}", class: "btn btn-info btn-sm edit-question-link pull-right", data: {question_id: question.id}
= render 'shared/rating', rateable: question
row
.col-xs-12
hr
- cache [question, policy(question).update?, comet]
div id="question-#{question.id}"
.row
.col-sm-10
p.lead
= link_to question_path(question)
= question.topic
- if policy(question).update?
div
= form_for question, remote: true do |f|
.little id="question-errors-#{question.id}"
= f.label :topic, 'Topic'
= f.text_field :topic, class: 'form-control'
= f.label :body, 'Question'
= f.text_area :body, class: 'form-control'
= f.submit 'Save', class: "btn btn-info btn-sm pull-right"
.col-sm-2
.pull-right id="question-buttons-#{question.id}"
- if comet
javascript:
$("#question-buttons-#{question.id}").html(JST["question_buttons"]({
question_id: "#{question.id}",
question_user_id: "#{question.user.id}"
}));
- else
- if policy(question).edit?
= link_to 'Edit', '#', id: "edit-question-link-#{question.id}", \
class: 'btn btn-info btn-sm edit-question-link pull-right', data: {question_id: question.id}
= render 'shared/rating', rateable: question
.row
.col-xs-12
hr
Loading