如何解决此 ability.rb 优先级问题?

How do I fix this ability.rb precedence issue?

我正在使用 CanCanCan,在我的 ability.rb 文件中我有这个:

  def initialize(user)
    alias_action :vote_up, :vote_down, to: :vote

    user ||= User.new # guest user (not logged in)
    if user.admin?
      can :manage, :all
    else
      can :manage, Question, user_id: user.id
      can :manage, Answer, user_id: user.id
      can :manage, Job, user_id: user.id
      can :manage, Company, user_id: user.id
      can :read, :all
      cannot :read, User do |u|
        !u.eql?(user.id)
      end

      can :vote, [Question, Answer]

    end
end

但是,当我尝试向不拥有 question 的用户投票时,它拒绝了。

例如,当我以 abc@test.com 身份登录时,这是投票时日志的样子:

Started POST "/questions/yet-another-hello-world/vote_up" for ::1 at 2016-06-14 23:45:13 -0500
Processing by QuestionsController#vote_up as JS
  Parameters: {"id"=>"yet-another-hello-world"}
  User Load (2.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  ORDER BY "users"."id" ASC LIMIT   [["id", 1546], ["LIMIT", 1]]
  Question Load (4.8ms)  SELECT  "questions".* FROM "questions" WHERE "questions"."user_id" =  AND "questions"."slug" =  ORDER BY "questions"."id" ASC LIMIT   [["user_id", 1546], ["slug", "yet-another-hello-world"], ["LIMIT", 1]]
  Answer Load (1.4ms)  SELECT "answers".* FROM "answers" WHERE "answers"."question_id" = 43
   (1.3ms)  SELECT COUNT(*) FROM "votes" WHERE "votes"."votable_id" =  AND "votes"."votable_type" =  AND "votes"."voter_id" =  AND "votes"."vote_scope" IS NULL AND "votes"."voter_type" =   [["votable_id", 43], ["votable_type", "Question"], ["voter_id", 1546], ["voter_type", "User"]]
   (0.7ms)  BEGIN
  SQL (3.8ms)  INSERT INTO "votes" ("votable_type", "votable_id", "voter_type", "voter_id", "vote_flag", "vote_weight", "created_at", "updated_at") VALUES (, , , , , , , ) RETURNING "id"  [["votable_type", "Question"], ["votable_id", 43], ["voter_type", "User"], ["voter_id", 1546], ["vote_flag", true], ["vote_weight", 1], ["created_at", 2016-06-15 04:45:13 UTC], ["updated_at", 2016-06-15 04:45:13 UTC]]
   (0.9ms)  COMMIT
   (1.3ms)  SELECT COUNT(*) FROM "votes" WHERE "votes"."votable_id" =  AND "votes"."votable_type" =  AND "votes"."vote_scope" IS NULL  [["votable_id", 43], ["votable_type", "Question"]]
   (1.4ms)  SELECT COUNT(*) FROM "votes" WHERE "votes"."votable_id" =  AND "votes"."votable_type" =  AND "votes"."vote_flag" =  AND "votes"."vote_scope" IS NULL  [["votable_id", 43], ["votable_type", "Question"], ["vote_flag", true]]
   (1.4ms)  SELECT COUNT(*) FROM "votes" WHERE "votes"."votable_id" =  AND "votes"."votable_type" =  AND "votes"."vote_flag" =  AND "votes"."vote_scope" IS NULL  [["votable_id", 43], ["votable_type", "Question"], ["vote_flag", false]]
   (1.6ms)  SELECT SUM("votes"."vote_weight") FROM "votes" WHERE "votes"."votable_id" =  AND "votes"."votable_type" =  AND "votes"."vote_flag" =  AND "votes"."vote_scope" IS NULL  [["votable_id", 43], ["votable_type", "Question"], ["vote_flag", true]]
   (1.5ms)  SELECT SUM("votes"."vote_weight") FROM "votes" WHERE "votes"."votable_id" =  AND "votes"."votable_type" =  AND "votes"."vote_flag" =  AND "votes"."vote_scope" IS NULL  [["votable_id", 43], ["votable_type", "Question"], ["vote_flag", false]]
  CACHE (0.0ms)  SELECT SUM("votes"."vote_weight") FROM "votes" WHERE "votes"."votable_id" =  AND "votes"."votable_type" =  AND "votes"."vote_flag" =  AND "votes"."vote_scope" IS NULL  [["votable_id", 43], ["votable_type", "Question"], ["vote_flag", true]]
  CACHE (0.0ms)  SELECT SUM("votes"."vote_weight") FROM "votes" WHERE "votes"."votable_id" =  AND "votes"."votable_type" =  AND "votes"."vote_flag" =  AND "votes"."vote_scope" IS NULL  [["votable_id", 43], ["votable_type", "Question"], ["vote_flag", false]]
   (0.8ms)  BEGIN
  SQL (2.1ms)  UPDATE "questions" SET "cached_votes_total" = , "cached_votes_up" = , "cached_votes_score" = , "cached_weighted_total" = , "cached_weighted_score" = , "updated_at" =  WHERE "questions"."id" =   [["cached_votes_total", 1], ["cached_votes_up", 1], ["cached_votes_score", 1], ["cached_weighted_total", 1], ["cached_weighted_score", 1], ["updated_at", 2016-06-15 04:45:13 UTC], ["id", 43]]
   (1.5ms)  COMMIT
  Rendering questions/vote_up.js.erb
  Rendered questions/vote_up.js.erb (1.3ms)
Completed 200 OK in 69ms (Views: 14.8ms | ActiveRecord: 26.9ms)

这很正常而且效果很好。

但是,如果我以另一个用户身份登录并尝试vote_up同样的问题,日志如下所示:

Started POST "/questions/yet-another-hello-world/vote_up" for ::1 at 2016-06-14 23:46:40 -0500
Processing by QuestionsController#vote_up as JS
  Parameters: {"id"=>"yet-another-hello-world"}
  User Load (2.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  ORDER BY "users"."id" ASC LIMIT   [["id", 1547], ["LIMIT", 1]]
  Question Load (3.2ms)  SELECT  "questions".* FROM "questions" WHERE "questions"."user_id" =  AND "questions"."slug" =  ORDER BY "questions"."id" ASC LIMIT   [["user_id", 1547], ["slug", "yet-another-hello-world"], ["LIMIT", 1]]
Completed 404 Not Found in 14ms (ActiveRecord: 5.3ms)



ActiveRecord::RecordNotFound - ActiveRecord::RecordNotFound:
  friendly_id (5.1.0) lib/friendly_id/finder_methods.rb:23:in `find'
  app/controllers/questions_controller.rb:123:in `set_question'

你可以看到它正在检查问题是否属于我控制器中的 current_user 但它在这里失败了:

def set_question
  @question = current_user.questions.includes(:answers).friendly.find(params[:id])
end

想法?

@question = current_user.questions.includes(:answers).friendly.find(params[:id])

这是错误的地方,因为 current_user 不拥有该问题,所以无法同时找到 question_iduser_id 的问题。您可以在日志中看到查询的内容:

SELECT "questions".* FROM "questions" WHERE "questions"."user_id" = AND "questions"."slug" = ORDER BY "questions"."id" ASC LIMIT [["user_id", 1547], ["slug", "yet-another-hello-world"], ["LIMIT", 1]]

将查找问题查询更改为:

@question = Question.includes(:answers).friendly.find(params[:id])

现在所有用户都可以对该问题进行投票,即使该问题不属于 him/her。