Building SQL statements using array entries - ruby

What is the proper way to build a string dynamically using items from an array. Currently I am building it using this;
#ar.each do |b|
#str = #str + "select '#{b[0]}' as SourceGUID, '#{b[1]}' as SourceFileName, '#{b[2]}' as FullPath, #{b[3]} as SizeInMB, #{b[4]} as ItemCount, #{b[5]} as ParentCount, #{b[6]} as ChildCount, '#{b[7]}' as CaseName, #{b[8]} as ProcessedSizeMB\n union all\n"
end
This is obviously a horrible way to do it. Is there a way to achieve it using .join?

A draft
2.3.1 :028 > row = %w(my_id my_name my_age)
=> ["my_id", "my_name", "my_age"]
2.3.1 :029 > aliases = %w(id name age)
=> ["id", "name", "age"]
2.3.1 :030 > fields = row.zip aliases
=> [["my_id", "id"], ["my_name", "name"], ["my_age", "age"]]
2.3.1 :031 > fields.map do |field|
2.3.1 :032 > field[0] = "'#{field[0]}'"
2.3.1 :033?> field.join(" AS ")
2.3.1 :034?> end.join(", ")
=> "'my_id' AS id, 'my_name' AS name, 'my_age' AS age"

Related

How do I copy contents into a hash without changing the memory address to which that hash points?

I'm using Ruby 2.4. I'm confused about the whole reference vs value thing when copying the contents of a hash. How do I copy the contents of one hash into another without changing the reference (memory address?) of the hash? Below is the example of the problem I'm having ....
2.4.0 :003 > def copy_hash(h)
2.4.0 :004?> new_hash = {"a" => 1}
2.4.0 :005?> h = new_hash
2.4.0 :006?> end
=> :copy_hash
2.4.0 :007 > h = {"b" => 2}
=> {"b"=>2}
2.4.0 :008 > copy_hash(h)
=> {"a"=>1}
2.4.0 :009 > h
=> {"b"=>2}
In the function, I'm assigning the parameter to a new hash ...
h = new_hash
But once the function returns the original hash is unchanged. What's the right way to change the hash in the function so that when it returns the value of the parameter is also changed? That is, if my hash started out as
{"b" => 2}
I'd like the value to be
{"a"=>1}
after I invoke the "copy_hash" function.
You can use Hash#replace to replace the contents of the hash:
def copy(h)
new_hash = { 'a' => 1 }
h.replace(new_hash)
end
h = { 'b' => 2 }
copy(h)
h == { 'a' => 1 } # => true

In a CSV, how do I loop through column names and get their position in the header row?

I have a CSV file that looks something like this:
ID,Name,Age
1,John,99
I've required csv in my Ruby script.
But using CSV, how do I loop thru the header row? How do I find the position number for ID,Name and Age?
After copying your data to a file x.csv, I executed the following in irb:
2.3.0 :009 > require 'csv'
=> false
2.3.0 :010 > csv = CSV.read 'x.csv'
=> [["ID", "Name", "Age"], ["1", "John", "99"]]
2.3.0 :010 > csv = CSV.read 'x.csv'
=> [["ID", "Name", "Age"], ["1", "John", "99"]]
2.3.0 :011 > header_line = csv[0]
=> ["ID", "Name", "Age"]
2.3.0 :012 > header_line[0]
=> "ID"
2.3.0 :013 > header_line[1]
=> "Name"
2.3.0 :014 > header_line[2]
=> "Age"
...so this is one way you can do it; use read to get an array of arrays, and assume the first is an array of column headings.
In the real world you probably won't want to read the entire file into memory at once and would use CSV.foreach:
#!/usr/bin/env ruby
data = []
CSV.foreach('x.csv') do |values_in_row|
if #column_names # column names already read; this must be a data line
data << values_in_row # just an example
# do something with values_in_row
else
#column_names = values_in_row
end
end
puts "Column names are: #{#column_names.join(', ')}"
puts "Data lines are:"
puts data

How to evaluate a member inside a hash that is a list

