How to search in nested jsonb column in Rails.
Model: Shop
jsonb column: shop_data
shop_data: {
common_data: {
"image_url" => "https://sample.com/img.jpg"
"token" => "AOsa2123ASDasdaasasda"
"uid" => ""
"expires_at" => ""
}
}
Wanna make a scopes that will checks for records where:
1. shop_data->common_data->expires_at IS NOT NULL
2. shop_data->common_data->image_url IS NULL
1. scope :expired, -> { where("shop_data -> 'common_data' ->> 'expires_at' IS NOT NULL") }
2. scope :null_image, -> { where("shop_data -> 'common_data' ->> 'image_url' IS NULL") }
source JSON functions in postgres
Hope it helps
The following query works as expected:
Purchase.all.group( :user_id ).sum( :price )
It returns an array of hashes:
[{ 1 : 234 }, ...
Is there a way to return an array of hashes with keys?
[{ id : 1, price : 234 }, ...
You can return an ActiveRecord::Relation with a single query.
Purchase.select("user_id as id, sum(price) as price").group("user_id")
I believe this will do:
Purchase.all.group(:user_id).sum(:price).map do |k, v|
{
id: k.keys.pop,
price: k.values.pop
}
end
Although a bit hacky, works.
Hello I wanted to create a hash that would be append the email with name if that name exist in someother hash. I believe there would be small piece of code that will do the ruby magic.
Input
a = [
{"email"=>"foobar#gmail.com", "name"=>"Adam"},
{"email"=>"test#gmail.com", "name"=>"John"},
{"email"=>"hello#gmail.com", "name"=>"Adam"}
]
Output
a = [
{"email"=>"foobar#gmail.com", "name"=>"Adam | foobar#gmail.com"},
{"email"=>"test#gmail.com", "name"=>"John"},
{"email"=>"hello#gmail.com", "name"=>"Adam | hello#gmail.com "}
]
Here's another option:
# get names
names = a.map {|e| e['name'] }
# find duplicates
duplicates = names.detect {|e| names.count(e) > 1 }
# append email to duplicates
a.each { |e| e['name'] = "#{e['name']} | #{e['email']}" if duplicate.include?(e['name'])}
Given your input
a = [
{"email"=>"foobar#gmail.com", "name"=>"Adam"},
{"email"=>"test#gmail.com", "name"=>"John"},
{"email"=>"hello#gmail.com", "name"=>"Adam"}
]
And I'll provide a cleverly named comparison hash of my own
b = [
{"name"=>"Adam"},
{"name"=>"Adam"}
]
Here's your ruby magic
a.map do |hash_a|
# This is the 'magic' line that compares the values of
# the two hashes name values
if b.any? { |hash_b| hash_b['name'] == hash_a['name'] }
hash_a['name'] << " | #{hash_a['email']}"
hash_a
else
hash_a
end
end
Output:
[
{
"email" => "foobar#gmail.com",
"name" => "Adam | foobar#gmail.com"
},
{
"email" => "test#gmail.com",
"name" => "John"
},
{
"email" => "hello#gmail.com",
"name" => "Adam | hello#gmail.com"
}
]
I am using the sqlite3 adapter for Ruby and getting some strange behavior. I am using ? to escape input into my queries. The following works:
db.execute 'SELECT * FROM table_name WHERE id = ?', 1
=> [{ "id"=> 1, "name" => "Hannah" }]
db.execute 'SELECT * FROM table_name WHERE name = ?, 'Hannah'
=> [{ "id"=> 1, "name" => "Hannah" }]
db.execute 'SELECT * FROM table_name WHERE id = 1 AND name = ?', 'Hannah'
=> [{ "id"=> 1, "name" => "Hannah" }]
The following, however, does not work:
db.execute 'SELECT * FROM table_name WHERE id = ? AND name = ?', 1, 'Hannah'
=> []
Why is this?
If I have an array like this
["Member", "Friends", "Hello", "Components", "Family", "Lastname"]
and I need to split it at "Components" and get 2 arrays, which are
["Member", "Friends", "Hello"]
and
["Family", "Lastname"]
Can I do that and how?
You can use Array#slice:
class Array
def msplit(m)
idx = self.index(m)
idx ? [self[0..idx-1], self[idx+1..-1]] : nil
end
end
arr = ["Member", "Friends", "Hello", "Components", "Family", "Lastname"]
a, b = arr.msplit("Components")
a # => ["Member", "Friends", "Hello"]
b # => ["Family", "Lastname"]
a.msplit("Foo") # => nil
In ruby 1.9 (because of chunk method):
array = ["Member", "Friends", "Hello", "Components", "Family", "Lastname"]
a, b = array.chunk {|e| e != "Components"}.map {|a, b| b if a}.compact
p a, b #=> ["Member", "Friends", "Hello"] ["Family", "Lastname"]
May be by
i = ary.index["Components"] - 1
ary[0..i] #=>["Member", "Friends", "Hello"]
i = ary.index["Components"] + 1
ary[i..ary.length] #=>["Family", "Lastname"]
or
ary[0..ary.index["Components"]-1] #=>["Member", "Friends", "Hello"]
ary[ary.index["Components"]+1..ary.length] #=>["Family", "Lastname"]
Also can use:
i = ary.index["Components"] - 1
ary.take(i) #=>["Member", "Friends", "Hello"]
newArray = oldArray.slice(5,2)
use the index and length methods to work out the 5 and 2 values
should leave you with:
newArray ["Family", "Lastname"]
oldArray ["Member", "Friends", "Hello"]
see the doc here: http://www.ruby-doc.org/core-1.8.3/classes/Array.html#M000398
As an method:
class Array
def split_by(val)
[0, a.index(val)], a[a.index(val)+1..-1]
end
end
array = ["Member", "Friends", "Hello", "Components", "Family", "Lastname"]
first, second = array.split_by("Complonents")
first
#=> ["Member", "Friends", "Hello"]
second
#=> ["Family", "Lastname"]
or inliner
array = ["Member", "Friends", "Hello", "Components", "Family", "Lastname"]
first, second = array[0, a.index("Components")], a[a.index("Components")+1..-1]