Group orderring - ruby-on-rails

I am looking to group a list of projects by a nested field, in this case custom_field.value when a certain id is passed in.
[{
id: 1,
name: "project one ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2010"
},
{
id: 5,
name: "Priority",
value: "low"
},
]},
{
id: 2,
name: "project two ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2011"
},
{
id: 5,
name: "Priority",
value: "medium"
},
]},
{
id: 3,
name: "project three ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2012"
},
{
id: 5,
name: "Priority",
value: "high"
},
]}]
So if the params[:id] == 4 I want the list to be ordered by the custom_field id's corresponding value in decending order.
So in this case they would be ordered.
2012
2011
2010
Any ideas?

Is this what you are looking for? Your question is a bit unclear but I think this should suffice:
Your Original Hash:
test = [{
id: 1,
name: "project one ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2010"
},
{
id: 5,
name: "Priority",
value: "low"
},
]},
{
id: 2,
name: "project two ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2011"
},
{
id: 5,
name: "Priority",
value: "medium"
},
]},
{
id: 3,
name: "project three ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2012"
},
{
id: 5,
name: "Priority",
value: "high"
},
]}]
Use group_by and sort(with handling for elements where there is no id found):
def group_and_sort(test_hash,id)
test_hash.group_by do |g|
elem = g[:custom_fields].detect {|h| h[:id] == id}
elem ? elem[:value] : "0"
end.sort.reverse.to_h
end
Then call like:
group_and_sort(test,4)
#=>{"2012"=>
[{:id=>3,
:name=>"project three ",
:custom_fields=>
[{:id=>4, :name=>"Year", :value=>"2012"},
{:id=>5, :name=>"Priority", :value=>"high"}]}],
"2011"=>
[{:id=>2,
:name=>"project two ",
:custom_fields=>
[{:id=>4, :name=>"Year", :value=>"2011"},
{:id=>5, :name=>"Priority", :value=>"medium"}]}],
"2010"=>
[{:id=>1,
:name=>"project one ",
:custom_fields=>
[{:id=>4, :name=>"Year", :value=>"2010"},
{:id=>5, :name=>"Priority", :value=>"low"}]}]}

Assume projects is the data you pasted.
def order_values_by_id(pjs, id)
pjs.map{|p| p[:custom_fields].find{|f| f[:id] == id}[:value] }.sort.reverse
end
order_values_by_id(projects)
#=> ["2012", "2011", "2010"]

Related

How to apply a group by for an array property

I need to group the data by sub categories, but the property is an array.
I'll appreciate your help, since I'm not good with sql.
Example
const data = [
{
title: "data 1",
sub_categories:[{ id: 1, name: 'gold'},{ id: 2, name: 'water' }]
},
{
title: "data 2",
sub_categories:[{ id: 2, name: 'water'}]
},
{
title: "data 3",
sub_categories:[{ id: 1, name: 'gold'},{ id: 3, name: 'fire' }]
},
{
title: "data 4",
sub_categories:[] // also can be empty
}
]

Get objects only within one array and not multiple arrays within an array

Sorry for the bad English Title but the code below would make more sense.
I used .each to get some keys and values that I wanted from the data but when I do it I get this result.
[
[
{
id: 1,
name: "Immad",
age: 18
}
],
[
{
id: 2,
name: "Vicky",
age: 21
}
],
[
{
id: 3,
name: "Adam",
age: 24
}
]
]
I want to map the objects to some js library for which I want it to be like:
[
{
id: 1,
name: "Immad",
age: 18
},
{
id: 2,
name: "Vicky",
age: 21
},
{
id: 3,
name: "Adam",
age: 24
}
]
Can anybody please atleast give me hint what should I use in order to do it using ruby. Thanks in advance.
There already is an Array method.
foo_array.flatten!
or non destructive (just a return value foo_array remains unchanged)
foor_array.flatten
Simple, You should do like this
Test = [[{:id=>1, :name=>"Immad", :age=>18}], [{:id=>2, :name=>"Vicky", :age=>21}], [{:id=>3, :name=>"Adam", :age=>24}]]
Use .flatten here.
Test.flatten
=> [{:id=>1, :name=>"Immad", :age=>18}, {:id=>2, :name=>"Vicky", :age=>21}, {:id=>3, :name=>"Adam", :age=>24}]
Use .map!:
foo = [
[
{
id: 1,
name: "Immad",
age: 18
}
],
[
{
id: 2,
name: "Vicky",
age: 21
}
],
[
{
id: 3,
name: "Adam",
age: 24
}
]
]
# Call .map! on the array
foo.map! { |array| array.first }
=> [
[0] {
:id => 1,
:name => "Immad",
:age => 18
},
[1] {
:id => 2,
:name => "Vicky",
:age => 21
},
[2] {
:id => 3,
:name => "Adam",
:age => 24
}
]

