2015-03-28 3 views
0

Я пытаюсь как можно больше сегментировать код для обратных вызовов логики контроллера. Но я начинаю беспокоиться о производительности. В приведенном ниже примере мне нужно запросить один и тот же экземпляр Vote 3x при обновлении голоса #. В любом случае, чтобы передать объект вокруг, чтобы я мог поддерживать мои обратные вызовы, но только один раз запрос db? Я пропустил какой-то механизм в Rails?Можно объединить удары БД при использовании обратных вызовов в контроллерах?

class VoteController < ApplicationController 
    #Access limitations etc. 
    before_action :authenticate_user! 
    before_action :correct_user_vote, only: [:edit, :update] 
    before_action :election_concluded_check, only: [:update] 

    def edit 
     @vote = Vote.find(params[:id]) 
    end 

    def update 
     @vote = Vote.find(params[:id]) 

     if [email protected]? && @vote.update_attributes(vote_params) 
      redirect_to party_path(@vote.party_id) 
     else 
      flash[:error] = "Something went wrong" 
      redirect_to root_path 
     end 
    end 

    private 

     def correct_user_vote 
      vote = Vote.find(params[:id]) 
      if vote.nil? || current_user.id!=vote.user_id 
       flash[:error] = "Something went wrong" 
       redirect_to root_path 
      end 
     end 

     def election_concluded_check 
      # Do not allow updating of votes if party.concluded 
      vote = Vote.find(params[:id]) 
      if vote.nil? || vote.election.concluded 
       flash[:error] = "Something went wrong" 
       redirect_to root_path 
      end 
     end 

     def vote_params 
      params[:vote].permit(:candidate_id,:note) 
     end 
end 

ответ

2

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

class VoteController < ApplicationController 
    before_action :authenticate_user! 
    before_action :find_vote, only: [:edit, :update] 
    before_action :correct_user_vote, only: [:edit, :update] 
    before_action :election_concluded_check, only: [:update] 

    def edit 
    end 

    def update 
    if @vote.update_attributes(vote_params) 
     redirect_to party_path(@vote.party_id) 
    else 
     flash[:error] = "Something went wrong" 
     redirect_to root_path 
    end 
    end 

    private 

    def find_vote 
    @vote = Vote.find(params[:id]) 
    end 

    def correct_user_vote 
    if current_user.id != @vote.user_id 
     flash[:error] = "Something went wrong" 
     redirect_to root_path 
    end 
    end 

    def election_concluded_check 
    # Do not allow updating of votes if party.concluded 
    if @vote.election.concluded 
     flash[:error] = "Something went wrong" 
     redirect_to root_path 
    end 
    end 
end 

Причиной вы можете сделать это, что переменный экземпляр (переменный, начинающийся с @) являются доступными между методами в одном и том же объекте. Таким образом, вы можете установить одним способом (find_vote), затем получить доступ к нему в других методах одного и того же объекта (например, update). В этом случае загружается только один раз в методе find_vote.

заметить также, что, как только вы загрузите переменную экземпляра в before_action, вам больше не нужно делать что-либо в вашем edit метод, который представляет собой хороший побочный эффект этого подхода.

Как примечание стороны, если предположить, что Vote является ActiveRecord::Base подкласс, когда вы делаете @vote = Vote.find(id), то объект никогда не будет nil, поскольку ActiveRecord::Base#find генерирует исключение, если он не находит запись, которую вы просите. Поэтому нет необходимости проверять на наличие @vote.nil?.

-1

Обычный метод заключается в замене переменных на метод, который кэширует объект при первом доступе. Например:

def edit 
    @vote = vote 
    end 

private 

    def vote 
    @_vote ||= Vote.find(params[:id]) 
    end 

    def correct_user_vote 
    if vote.nil? || current_user.id != vote.user_id 
     flash[:error] = "Something went wrong" 
     redirect_to root_path 
    end 
    end 

К сожалению, Rails считает, что это хорошая идея, чтобы передать информацию своим видом, используя переменные экземпляра, так что вы должны быть осторожны, о том, как вы называете ваши кэшированные значения (отсюда @_vote вместо).

Смежные вопросы