ruby/rails - Given two Hashes how to exchange items? - ruby-on-rails

I have the following hashes:
#valids
[
{
:lname => "Brown",
:email => "james#intuit.com",
:fname => "James"
},
{
:lname => "Smith",
:email => "brad#intuit.com",
:fname => "Brad"
}
]
#invalids
[
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
},
{
:lname => nil,
:email => "roger#gmail.com",
:fname => nil
}
]
What I'm going to be doing is looping through the invalids, and if an email meets a certain criteria, I want to move that item to valids and then remove it from invalids.
Example, while looping through #invalids, if the email = roger#gmail.com, I want to take:
{
:lname => nil,
:email => "roger#gmail.com",
:fname => nil
}
And move it to #valids, and remove it from #invalids.
Is there a way to do this without having to create new hashes? Thanks

This should do it:
#invalids = #invalids.reject do |record|
if record[:email] == "roger#gmail.com"
#valids.push(record)
end
end
To explain it a little bit, I'm setting #invalids as the result of running
#invalids.reject and passing it a block, so it will reject any array item that meets the criteria (returns something truish).
Inside the conditional I add to the #valids array

Related

How to convert mongoid criteria to array?

I have a mongoid criteria categories and I need to convert to an array. I'm using categories.to_a but this dont works and always that the mongoid criteria is iterate by .map it's doing a .find a new query.
How can I fix this?
def self.mapOffers (array, user)
array.map { |u|
{
:id => u.id.to_s,
:name => u.name,
:description => u.description,
:price => u.price,
:url => u.url,
:categories => Category.mapCategories(u.categories.to_a, user),
:picture => u.picture.url,
:accepts_cash => u.accepts_cash_transactions,
:location => {
:longitude => u.longitude,
:latitude => u.latitude,
:street => u.street,
:neighborhood => u.neighborhood,
:number => u.number,
:zip => u.zip,
:city => u.city,
:state => u.state,
:complement => u.complement,
:country => u.country,
},
:fixedMeetingPoint => u.fixedMeetingPoint,
:meetingPoint => {
:street => u.meetingPointStreet,
:neighborhood => u.meetingPointNeighborhood,
:number => u.meetingPointNumber,
:zip => u.meetingPointZip,
:city => u.meetingPointCity,
:state => u.meetingPointState,
:complement => u.meetingPointComplement,
:country => u.meetingPointCountry,
:latitude => u.meetingPointLatitude,
:longitude => u.meetingPointLongitude,
},
:notes => u.notes,
}}
end
def self.mapCategories (array, user)
array.map { |u| {
:id => u.id.to_s,
:name => u.name,
:selected => !user.nil? && u.users.include?(user),
:picture => u.picture.url,
}}
end
Starting from criteria:
scope = Band.where(name: 'foo')
... retrieve the complete result set from the database and store in an array:
bands = scope.to_a
... then iterate the array any number of times:
bands.each { |band| ... }
bands.each { |band| ... }

ARRAY ACCESS AND INSERTION RECORD DATABASE