I've the following Hash (dummy{}) with one member being an array, how do I build a code logic to:
(a) evaluate each Key -> Value
(b) evaluate each Key -> values(s) (if it is an array inside a Hash)
dummy = { :a1 => "xyz",
:b1 => ["xyz1", "ayz2", "xyz3", "xyz4"] }
The code I've for a Key with just one value is:
eval(dummy)[a1.to_sym]
I need a clean way to evaluate a hash member that has multiple values in an array.
Here is the IRB output:
1.9.3-p327 :002 > dummy = { :a1 => "xyz",
1.9.3-p327 :003 > :b1 => ["xyz1", "ayz2", "xyz3", "xyz4"] }
=> {:a1=>"xyz", :b1=>["xyz1", "ayz2", "xyz3", "xyz4"]}
Now I can access the members and their Key-Value pairs (in a very simple way as below:)
1.9.3-p327 :005 > pp dummy[:a1.to_sym]
"xyz"
=> "xyz"
1.9.3-p327 :006 > pp dummy[:b1.to_sym][0]
"xyz1"
=> "xyz1"
1.9.3-p327 :007 > pp dummy[:b1.to_sym][1]
"ayz2"
=> "ayz2"
1.9.3-p327 :008 > pp dummy[:b1.to_sym][2]
"xyz3"
=> "xyz3"
1.9.3-p327 :009 > pp dummy[:b1.to_sym][3]
"xyz4"
=> "xyz4"
Now, I need a "generic" ruby code that takes care of both the above situations to access the members and their values - note: for example, I only selected 1 and 4 values, but in reality my need is where the values range from 1000 - 5000
Making sure everything is an Array allows for uniform treatment:
dummy = { :a1 => "xyz",
:b1 => ["xyz1", "ayz2", "xyz3", "xyz4"] }
dummy.each do |k, v|
Array(v).each do |element| #Array(v) puts v in an Array, unless it already is an array.
puts element
end
puts
end

Prepared Statements Already Exists

I am trying to use the prepared statements in ruby with pg gem. This is how my statement looks like
conn.prepare("insert_values", "insert into " + objectName + "(" + headerStr + ") values (" + prep_values + ")")
conn.exec_prepared("insert_values", arr)
I keep getting the error
Prepared Statement insert_values already exists.
How Do i Fix this?? Thanks
Try to run:
conn.exec("DEALLOCATE name_of_prepared_statement")
In your example:
conn.exec("DEALLOCATE insert_values")
Simple test and it is working in my irb:
1.8.7 :001 > require 'rubygems'
=> true
1.8.7 :002 > require 'pg'
=> true
1.8.7 :003 > conn = PGconn.connect(:host => 'localhost', :port => 5912, :user => 'test', :dbname => 'test' )
=> #<PGconn:0x7fe6ac703970>
1.8.7 :005 > conn.prepare("insert_values", "select * from data where id < $1")
=> #<PGresult:0x7fe6ac6b2e58>
1.8.7 :006 > conn.prepare("insert_values", "select * from data where id < $1 and id > $2")
PGError: ERROR: prepared statement "insert_values" already exists
from (irb):6:in 'prepare'
from (irb):6
1.8.7 :007 > conn.prepare("insert_values", "select * from data where id < $1")
PGError: ERROR: prepared statement "insert_values" already exists
from (irb):7:in 'prepare'
from (irb):7
1.8.7 :008 > conn.exec("DEALLOCATE insert_values")
=> #<PGresult:0x7fe6ac6738c0>
1.8.7 :009 > conn.prepare("insert_values", "select * from data where id < $1")
=> #<PGresult:0x7fe6ac665fe0>
1.8.7 :010 > conn.exec_prepared("insert_values",[200])
=> #<PGresult:0x7fe6ac65d188>
1.8.7 :011 > conn.exec("DEALLOCATE insert_values")
=> #<PGresult:0x7fe6ac654df8>
1.8.7 :012 > conn.exec_prepared("insert_values",[200])
PGError: ERROR: prepared statement "insert_values" does not exist
from (irb):12:in 'exec_prepared'
from (irb):12
This is a better way reusing prepare(), avoid prepared statement "my_statement" already exists:
sql = "select * from my_table where id = $1"
begin
ActiveRecord::Base.connection.raw_connection.prepare('my_statement', sql)
rescue PG::DuplicatePstatement => e
end
pg_result = ActiveRecord::Base.connection.raw_connection.exec_prepared('my_statement', [my_table_id])

