如何在Rails控制器中将变量从一个操作传递到另一个操作?

时间:2012-12-16 07:01:34

标签: ruby ruby-on-rails-3 ruby-on-rails-3.2

我需要通过update操作调用create操作:

def create
  @product = Product.find_or_initialize_by_sku(params[:sku])
  if @product.new_record?
    respond_to do |format|
      if @product.save
        format.html { redirect_to @product, notice: 'Product was successfully created.' }
        format.json { render json: @product, status: :created, location: @product }
      else
        format.html { render action: "new" }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  else
   update ##*** I am calling the update action at this point ***##
  end
end

def update
  @product = Product.find_or_initialize_by_sku(params[:sku])

  respond_to do |format|
    if @product.update_attributes(params[:product])
      format.html { redirect_to @product, notice: 'Product was successfully updated.' }
      format.json { head :no_content }
    else
      format.html { render action: "edit" }
      format.json { render json: @product.errors, status: :unprocessable_entity }
    end
  end
end

但我最终对我的数据库进行了两次相同的查询,因为我不确定将变量(在本例中为实例变量@product)从一个动作传递到另一个动作的最有效方法。

我试图抓住'rails'的方式来做到这一点。我该怎么办(据我所知,我不应该进行两次相同的数据库查询)?

我是否会将其存储在会话中,就好像我正在执行重定向一样(我是在我从另一个操作中调用某个操作时执行重定向?)?

session[:product] = @product # in my create action
# then
@product = session[:product] # in my update action

缓存是否会使这一切变得没有实际意义?

1 个答案:

答案 0 :(得分:3)

考虑使用memoization

@product ||= Product.find_or_initialize_by_sku(params[:sku])

||=运算符将检查@product是否为零,如果是,则Ruby将执行查找程序。否则,Ruby将使用当前值。因此,当您从update致电create时,update方法将使用您在@product中找到或初始化的create

关于第二个问题,当您从另一个调用一个控制器操作时,您没有执行重定向。尽量不要过度思考 - 控制器只是另一个具有自己的实例变量(例如@product)和方法的Ruby类。要执行重定向,您必须调用redirect_to,这将导致向您的控制器发送第二个Web请求。