Reputation: 5802
There is a situation where I need to call my update
action from my create
action:
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
But I end up making two identical queries to my database because I am not sure of the most effective way to pass a variable (in this case, the instance variable @product
) from one action to another.
I am trying to get a grasp on the 'rails' way to do this. What should I do here (as I know I should not be making two identical database queries)?
Would I store it in the session as if I was performing a redirect (Am I performing a redirect when I call an action from within another action like this?)?
session[:product] = @product # in my create action
# then
@product = session[:product] # in my update action
Does caching make this all a moot point?
Upvotes: 0
Views: 1959
Reputation: 773
Consider using memoization:
@product ||= Product.find_or_initialize_by_sku(params[:sku])
The ||=
operator will check if @product
is nil, and if it is, Ruby will execute the finder. Otherwise, Ruby will use the current value. Therefore, when you call update
from create
, the update
method will use the @product
that you found or initialized in create
.
Regarding your second question, you're not performing a redirect when you call one controller action from another. Try not to over-think it - a controller is just another Ruby class with its own instance variables (e.g. @product
) and methods. To perform a redirect, you would have to call redirect_to
, which would result in a second web request to your controller.
Upvotes: 3