Emptying a PostgreSQL text array column in Ruby on Rails - ruby-on-rails

data = {string1,string2}
The array data is fetched from PostgreSQL database that has a column of type text[] ie text array.
I need to empty this array.
OUTPUT:
data = {}
Can I use
tablename.update_attributes!(data: "")
OR
tablename.data.map!{ |e| e.destroy }
Context:
EMAILS.each do |email|
res = tablename.where('lower(email) = lower(?)',
"#{email}")
res.each do |u|
u.data.map! { |e| e.destroy } // this is where i want to empty the array
end
puts ""
end;
end;
I am very new in Rails. Can someone suggest something I can use?

Please, replace your line of code with this
u.data.map! { |e| e.update(data: []) }

The way to erase an array column is to set an empty array to it: data: []
You can use update_all to update all retrieved records at once:
EMAILS.each do |email|
tablename.where('lower(email) = lower(?)', email).update_all(data: [])
end

Related

Updating Ruby Hash Values with Array Values

I've created the following hash keys with values parsed from PDF into array:
columns = ["Sen", "P-Hire#", "Emp#", "DOH", "Last", "First"]
h = Hash[columns.map.with_index.to_h]
=> {"Sen"=>0, "P-Hire#"=>1, "Emp#"=>2, "DOH"=>3, "Last"=>4, "First"=>5}
Now I want to update the value of each key with 6 equivalent values from another parsed data array:
rows = list.text.scan(/^.+/)
row = rows[0].tr(',', '')
#data = row.split
=> ["2", "6", "239", "05/05/67", "Harp", "Erin"]
I can iterate over #data in the view and it will list each of the 6 values. When I try to do the same in the controller it sets the same value to each key:
data.each do |e|
h.update(h){|key,v1| (e) }
end
=>
{"Sen"=>"Harper", "P-Hire#"=>"Harper", "Emp#"=>"Harper", "DOH"=>"Harper", "Last"=>"Harper", "First"=>"Harper"
So it's setting the value of each key to the last value of the looped array...
I would just do:
h.keys.zip(#data).to_h
If the only purpose of h is as an interim step getting to the result, you can dispense with it and do:
columns.zip(#data).to_h
There are several ways to solve this problem but a more direct and straight forward way would be:
columns = ["Sen", "P-Hire#", "Emp#", "DOH", "Last", "First"]
...
#data = row.split
h = Hash.new
columns.each_with_index do |column, index|
h[column] = #data[index]
end
Another way:
h.each do |key, index|
h[key] = #data[index]
end
Like I said, there are several ways of solving the issue and the best is always going to depend on what you're trying to achieve.

Not able to place csv data in a Hash

I have a CSV file with two columns:
PPS_Id Amount
123 100
1234 150
I read data from this file and insert in a array using the code below:
CSV.foreach("filename.CSV", headers: true) do |row|
file_details << row.inspect # hash
end
I am then trying to push the data in the file_details into a hash with PPS_Id as key and Amount as Value, I am using the code below:
file_details_hash = Hash.new
file_details.each { |x|
file_details_hash[x['PPS_Id']] = x['Amount']
}
But when I print the result I get nothing just {"PPS_Id"=>"Amount"}
Can you please help
Your code, modified to work
You need to specify the column separator for your csv, and remove inspect.
require 'csv'
file_details = []
CSV.foreach("filename.CSV", headers: true, col_sep: "\s" ) do |row|
file_details << row
end
file_details_hash = Hash.new
file_details.each { |x|
file_details_hash[x['PPS_Id']] = x['Amount']
}
p file_details_hash
#=> {"123"=>"100", "1234"=>"150"}
It now returns what you expected to get.
Shorter solution
Read the csv, drop the first line (header) and convert to a Hash :
p CSV.read("filename.CSV", col_sep: "\s").drop(1).to_h
#=> {"123"=>"100", "1234"=>"150"}
First of all, you are collecting strings into an array (see String#inspect):
file_details << row.inspect
After that you call (sic!) String#[] on that strings:
x['PPS_Id'] #⇒ "PPS_Id", because string contains this substring
That said, your code has nothing but errors. You might achieve what you want with:
csv = CSV.parse(File.read("filename.CSV"), col_sep: "\s")
csv[1..-1].to_h
#⇒ {
# "123" => "100",
# "1234" => "150"
# }
Using inspect will save your CSV rows as strings, so obviously you won't be able get what you need. Instead try this:
file_details = CSV.read("filename.csv")
Read CSV directly will create an 2D array that you can then iterate over, which will look like this: [["PPS_Id", "Amount"], ["123", "100"], ["1234", "150"]]
From there you can slightly modify your approach:
file_details.each do |key, value|
file_details_hash[key] = value
end
To receive a hash like this: {"PPS_Id"=>"Amount", "123"=>"100", "1234"=>"150"}

How to format data Rails

I need to retrieve data from database column and put them to
[{1442507641,1},{1442507642,2},{1442507643,3},{1442507644,4}...]
format as the plot format requires.
I'm trying to do this by :
#data = TableName.where(:id => requiredid)
.map {|r| { r.received_date.to_i => r.value } }
but this returns format
data=[{1442507641=>6}, {1442507641=>7}, {1442507641=>5}, {1442507641=>6}, {1442507641=>5}, {1442507695=>9}, {1442507695=>9}, {1442507695=>7}, {1442507695=>8}]
How can I make the bracket as plot requires and remove the strange =&gt ?
It seems like this ought to do what you're asking for:
parts = TableName.where(:id => requiredid).map do |r|
sprintf("{%d,%d}", r.received_date, r.value)
end
#data = "[#{parts.join(",")}]"
It's only for your options to manipulate your data:
#data = []
#data = User.where(:id => requiredid).map {|r| #data << "{#{r. received_date}, #{r.value}}"}
First you make #data as array. Than collect the string into array.

How do I convert an array of hashes into a sorted hash?

If I have an array of hashes, each with a day key:
[
{:day=>4,:name=>'Jay'},
{:day=>1,:name=>'Ben'},
{:day=>4,:name=>'Jill'}
]
What is the best way to convert it to a hash with sorted day values as the keys:
{
:1=>[{:day=>1,:name=>'Ben'}],
:4=>[{:day=>4,:name=>'Jay'},{:day=>4,:name=>'Jill'}]
}
I'm using Ruby 1.9.2 and Rails 3.1.1
Personally, I wouldn't bother "sorting" the keys (which amounts to ordering-by-entry-time in Ruby 1.9) until I actually needed to. Then you can use group_by:
arr = [{:day=>4,:name=>'Jay'}, {:day=>1,:name=>'Ben'}, {:day=>4,:name=>'Jill'}]
arr.group_by { |a| a[:day] }
=> {4=>[{:day=>4, :name=>"Jay"}, {:day=>4, :name=>"Jill"}],
1=>[{:day=>1, :name=>"Ben"}]}
Instead, sort the keys when you actually need them.
Assuming you array is called is list, here's one way using the reduce method:
list.reduce({}) { |hash, item|
(hash[item[:day]] ||= []) << item; hash
}
Here's another using the map method, but you have to carry a holder variable around:
hash = {}
list.each { |item|
(hash[item[:day]] ||= []) << item
}
Once you have the unsorted hash say in variable foo, you can sort it as,
Hash[foo.sort]
Simple answer:
data = [
{:day=>4,:name=>'Jay'},
{:day=>1,:name=>'Ben'},
{:day=>4,:name=>'Jill'}
]
#expected solution
sol = {
1=>[{:day=>1,:name=>'Ben'}],
4=>[{:day=>4,:name=>'Jay'},{:day=>4,:name=>'Jill'}]
}
res = {}
data.each{|h|
res[h[:day]] ||= []
res[h[:day]] << h
}
p res
p res == sol #check value
p res.keys == sol.keys #check order
Problem with this solution: The hash is not sorted as requested. (Same problem has Anurags solution).
So you must modify the answer a bit:
res = {}
data.sort_by{|h| h[:day]}.each{|h|
res[h[:day]] ||= []
res[h[:day]] << h
}
p res
p res == sol #check value
p res.keys == sol.keys #check order
In Rails you can use OrderedHash:
ActiveSupport::OrderedHash[arr.group_by { |a| a[:day] }.sort_by(&:first)]
Update: In fact in Ruby 1.9 hash is ordered, so using ActiveSupport extension is not required:
Hash[arr.group_by { |a| a[:day] }.sort_by(&:first)]

Rails :: Why the attribute change doesn't persist?

Controller:
#events = Event.all
#events.each { |e| e.user_subscribed = "someuser" }
#events.each { |e| puts "error" + e.user_subscribed }
I have attr_accessor :user_subscribed. but the error is can't convert nil into String as e.user_subscribed evaluates to nil.
I'm using mongoid on the backend.
edit: this works, but it just copies the whole array.
#events = #events.map do |e|
e.user_subscribed = "faaa"
e
end
If you're not saving the #events to the database, user_subscribed won't persist, unless you keep it in memory:
#events_with_subscription = #events.map { |e| e.user_subscribed = "someuser"; return e }
edited based on OP comments.
sounds like it might be better to just output Event.user_subscribed(current_user) directly in the view...but if you wanted to load up all that data before hand you could do:
#array_of_subscription_results = #Events.map{|e| e.user_subscribed(current_user,some,other,var,required) }
As long as user_subscribed returns the values you are interested in, thats what map will load into #array_of_subscription_results

Resources