Ruby: Convert String to Symbol during String Interpolation - ruby

I am looping over a block of code, each time increasing variable "filter_index", from 1, to 2, to 3... etc.
I'd like to use this variable to access the different symbols:
filter1_field_name,
filter2_field_name,
filter3_field_name
#filter1_field_name = "Region"
#filter2_field_name = "Country"
#filter3_field_name = "City"
SELECT_STATEMENT = "GROUP BY "
numberOfFilters = 3
filter_index = 1
numberOfFilters.times do #Number of iterations
filter_field_name = "#filter#{filter_index.to_s}_field_name"
SELECT_STATEMENT.sub! "GROUP BY", "AND #{filter_field_name.to_sym} GROUP BY"
filter_index += 1
end
puts SELECT_STATEMENT
This results in
AND #filter1_field_name AND #filter2_field_name AND
#filter3_field_name GROUP BY
But the desired result is
AND Region AND Country AND City GROUP BY
I'm wondering why filter_field_name.to_sym is not working (or rather, what I'm doing wrong)?

You can use instance_variable_get function to get variable value.
Replace the line
filter_field_name = "#filter#{filter_index.to_s}_field_name"
with
filter_field_name = instance_variable_get("#filter#{filter_index.to_s}_field_name")
EDIT:
I think you can put the field names into an array and concat the values with join method.
fields = ['Region','Country','City']
fields.join(' AND ')

you can use instance_variable_get or eval
filter_field_name = instance_variable_get("#filter#{filter_index.to_s}_field_name")
or
filter_field_name = eval("#filter#{filter_index.to_s}_field_name")

Related

one2many field get row number

I have a module contain one2many filed.
while I create data line in this o2m field, I'd like to append a row number to it.
I have try some method that I found in forum, like this link.
but since I have no function called _onchange_partner_id() , I don't know how to use it.
or this link .
but it seems like an old version method that I can't get well.
class YcWeight(models.Model):
_name = "yc.weight"
customer_detail_ids = fields.One2many("yc.weight.details", "name", "customer details")
class YcWeightDetails(models.Model):
_name = "yc.weight.details"
name = fields.Many2one("yc.weight", "weight detail list", ondelete="cascade")
no = fields.Integer("row number")
the "no" is a field that I want to show number of row count.
my problem is :
how can I get get the number of rows?
since onchage decorated function can't get data from db.
I find a solution by myself and it is simple:
use depends decorator.
class YcWeightDetails(models.Model):
_name = "yc.weight.details"
name = fields.Many2one("yc.weight", "weight detail list", ondelete="cascade")
no = fields.Integer("row number")
compuute_no = fields.Integer("invisible field", compute= "_get_row_no")
create a field "compuute_no" to compute.
#api.depends("compuute_no")
def _get_row_no(self):
if self.ids:
count =1
for rec in self:
weight_id = self.env['yc.weight.details'].search([('id','=', rec.id)])
weight_id.write({'no': count})
count+=1
or overwrite create method
#api.model
def create(self, vals):
main_key = self.env["yc.weight"].search([], order="id desc", limit=1).id
item_key = vals["name"]
if item_key and main_key == item_key:
number = len(self.env["yc.weight.details"].search([("name", "=", item_key)]))
vals.update({"no": number + 1})
return super(YcWeightDetails, self).create(vals)
hope it can help you.

adding array as parameter to sql query in ruby

