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