Попытка использовать current_user там, где он не определен - PullRequest
0 голосов
/ 18 апреля 2011

У меня есть этот вызов в моей модели голосования:

 fires :vote_updated, :on => :update,
                   :actor => :user,
                   :secondary_subject => :video,
                   :if => lambda { |vote| ((vote.value == 1) || (vote.value == -1)) && (vote.video.user != current_user)}

Если вы не знакомы, он работает с плагином timeline_fu .

Я делаюне хотите, чтобы вызов был запущен, если пользователь, которому принадлежит проголосовавшее видео, является текущим пользователем.Вот где появляется эта строка:

:if => lambda { |vote| ((vote.value == 1) || (vote.value == -1)) && (vote.video.user != current_user)}

Однако у меня нет доступа к current_user здесь.Как мне обойти это?

Вот метод создания в моем контроллере голосов (там на самом деле нет метода обновления):

def create       
  @video = Video.find(params[:video_id])
  @vote = current_user.video_votes.find_or_create_by_video_id(@video.id)

  if @vote.value.nil?
    if params[:type] == "up"
      @vote.value = 1
    else
      @vote.value = -1
    end
  elsif (params[:type] == "up" && @vote.value == 1) || (params[:type] == "down" && @vote.value == -1)
    @vote.value = 0
  elsif ((params[:type] == "up" && @vote.value == -1) || (params[:type] == "down" && @vote.value == 1)) || (@vote.value == 0)
    if params[:type] == "up"
      @vote.value = 1
    else
      @vote.value = -1
    end
  end  

  if @vote.save
    respond_to do |format|
      format.html { redirect_to @video }
      format.js
    end
  else
    respond_to do |format|
      format.html
      format.js
    end
  end  
end

Ответы [ 2 ]

0 голосов
/ 18 апреля 2011

Вы получаете эту ошибку, потому что обычно не рекомендуется обращаться к current_user (или информации о сеансе) в вашей модели. Я не очень хорошо знаком с гемом timeline_fu, поэтому этот ответ не будет лучшим ответом, который вы можете получить. Я просто покажу вам, как получить доступ к current_user из любой модели.

Сначала зайдите в контроллер вашего приложения. Вы захотите создать метод, который устанавливает текущего пользователя. Вам необходимо вызвать метод в фильтре before.

before_filter :loadCurrentUser 

def loadCurrentUser
  User.currentUser = current_user
end

Тогда в вашей пользовательской модели вам нужно определить 'currentUser'.

def self.currentUser
   Thread.currentUser[:user]
end

Вам не обязательно объявлять current_user в контроллере приложения, но, поскольку это драгоценный камень, я не уверен, имеет ли он легко доступный контроллер.

Редактировать: Этот способ может быть подвержен проблемам, но я не совсем уверен, спрашивали ли вы, как сделать current_user доступным в моделях, или использовать совершенно другой обходной путь, чтобы у вас не было этой проблемы ... и читали ответы другого ответа, я думаю, что это не то, что вы спрашивали.

0 голосов
/ 18 апреля 2011

Я считаю, что правильнее всего было бы проверить это в контроллере. Я бы создал фильтр до этого случая

UPDATE:

Просто в качестве быстрого примера:

before_filter :valid_vote, :only => :update

def update
   @vote.update_attributes(params[:vote]) # or whatever
end
..

private

def valid_vote
   @vote = Vote.find params[:id]
   unless ( @vote.video.user.id != current_user.id )
      render :text => 'You can't vote for your own video', :status => 403
   end
end

Таким образом, @vote объявляется и проверяется перед обработкой вашего действия 'update'. Если он недействителен, то ваше действие по обновлению остается без изменений

ОБНОВЛЕНИЕ 2:

не знаю, как вам это понравится, но вы также можете сделать следующее:

в модели голосования:

attr_accessor :skip_timeline

затем используйте концепцию с фильтром before, но сделайте @vote.skip_timeline = true вместо рендеринга текста

тогда утверждение может выглядеть следующим образом:

:if => lambda { |vote| ((vote.value == 1) || (vote.value == -1)) && !vote.skip_timeline }

Вы также можете переместить ((vote.value == 1) || (vote.value == -1)) к фильтру до:

def valid_vote
   @vote = Vote.find params[:id]
   unless ( [1,-1].include? @vote.value && @vote.video.user.id != current_user.id )
       @vote.skip_timeline = true
   end
end

и

: if => lambda {| голос | ! voice.skip_timeline}

...