I have an array
ziparray = ["95626", "95645", "95837"]
I want to pass this to my sql query ,
sql = "SELECT * from table_name WHERE code in ($1);"
res1 = conn.exec(sql, [ziparray])
It does work for single values.
I am using pg gem and connecting to database using
conn = PG.connect()
I am using postgres and it doesn't take double quotes . I am assuming that to be the problem.
How to achieve this.
Update
I could convert to desired string using
str = "'"
str << ziparray.join("','")
str << "'"
#print str
But I guess the problem is passing of multiple parameters.
this works -
res1 = conn.exec(fipscodesql, ['95626'])
But not this
res1 = conn.exec(fipscodesql, ['95626', '95625'])
and this is exactly what I did when I converted the array to string. I guess this is not the right way to use parameters.
is there any other way.
As others said, you can't parametrise a whole array. Use this instead:
ziparray = ["95626", "95645", "95837"]
zip_placeholders = ziparray.map.with_index(1) { |_, i| "$#{i}" }.join(', ')
sql = "SELECT * from table_name WHERE code in (#{zip_placeholders});"
# => "SELECT * from table_name WHERE code in ($1, $2, $3)"
Then you can use the normal parameter binding.
[ziparray].map { |zip| "'#{zip}'" }.join(',')
SQL method "IN" doesn't use array.
So:
IN(234) - correct
IN(234,543) - correct
IN([234,543]) - wrong
You can try to convert array to string and pass variable $1 like '95626, 95645, 95837'
If x is an array and x = ['a','b','c']
quotes = (select * from quote in (?), x)
We cannot use this in a SQL parameter
x.join(',') returns "a,b,c". If it is int this is not a problem.
Instead, save this array in a variable and use it in a SQL parameter.
a = x and then use quotes = (select * from quote in (?),a)

In Ruby, how can I define a string with interpolated variables before those variables are defined?

In Ruby, how can I define a string with interpolated variables before those variables are defined?
What do I need to do to perform the interpolation once those variables have values assigned?
tips = 'Hi,#{name},your order total price is #{price*count}'
name = 'roy'
price = 13.5
count = 10
tips.xxx = 'Hi,roy,your order total price is 135'
In order to evaluate all between #{...} as Ruby code you must use double quotes, otherwise it'd just be printed as a commong String. And I guess you want to return something like 'Hi,roy,your order total price is 135', so, you need to create the name, price and count variables before, because if you don't do it then you'll get an undefined local variable or method 'variable' for main:Object error, so you could try:
name = 'roy'
price = 13.5
count = 10
tips = "Hi,#{name},your order total price is #{price*count}"
puts tips
# Hi,roy,your order total price is 135.0
For your case you can use late interpolation:
tips = 'Hi, %{name},your order total price is %{price}'
name = 'roy'
price = 13.5
count = 10
tips % {name: name, price: price * count}
# => "Hi,roy,your order total price is 135"
Link to documentation: https://ruby-doc.org/core-2.4.1/String.html#method-i-25

How to assign column name from variable

I want to assign a value to a table column. The column selected needs to be based on a variable. How do you do this?
If #language = "german" than I want to assign #new_word.german = string
#new_word = Word.new
#new_word.german = string
#new_word.save
So how would I assign .german using #language? #new_word.#language :/
x = "german"
#new_word.send("#{x}=", "some value")
#new_word[x] = "some value" # may end up skipping overrides/callbacks, etc though. check the docs.

Set array elements (string) as variable name in Ruby

I have the following array, that I use to later write the header on an Excel file.
fields = ["fileName", "type", "id"]
And then I have the following code that reads values from an XML:
filename = xml.xpath('//path/filename').text
type = xml.xpath('//path/type').text
id = xml.xpath('//path/id').text
The I iterate the initial array (fields) in order to set the Excel cells to the values extracted in the previous step:
row = 2
c = 1
fields.each do |content|
ws.Cells(row,c).Value = content
c = c + 1
I'm trying to have the array's (fields) contents to variable names instead of strings in order to be able to reuse the head fields.
Can anyone recommend a way of making it possible?
This sounds like you need to use a Hash to associate field names to the values you extracted:
fields = {
"fileName" => xml.xpath('//path/filename').text,
"type" => xml.xpath('//path/type').text,
"id" => xml.xpath('//path/id').text
}
row=2
c=1
fields.each do |key,value|
ws.Cells(row,c).Value = value
c=c+1
end

Resources