How to access Sequel result with dot operator in ruby? - ruby

I am newbie to Sequel and ruby and I have one thing need your help.
In a word, I can't access database query result with dot operator.
I am using sequel adapter in padrino ruby project.
For example,
persons = Person.all
persons.each do |p|
puts p.name . # this output correct person name, as 'john'
end
But if I do some query
persons = Person.where(:age=>20)
persons.each do |p|
puts p.name . # this line cause error
end
I compared their data types and there are different each other.
puts persons # in first case - array
#<Gig:0x007fbdb6d64ef0>
#<Gig:0x007fbdb6d64838>
#<Gig:0x007fbdb6d641f8>
puts persons # in second case - object
#<Sequel::Postgres::Dataset:0x007fbdbc614898>
So I tried to change result to hash array in second case to access fields with dot operator
persons_hash= persons.collect do |p|
ro.to_hash
end
In this case, I was able to access user name with person[0][:name], but I couldn't access with dot operator.
So I want to know how should I have to do to access Sequel query result using dot operator.
Thanks :)

persons.each do |p|
puts p.name . # this line cause error
end
What exact error are you getting here? I'm guessing an undefined method error? Seems you may be familiar with ActiveRecord syntax. I have not used sequel myself, but it is a bit different from AR. According to their docs, you would do something like this
persons.map(:name) # => ['Harry', 'Steve', 'Israel', ...]
The all method returns an array of hashes, where each hash corresponds to a record.
For your above example, I would try the following:
persons.each do |p|
puts p[:name] . # here we are now accessing the name hash key instead of trying to access the name method.
end
You want to access the name key of each hash being iterated over. Because you are iterating through an array OF hashes. This is why you could access that data with person[0][:name]. You were calling the 0th item of the persona array and accessing its 'name' hash key.

Related

Comparing values in two hashes