I would need to access the array to retrieve the information and insert it into the database (Code, Customer, Phone1, Phone2). Someone can help me?
{
:recordset => {
:row => [
[0] {
:property => [
[0] {
:name => "Code",
:value => "C0001"
},
[1] {
:name => "Customer",
:value => "ROSSI MARIO"
},
[2] {
:name => "Phone1",
:value => "1234567890"
}
]
},
[1] {
:property => [
[0] {
:name => "Code",
:value => "C0002"
},
[1] {
:name => "Customer",
:value => "VERDE VINCENT"
},
[2] {
:name => "Phone1",
:value => "9876543210"
},
[3] {
:name => "Phone2",
:value => "2468101214"
}
]
}
]
},
:#xmlns => "http://localhost/test"
}
p.s. The Phone2 value during the SOAP call is only displayed if it is present in an archive
Thank you
Your data doesn't look like a valid ruby structure. Once you are able to convert it to be more ruby-like, you can make use of each_with_object to generate a well formatted set of attributes and their values from your data:
data
=> {:recordset=>{
:row=>[{
:property=>[
{:name=>"Code", :value=>"C0001"},
{:name=>"Customer", :value=>"ROSSI MARIO"},
{:name=>"Phone1", :value=>"1234567890"}
]
}, {
:property=>[
{:name=>"Code", :value=>"C0002"},
{:name=>"Customer", :value=>"VERDE VINCENT"},
{:name=>"Phone1", :value=>"9876543210"},
{:name=>"Phone2", :value=>"2468101214"}
]
}]
},
:#xmlns=>"http://localhost/test"}
data.keys
=> [:recordset, :#xmlns]
data[:recordset][:row].count
=> 2 # There are 2 set of attribute-value pairs
result = data[:recordset][:row].each_with_object([]) do |hash, out|
out << hash[:property].each_with_object({}) do |h, o|
o[h[:name]] = h[:value]
end
end
=> [{"Code"=>"C0001", "Customer"=>"ROSSI MARIO", "Phone1"=>"1234567890"},
{"Code"=>"C0002", "Customer"=>"VERDE VINCENT", "Phone1"=>"9876543210", "Phone2"=>"2468101214"}]
Now, you can iterate over result and create respective records in database.

Activerecord map to array

I'm trying to take everything out of my Users table and send it to mail chimp for subscription.
I need to go from User.all to
[{:email => {:email => "example#domain.org"},
:merge_vars => {:FNAME => "First name", :LNAME => "Last name"}
}]
I'm trying to do this with map but I'm struggling, any ideas of the cleanest way of doing this?
subscription_array = User.all.collect do |user|
{
:email => {:email => user.email},
:merge_vars => {:FNAME => user.first_name, :LNAME => user.last_name}
}
end
users_array = []
User.all.find_each {|u| users_array << {:email => u.email, :merge_vars => {:FNAME => u.first_name, :LNAME => u.last_name} }
I chose to use find_each is it's a more efficient way of loading your collection.
http://api.rubyonrails.org/classes/ActiveRecord/Batches.html

How to remove duplicates in a hash in Ruby on Rails?

I have a hash like so:
[
{
:lname => "Brown",
:email => "james#intuit.com",
:fname => "James"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad#intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad#intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
}
]
What I would like to learn how to do is how to remove a record if it is duplicate. Meaning, see how there are several "brad#intuit.com" how can I remove the duplicate records, meaning remove all the others that have an email of "brad#intuit.com".... Making email the key not the other fields?
In Ruby 1.9.2, Array#uniq will accept a block paramater which it will use when comparing your objects:
arrays.uniq { |h| h[:email] }
I know this is an old thread, but Rails has a method on 'Enumerable' called 'index_by' which can be handy in this case:
list = [
{
:lname => "Brown",
:email => "james#intuit.com",
:fname => "James"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad#intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad#intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
}
]
Now you can get the unique rows as follows:
list.index_by {|r| r[:email]}.values
To merge the rows with the same email id.
list.group_by{|r| r[:email]}.map do |k, v|
v.inject({}) { |r, h| r.merge(h){ |key, o, n| o || n } }
end
Custom but efficient method:
list.inject({}) do |r, h|
(r[h[:email]] ||= {}).merge!(h){ |key, old, new| old || new }
r
end.values
If you're putting this directly into the database, just use validates_uniqueness_of :email in your model. See the documentation for this.
If you need to remove them from the actual hash before being used then do:
emails = [] # This is a temporary array, not your results. The results are still in my_array
my_array.delete_if do |item|
if emails.include? item[:email]
true
else
emails << item[:email]
false
end
end
UPDATE:
This will merge the contents of duplicate entries
merged_list = {}
my_array.each do |item|
if merged_list.has_key? item[:email]
merged_list[item.email].merge! item
else
merged_list[item.email] = item
end
end
my_array = merged_list.collect { |k, v| v }
Ok, this (delete duplicates) is what you asked for:
a.sort_by { |e| e[:email] }.inject([]) { |m,e| m.last.nil? ? [e] : m.last[:email] == e[:email] ? m : m << e }
But I think this (merge values) is what you want:
a.sort_by { |e| e[:email] }.inject([]) { |m,e| m.last.nil? ? [e] : m.last[:email] == e[:email] ? (m.last.merge!(e) { |k,o,n| o || n }; m) : m << e }
Perhaps I'm stretching the one-liner idea a bit unreasonably, so with different formatting and a test case:
Aiko:so ross$ cat mergedups
require 'pp'
a = [{:fname=>"James", :lname=>"Brown", :email=>"james#intuit.com"},
{:fname=>nil, :lname=>nil, :email=>"brad#intuit.com"},
{:fname=>"Brad", :lname=>"Smith", :email=>"brad#intuit.com"},
{:fname=>nil, :lname=>nil, :email=>"brad#intuit.com"},
{:fname=>"Brad", :lname=>"Smith", :email=>"brad#intuit.com"},
{:fname=>"Brad", :lname=>"Smith", :email=>"brad#intuit.com"}]
pp(
a.sort_by { |e| e[:email] }.inject([]) do |m,e|
m.last.nil? ? [e] :
m.last[:email] == e[:email] ? (m.last.merge!(e) { |k,o,n| o || n }; m) :
m << e
end
)
Aiko:so ross$ ruby mergedups
[{:email=>"brad#intuit.com", :fname=>"Brad", :lname=>"Smith"},
{:email=>"james#intuit.com", :fname=>"James", :lname=>"Brown"}]

in ruby, how do you make this nested hash work?

this one creates an error:
#settings = {
:tab1 => {
:name => {
:required => true
},
:description
}
}
need to change :descrpition to :description => {}, but i don't have any values for :description so i want it to remain as is (without the empty => {})
Would you show me the best way to handle this kind of situation?
thanks in advance
You can assign nil to it.
#settings = {
:tab1 => {
:name => {
:required => true
},
:description => nil
}
}
Ruby's Hash prior to 1.9 is not ordered, and even afterwards it's a bit clumsy, as AFAIK you can't reorder items etc., so if you also want to preserve the order of the elements, you may consider using array instead of hash:
#settings = {
:tab1 => [
{
:field => :name,
:required => true
},
{
:field => :description
}
]
}

Resources