show method variable

In my show method for my products controller I’ve got a variable that track qty ( @remaining ).

Can I access this variable from another method within the same controller?

Thanks,

Joe

Joe,

You can as it is an instance variable, but it will only be available for that instance of the controller (i.e., a single request). If you’re calling other methods during that show request, the instance variable will be available. If you want to access it from another method that responds to a different request, it won’t be set. You can also use this instance variable in any views resulting from the show method.

I hope this was clear enough…

Tamara

ok good. yes, I will call it from within that same controller…

Now I’ve got to figure out how to run an update query.

ok, I added this piece of code…

  if @remaining == 1
# put some conditions around this @remaining == 0?
  Product.update(params[:product_id], :funded => true)
  Cart.where(:product_id => params[:product_id]).update_all(:processing => true)

ok, i used pry.binding to look at the @remining variable and it’s nil.

that why it’s not working. so the question is why is this the case when it has a value in the show section?

ok, i used pry.binding to look at the @remining variable and it's nil.

that why it's not working. so the question is why is this the case when it has a value in the show section?

As tamouse said:

You *can* as it is an *instance variable*, but it will only be available for that instance of the controller (i.e., a single request). If you're calling other methods during that show request, the instance variable will be available. If you want to access it from another method that responds to a different request, it won't be set. You can also use this instance variable in any views resulting from the show method.

You are trying to access it from another method that responds to a different request.

Colin

Ok, how do I deal with that?

You have to recalculate the variable in each method that you need it.

Colin

ok, I thought about that. Would it be ok to like set the instant variable to a global and use that?

$remaining = @remaining

I tried that, and it seems to have worked. I not sure if it’s the best practice though.

As Colin mentioned you’d want to recalculate the variable in each method that it’s used. Global variables may work for your use case but they are not best practice and can lead to a mutable/mutex object which may not be your intended behavior.

Would it be ok to like set the instant variable to a global and use that?

Not if that value is going to be different for different users...

I tried that, and it seems to have worked. I not sure if it's the best practice though.

It's not.

Write a separate method that creates the instance variable and use a before_filter to set it in the methods that need it.

ok, I thought about that. Would it be ok to like set the instant variable to a global and use that?

$remaining = @remaining

I tried that, and it seems to have worked. I not sure if it's the best practice though.

Definitely not. In addition to the fact that presumable @remaining is different for different products, and a request for a different product could come in between the two requests you are interested in (so the global would be set for the wrong product) consider the case where your app becomes popular enough to be distributed over multiple instances of the server. In that case the two requests might go to different servers so the global would not be setup for the second one. Also consider that when using something like nginx to run your production site that if it is not used for a while nginx may shutdown the app and restart it when the next request comes in. Again the global would not be set.

I suggest following Hassan's advice.

Colin

so basically what your saying is;

before filter: calc_remaining

def calc_renaming

     #taken query here -- I forget what I did - not at my development pc...

@remaining = @product.qty - @taken

end

Then call calc_renaming from the two methods I need to figure out what remaining is.

Thanks,

Joe

You won't need to call it explicitly in the methods, that is what before_filter does. If you only need it in those two methods then either specify that in the before filter (look at the docs for how to do that), or don't use before filter just call it in the methods. However if @taken is also a query on product then define a method in product called, possibly, remaining and then in your methods just do @remaining = @product.remaining

Colin

ok, here’s my method…

def calc_remaining
  @taken = Cart.where('product_id' => @product).count

  @remaining = @product.qty - @taken
end


but when I call it from my add to cart method, @product.qty is undefined method `qty' for nil:NilClass.

And that tells you that @product is nil at that point. Where is the code that sets that variable?

It works fine in the show method, but fails in add_to_cart.

You’re getting no method error “qty” because @product is not set in your controller action. So you’re essentially trying to subtract @taken from something that is NIL.

You need to see @product as an instance variable in your specific controller method and this should work out for you.

-James

it is set up in the private section

def set_product
  @product = Product.find(params[:id])
end


and I can see it in my show method...

**How do I get to see it in my**

def calc_remaining @taken = Cart.where(‘product_id’ => @product).count @remaining = @product.qty - @taken end

method?


it is set up in the private section

def set_product   @product = Product.find(params[:id]) end

and I can see it in my show method...

How do I get to see it in my

def calc_remaining @taken = Cart.where('product_id' => @product).count @remaining = @product.qty - @taken end

method?

Presumably you know which product you are talking about in that method, that is what it should be.

Colin