0

I have an issue storing the result of a query in a controller:

payments = Payment.select("SecurityKey").where("VendorTxCode = '%#{params[:VendorTxCode]}%'").limit(1)

payments.each do |payment|
    security_key = payment.SecurityKey
end

Later when I use security_key, I get an error that it is undefined. However, when I run this in the rails console as:

payments.each do |payment|
    puts payment.SecurityKey
end
#=> df4g5ds6

How can I store this result in a variable for use later on as my method is not working?

Harry
  • 1,659
  • 5
  • 19
  • 34
  • 2
    Just curious why you have a `.limit(1)` in your controller when you're planning to loop through each payment? – claptimes Oct 26 '12 at 15:56
  • 1
    Its not a good idea to just plop down `params[:VendorTxCode]` in your SQL clause, this is open to SQL injection attack. Rather, use a bind parameter: `Payment.select("SecurityKey").where(["VendorTxCode = '%?%'", params[:VendorTxCode]])`. Notice the use of `?` in your query, where the actual value once its escaped by ActiveRecord will be substituted in. – Cody Caughlan Oct 26 '12 at 16:03
  • @claptimes because I know no better way at moment. – Harry Oct 27 '12 at 17:48
  • @CodyCaughlan, I guess this is good practice but in this instance comes directly from a Sage Pay POST request so would be fair to assume this is not going to malicious. No harm in doing this though, so thanks. – Harry Oct 27 '12 at 17:49

4 Answers4

1

It looks like you need to define your variable before your each do block. Try storing the keys into an array as such:

payments = Payment.select("SecurityKey").where("VendorTxCode = '%#
{params[:VendorTxCode]}%'").limit(1)

security_key = []
payments.each do |payment|
    security_key << payment.SecurityKey
end

And then you can access the keys like security_key[0], etc.

oshikryu
  • 257
  • 1
  • 13
0

First off, since you're limiting your search to 1, you don't really need to use a loop. Just do:

security_key = payments.first.SecurityKey

Other than that, what do you mean by "Later when I use security_key, I get an error that it is undefined.". Where are you using it? Are you using it within that method? Then it should be there. The only reason why it may not be, is if your query returned nothing. If your query returned an empty collection, then the loop will never happen, and the variable will never be created or set.

Try this:

payments = Payment.select("SecurityKey").where("VendorTxCode = '%#{params[:VendorTxCode]}%'").limit(1)

p payments.first # Will output nil if it's not there

If you get outputted nil, then you know that's what's happening. You'll then have to modify your code to check for nil and respond/behave accordingly.

MrDanA
  • 11,489
  • 2
  • 36
  • 47
0

If by 'later' you mean accessing it from helpers or views, you need to make the variable an instance variable instead of local: @security_key.

nanaya
  • 500
  • 4
  • 5
0

You're defining security_key as a local variable within the scope of the do...end block you're passing to that each statement. In other words, it's not available outside that block. Here's an example in the Pry console.

[4] pry(main)> (1..10).each {|number| result = number}
=> 1..10
[5] pry(main)> result
NameError: undefined local variable or method `result' for main:Object

result defined inside the block is not defined or visible outside it.

[6] pry(main)> result = 0
=> 0
[7] pry(main)> (1..10).each {|number| result = number}
=> 1..10
[8] pry(main)> result
=> 10

Here, by defining result within the scope of the console session first I can now see the changes made to it within the block.

Does that make sense?

Mark Weston
  • 1,164
  • 10
  • 12