Using Tuples in Ruby?

Does anyone use tuples in Ruby? If so, how may one implement a tuple? Ruby hashes are nice and work almost as well, but I'd really like to see something like the Tuple class in Python, where you can use . notation to find the value for which you are looking. I'm wanting this so that I can create an implementation of D, similar to Dee for Python.
OpenStruct?
Brief example:
require 'ostruct'
person = OpenStruct.new
person.name = "John Smith"
person.age = 70
person.pension = 300
puts person.name # -> "John Smith"
puts person.age # -> 70
puts person.address # -> nil
Based on the fact that you talk about hashes and . notation I'm going to assume you mean a different kind of tuple than the (1. "a") sort. You're probably looking for the Struct class. eg:
Person = Struct.new(:name, :age)
me = Person.new
me.name = "Guy"
me.age = 30
While this isn't strictly a tuple (can't do dot notation of members), you can assign a list of variables from a list, which often will solve issues with ruby being pass-by-value when you are after a list of return values.
E.g.
:linenum > (a,b,c) = [1,2,3]
:linenum > a
=> 1
:linenum > b
=> 2
:linenum > c
=> 3
Arrays are cool to use as tuples because of destructuring
a = [[1,2], [2,3], [3,4]]
a.map {|a,b| a+b }
Struct give you convenient . accessors
Person = Struct.new(:first_name, :last_name)
ppl = Person.new('John', 'Connor')
ppl.first_name
ppl.last_name
You can get the convenience of both worlds with to_ary
Person = Struct.new(:first_name, :last_name) do
def to_ary
[first_name, last_name]
end
end
# =>
[
Person.new('John', 'Connor'),
Person.new('John', 'Conway')
].map { |a, b| a + ' ' + b }
# => ["John Connor", "John Conway"]
I'm the author of Gem for Ruby tuples.
You are provided with two classes:
Tuple in general
Pair in particular
You can initialize them in different ways:
Tuple.new(1, 2)
Tuple.new([1, 2])
Tuple(1, 2)
Tuple([1, 2])
Tuple[1, 2]
Both of the classes have some auxiliary methods:
length / arity - which returns number of values inside tuple
first / last / second (only pair) - which returns a corresponding elements
[] that gives you an access to a particular elements
You can mock the Scala tuples with this trick :
Tuple = Struct.new(:_1, :_2)
2.2.5 :003 > t = Tuple.new("a", "b")
=> #<struct Tuple _1="a", _2="b">
2.2.5 :004 > t._1
=> "a"
2.2.5 :005 > t._2
=> "b"
but here you can't have destructuring:
2.2.5 :012 > a, b = t
=> {:_1=>"a", :_2=>"b"}
2.2.5 :013 > a
=> {:_1=>"a", :_2=>"b"}
2.2.5 :014 > b
=> nil
But thanks to this trick : https://gist.github.com/stevecj/9ace6a70370f6d1a1511
destructuring will work:
2.2.5 :001 > Tuple = Struct.new(:_1, :_2)
=> Tuple
2.2.5 :002 > t = Tuple.new("a", "b")
=> #<struct Tuple _1="a", _2="b">
2.2.5 :003 > t._1
=> "a"
2.2.5 :004 > class Tuple ; def to_ary ; to_a ; end ; end
=> :to_ary
2.2.5 :005 > a, b = t
=> #<struct Tuple _1="a", _2="b">
2.2.5 :006 > a
=> "a"
2.2.5 :007 > b
=> "b"
You can do something similiar with destructuring:
def something((a, b))
a + b
end
p something([1, 2])
This prints out 3 as expected.

Resources