I am having trouble in comparing values in two hashes, getting the error "Can't convert String into Integer".
First hash has values captured from a web page using the method "capture_page_data(browser)" and the second hash has data parsed from a report.
Code looks like below:
# Open the web application
# Navigate to a specific page and capture page data
loan_data = Hash.new
loan_data = capture_page_data(browser)
Second hash has values captured from a report generated from the web application.
Code looks like below:
#report_data[page] = Hash.new
# we have written some logic to parse the data from the report into hash variable
Now I am trying to compare the values in theses two hashes to ensure the data in report is matching with the data in application using below code which is giving me the error "Can't convert String into Integer".
loan_data.map{|ld| ld['MainContent_cphContent_LoanOverViewGeneralInfoCtrl_lblRelName']} &
#report_data.map{|rd| rd['Relationship']}
Please help me out in resolving this issue.
Regards,
Veera.
Hash#map iterates through the hash like it was an array of key/value pairs.
{a:1,b:2}.map{|x| puts x.inspect }
# prints
# [:a,1]
# [:b,2]
{a:1,b:2}.map{|k,v| puts "#{k} => #{v}" }
# prints
# a => 1
# b => 2
It applies the block you provide to each pair and collects the results into a new array.
result = {a:1,b:2}.map{|k,v| "#{k} => #{v}" }
puts result.inspect
# prints
# [ "a => 1", "b => 2" ]
I would guess what you are trying to do is compare a single key from each array... in which case...
if loan_data[:id][:span]['MainContent_cphContent_LoanOverViewGeneralInfoCtrl_lblR‌​elName'] == #report_data[1]['Relationship']
log_message("pass")
else
log_message("fail")
end
might be what you are trying to do.. but I am only guessing.
It all depends on the shape of your data.
If you inspect the ld variable inside your block, you will find that it is an array. You can get an element of it with ld[0] or ld[1], but ld[string] does not make sense and results in the exception you are seeing. The ld array will actually be an array with two elements: key and value.
Thanks for your suggestions.. but I found a different solution to compare a single key from two hashes/Arrays using the below code which worked fine.
string_equals?(loan_data[:id][:span]['MainContent_cphContent_LoanOverViewGeneralInfoCtrl_lblRelName'], #report_data[1]['Relationship'] )
Thanks,
Veera.
It's best to debug the content of loan_data and #report_data directly, but you can try .to_sym to convert the key into symbol.
loan_data.map{|ld| ld['MainContent_cphContent_LoanOverViewGeneralInfoCtrl_lblRelName'.to_sym]} &
#report_data.map{|rd| rd['Relationship'.to_sym]}

Table column names to array in ruby

In Rails I would simply use:
MyModel.column_names
to access the tables column names, but I am enduring my first fumblings with Sinatra (in order to better learn Ruby) and need to get the column names of a table into an array.
Previously, I have iterated over the params hash to extract key, value pairs:
params.each do |key, value|
#manipulate keys and values
end
and know that using:
#mm = MyModel.new
#mm.each do ....
leads to an undefined method 'each' error.
logger.info #mm.inspect
logs something like:
#<MyModel #id=nil #start=nil #end=nil #yada=nil #created_at=nil #updated_at=nil #foreign_id=nil>
So, how do I get those blasted column names I can see so clearly into an array?
Thanks...
UPDATE
Thanks to Doon for pointing me in the right direction with Datamapper properties.
I ended up making a private method column_names:
def self.column_names
self.properties.collect {|column| column.name.to_s }
end
which works a treat
Are you looking for properties ?
http://rubydoc.info/gems/dm-core/1.1.0/DataMapper/Model/Property
For any Ruby object you have the methods instance_variables that returns the array of that object’s attributes. Is that too generic for you? I’m not familiar with DataMapper, there may be a specific method to do the equivalent of column_names in ActiveRecord.

Passing Hash values as parameters to methods in Ruby

I have a method met1 that takes hash values as parameters.
For example: met1('abc' => 'xyz')
What should be the syntax when I define the method? Can it be something like this?
def met1(options)
puts options
end
I know the above syntax works. But how can I access the individual hash key and value inside the met1? (where key is abc and value is xyz?) Thank you!
Thats easy
met1("abc" => "xyz")
def met1(options)
puts options
# with key
puts options["abc"]
end
I assume you know what the options might contain in terms of keys right? if not,
def met1(options)
puts options.keys # options is the hash you passed it, use it like one
end
Your syntax is correct. simply use options['key'] (in case 'key' is a string) in your method. It's customary to use symbols as keys, so in your example:
met1(:abc => 'xyz')
def met1(options)
puts options[:abc]
end

Can't convert String onto integer (TypeError)

Following code return error "Can't convert String onto integer", please help
subject = ['eng','Math','Sci']
grade = ['grade 1','grade 2','grade 3']
subject.each do |sub|
puts ("some string")
grade[sub] .each do |grd|
puts ("some string")
end
end
grade[sub] .each do |grd| thats the problem.
Array elements are accessed by using a index of integer or a range of integers.
You are trying to access a array element by using the variable stored in sub. Since this is a ordinary .each loop it will loop all the elements in the array, in this case 'eng','Math','Sci'. If you want the position of for example 'eng' you could use a .each_with_index
it should probably just be
grade.each do |grd|
with each_with_index it would be
subject.each_with_index do |sub, index|
print sub
print grade[index]
end
If you want a subject -> grade collection it might be good to look into using a Hash like Dave Newton said.
{"eng" => "grade 1","Math" => "grade 2","Sci" => "grade 3"}.each do |subject, grade|
puts "#{subject| #{grade}"
end
When you do
grade[sub] .each do |grd|
Ruby expects sub to be using an integer to reference a position in the list of grades.
subject and grade are both arrays. They can only be accessed by their position. In your each loop, the block gets the actual element (in sub), not the position. So in line 5, you are trying to access grade['eng'], which will not work and produces the error. Note that unlike in e.g. PHP, an array and a hash (an associative array) are different things.
Guessing from your code, you might want to use each_index instead of each which will pass the index number to the block instead of the element.
I'm not sure I understand what you're trying to achieve; however, if you'd like to print subjects and grades and you're sure about the relative order of elements in the arrays, you could do this:
subject = ['eng','Math','Sci']
grade = ['grade 1','grade 2','grade 3']
subject.each_with_index do |sub, idx|
puts "#{sub} - #{grade[idx]}"
end
Output:
eng - grade 1
math - grade 2
sci - grade 3
An hash is however probably more suitable to your needs.

ruby: search an multi-dimensional array for a value and update if needed

Trying to look through an array and see if a particular value is set and if it is, update the numbers attached to it.
Example:
test = [['test',1,2],['watch',1,2],['fish',1,2]]
So I'd like to search this array for 'test' - if it exists, amend the values '1,2', if it doesn't exist, just add the new search term into the array.
New to ruby and having trouble searching inside a multi-dimensional array and getting the key back
I'd go for the hash method suggested in the comments, but if you're really wanting to store your data in the multidimensional array like that I suppose you could do something like:
search_term = "test"
search_item= nil
test.each do |item|
if item.include? search_term
search_item = item
end
end
if search_item.nil?
test << [search_term]
else
search_item << [1,2]
end
I think that would do it (although I'm a little fuzzy on what you were wanting to do after you found the item).

Resources