Optimize formatting from aggregated return from Sequel

I have a query from sequel that is returning something like this:
posts = [
<Post: #attributes={ id: 1, title: 'Foo', text: 'Bar', user_id: 21, user: <User: #attributes={ id: 21, name: 'John'}>}>,
<Post: #attributes={ id: 2, title: 'Bar', text: 'Foo', user_id: 21, user: <User: #attributes={ id: 21, name: 'John'}>}>,
<Post: #attributes={ id: 3, title: 'FooBar', text: 'FooBar', user_id: 19, user: <User: #attributes={ id: 19, name: 'Jane'}>}>
]
An array of Post and User objects.
I want to return it like this to the user:
json = {
posts:[
{ id: 1, title: 'Foo', text: 'Bar', user_id: 21 },
{ id: 2, title: 'Bar', text: 'Foo', user_id: 21 },
{ id: 3, title: 'FooBar', text: 'FooBar', user_id: 19 }
],
users: [
{ id: 21, name: 'John'},
{ id: 19, name: 'Jane'}
]
}
What would be the most efficient way to extract this Hash from the original array?
This is the code I'm using for it right now:
def prepare_json(array)
posts = []
users = Hash[]
array.each do |item|
posts.push(item.post)
# user id is unique so I use it to avoid duplication on
# the users array
users[item.user.id.to_sym] = item.user
end
{ posts: posts, users: users.values }
end
users = posts.map{|h| h.delete(:user)}.uniq
json = {posts: posts, users: users}
Result:
{
:posts=>[{:id=>1, :title=>"Foo", :text=>"Bar", :user_id=>21}, {:id=>2, :title=>"Bar", :text=>"Foo", :user_id=>21}, {:id=>3, :title=>"FooBar", :text=>"FooBar", :user_id=>19}],
:users=>[{:id=>21, :name=>"John"}, {:id=>19, :name=>"Jane"}]
}

how to covert array object to hash in rails

i have a hash with array object :
{
false=>[#<Campaign id: 1, name: "campaign 1", active: false>, #<Campaign id: 3, name: "campaign 3", active: false>, #<Campaign id: 4, name: "campaign 4", active: false>],
true=>[#<Campaign id: 2, name: "campaign 2", active: true>]
}
how to convert above hash to hash
{
false=>[{id:1, name:"campaign 1"}, {id:3, name: "capaign 3"}, ....],
true =>[{id:2, name:"campaign 2"}]
}
hash.each {|k,v| hash[k] = v.map{|e| {id: e[:id], name: e[:name]}}}
and if you can use select_all method get the array of hash, not array of object, so you doesn't need to covert object to hash.
ModelName.connection.select_all("select id, name from <table_name>;")
=> [{id:xxx, name: xxx}.......]
Use attributes method on your object
attributes() public
Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
hash = {
false => [#<Campaign id: 1, name: "campaign 1", active: false>, #<Campaign id: 3, name: "campaign 3", active: false>, #<Campaign id: 4, name: "campaign 4", active: false>],
true => [#<Campaign id: 2, name: "campaign 2", active: true>]
}
So this line should do the trick -
hash.each {|k, v| hash[k] = v.map(&:attributes) }
{
false => [{"id": 1, "name": "campaign 1", "active": false}, {"id": 3, "name": "campaign 3", "active": false}, {"id": 4, "name": "campaign 4", "active": false}],
true => [{"id": 2, "name": "campaign 2", "active": true}]
}

how to register a many-to-many model using the seed-fu

I have Users and Tags and User_Tag tables.
The Column of Users have id and name.
The Column of Tags have id and name.
The Column of User_Tag have user_id and tag_id.
How to register a many-to-many model using the seed-fu?
EDIT
I know that these following codes work.
I want to get rather better way.
db/fixtures/User.rb
User.seed(:id,
{ id: 1, name: 'ko2ic' },
{ id: 2, name: 'hoge' },
{ id: 3, name: 'fuga' },
)
db/fixtures/tag.rb
Tag.seed(:id,
{ id: 1, name: 'ruby'},
{ id: 2, name: 'java'},
{ id: 3, name: 'objective-c'},
)
db/fixtures/user_tag.rb
UserTag.seed(:id,
{ id: 1, user_id: 1, tag_id: 1 },
{ id: 2, user_id: 1, tag_id: 2 },
{ id: 3, user_id: 1, tag_id: 3 },
{ id: 4, user_id: 2, tag_id: 1 },
{ id: 5, user_id: 2, tag_id: 2 },
{ id: 6, user_id: 3, tag_id: 3 },
)

Resources