Arrange unique contents of hash according to there occurences - ruby

Suppose I am firing a activerecord statement and the resulting array of hash contains the following
I am sorry for the vague question without providing proper information
to be precise after running Item.joins(:item_categories).where(:item_categories => {:category_id => i.id})
I get the following
[#<Item id: 1, name: "Bat", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 1, name: "Bat", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 1, name: "Bat", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 2, name: "Base", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 2, name: "Base", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 2, name: "Base", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 3, name: "Glove", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 3, name: "Glove", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 3, name: "Glove", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 4, name: "Ball", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 4, name: "Ball", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 4, name: "Ball", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 5, name: "Catchers Mitt", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 5, name: "Catchers Mitt", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 5, name: "Catchers Mitt", created_at: "2014-02-10 00:28:43", updated_at: "2014-02-10 00:28:43">,
#<Item id: 6, name: "Batting Glove", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 6, name: "Batting Glove", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 6, name: "Batting Glove", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 7, name: "Batting Helmet", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 7, name: "Batting Helmet", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 7, name: "Batting Helmet", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 8, name: "Baseball Cap", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 8, name: "Baseball Cap", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 8, name: "Baseball Cap", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 9, name: "Gear Cycle", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 9, name: "Gear Cycle", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 10, name: "Non Gear Cycle", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 10, name: "Non Gear Cycle", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 11, name: "Mountain Bike", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 11, name: "Mountain Bike", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 12, name: "Uni-cycle", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">,
#<Item id: 12, name: "Uni-cycle", created_at: "2014-02-10 00:28:44", updated_at: "2014-02-10 00:28:44">]
In this case I not only want the output to be unique but also the hashes should be arranged according to the occurrences of there Item id:
Is there any method available for this?, do I have to work on my activerecord query or do I have to write the method to do this ?

Assuming you meant to show an array of hashes and not hashes with duplicate keys, you can use Array#uniq with a block to specify the criteria for uniqueness:
array = [
{ a: 1, b: 2 },
{ a: 1, b: 3 },
{ a: 2, b: 1 },
{ a: 2, c: 4 }
]
array.uniq {|hash| hash[:a] }
#=> [{ a: 1, b: 2 }, { a: 2, b: 1 }]

Hashes can't have duplicate keys, so no this is not possible. See the documentation at
http://www.ruby-doc.org/core-2.1.0/Hash.html
"A Hash is a dictionary-like collection of unique keys and their values."

If you executed this:
h = {'name' => 'hank', 'name' => 'hank','name' => 'steve',
'name' => 'brad', 'name' => 'brad','name' => 'brad' }
Ruby would not complain. It would set h['name'] to 'hank', then it would do that again, then it would change h['name'] to 'steve' and then set h['name'] to 'brad' three times, so you would end up with
h = { 'name' => 'brad' }
If you changed the keys so they were unique, wanted each value to appear only once and didn't care which key/value pairs you removed to accomplish that, here's an easy way to do it:
h = {'name1' => 'hank', 'name2' => 'hank', 'name3' => 'steve',
'name4' => 'brad', 'name5' => 'brad', 'name6' => 'brad' }
h.invert.invert #=> {"name2"=>"hank", "name3"=>"steve", "name6"=>"brad"}

Related

where for querying an array attribute in rails model

I have a user model with an array of roles.
u=User.first
u.roles = ['admin']
v=User.last
u.roles = ['admin', 'member']
How do i query to fetch all users with admin role?
Edit:
roles is a serialized array for the user model
User Model:
serialize :roles
Migration:
add_column :users, :roles, :string, default: []
Depends on what "roles" means:
If it is an association as in
class User < ActiveRecord::Base
has_many :roles
end
Then you look up the role and fetch all users:
Role.find_by_name("admin").users
or roles is just a column and it is serialised, in which case you can instantiate all users (slow)
User.all.select { |u| u.roles.include? "admin" }
Or query the database directly which is more complex and depends on the adapter.
My opinion: I would avoid using serialised columns, when relations can do. They are cumbersome in every way: Forms, Searches, Selects...
Another way is using scopes:
Model user.rb:
class User
scope :admins, -> () { where("roles #> ?", '{admin}')}
scope :by_roles, -> (roles) { where("roles #> ?", "{#{roles.join(', ')}}") }
end
Scoped calls, with results
Admins:
3.0.0 :001 > User.admins
User Load (0.4ms) SELECT "users".* FROM "users" WHERE (roles #> '{admin}') /* loading for inspect */ LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, account_uuid: "0812df2d-58ed-4231-aca5-ec7708a156bb", email: "admin#example.com", password_digest: [FILTERED], first_name: "Admin", last_name: "Admin" remember_token: nil, remember_token_expires_at: nil, roles: ["user", "admin"], created_at: "2021-12-02 11:51:50.684788000 +0000", updated_at: "2021-12-02 11:51:50.684788000 +0000">]>
Users by_roles within single role:
3.0.0 :002 > User.by_roles(['user'])
User Load (0.5ms) SELECT "users".* FROM "users" WHERE (roles #> '{user}') /* loading for inspect */ LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, account_uuid: "0812df2d-58ed-4231-aca5-ec7708a156bb", email: "admin#example.com", password_digest: [FILTERED], first_name: "Admin", last_name: "Admin", remember_token: nil, remember_token_expires_at: nil, roles: ["user", "admin"], created_at: "2021-12-02 11:51:50.684788000 +0000", updated_at: "2021-12-02 11:51:50.684788000 +0000">, #<User id: 2, account_uuid: "7a09830d-bfde-45eb-abeb-4b305a7bb374", email: "user_1#example.com", password_digest: [FILTERED], first_name: "User", last_name: "Adviseman", remember_token: nil, remember_token_expires_at: nil, roles: ["user"], created_at: "2021-12-02 17:40:12.172547000 +0000", updated_at: "2021-12-02 17:40:12.172547000 +0000">, #<User id: 3, account_uuid: "a0044954-6ad0-4d8f-9681-bd5dfcfa72b7", email: "user_2#example.com", password_digest: [FILTERED], first_name: "User", last_name: "Adviseman", remember_token: nil, remember_token_expires_at: nil, roles: ["user"], created_at: "2021-12-02 17:40:12.583594000 +0000", updated_at: "2021-12-02 17:40:12.583594000 +0000">, #<User id: 4, account_uuid: "7d26e5d5-beaf-48bd-ad98-f53044a7182b", email: "user_3#example.com", password_digest: [FILTERED], first_name: "User", last_name: "Adviseman", remember_token: nil, remember_token_expires_at: nil, roles: ["user"], created_at: "2021-12-02 17:40:12.847412000 +0000", updated_at: "2021-12-02 17:40:12.847412000 +0000">]>
Users by_roles within multiple roles:
3.0.0 :003 > User.by_roles(['user', 'admin'])
User Load (0.6ms) SELECT "users".* FROM "users" WHERE (roles #> '{user, admin}') /* loading for inspect */ LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, account_uuid: "0812df2d-58ed-4231-aca5-ec7708a156bb", email: "admin#example.com", password_digest: [FILTERED], first_name: "Admin", last_name: "Bezugliy", remember_token: nil, remember_token_expires_at: nil, roles: ["user", "admin"], created_at: "2021-12-02 11:51:50.684788000 +0000", updated_at: "2021-12-02 11:51:50.684788000 +0000">]>

What is inside my ruby array?

So I have an Array filled of what exactly?
myArray = [ #<Follower id: 1, username: "Prep Bootstrap", imageurl: "http://pbs.twimg.com//profile_images/2825468445/2a4...", user_id: "thefonso", follower_id: "2397558816", created_at: "2014-05-21 15:29:03", updated_at: "2014-05-21 15:29:03">, #<Follower id: 2, username: "JAVA Developer", imageurl: "http://pbs.twimg.com//profile_images/2825468445/2a4...", user_id: "thefonso", follower_id: "2352382640", created_at: "2014-05-21 15:29:05", updated_at: "2014-05-21 15:29:05">,
Follower id: 3, username: "JAVA Developer two", imageurl: "http://pbs.twimg.com//profile_images/2825468445/2a4...", user_id: "thefonso", follower_id: "2352382641", created_at: "2014-05-21 17:29:05", updated_at: "2014-05-21 17:29:05"> ]
Now I have many more of these inside this array with consecutive ids, etc..I'm confused by the #< >, is this an array of hashes? What am I looking at exactly? What is this an array of?
It looks like ActiveRecord's Followers class instances. Plus, it looks like you named your model improperly (with Rails practices, it should be named Follower).
Get the class of one of the objects and you'll know it
puts myArray[0].class

Split array. Ruby

Could you help me please with some problem?
I have array from database like this
str = Hiring::Tag.all
Hiring::Tag Load (0.1ms) SELECT `hiring_tags`.* FROM `hiring_tags`
=> [#<Hiring::Tag id: 1, name: "tag1", created_at: "2013-12-10 11:44:39", updated_at: "2013-12-10 11:44:39">,
#<Hiring::Tag id: 2, name: "tag2", created_at: nil, updated_at: nil>,
#<Hiring::Tag id: 3, name: "tag3", created_at: nil, updated_at: nil>,
#<Hiring::Tag id: 4, name: "wtf", created_at: "2013-12-11 07:53:04", updated_at: "2013-12-11 07:53:04">,
#<Hiring::Tag id: 5, name: "new_tag", created_at: "2013-12-11 10:35:48", updated_at: "2013-12-11 10:35:48">]
And I need to split this array like this:
data:[{id:1,name:'tag1'},{id:2,name:'tag2'},
{id:3,name:'tag3'},{id:4,name:'wtf'},{id:5,name:'new_tag'}]
Help me please!
if you use ActiveRecord 4.0
Hiring::Tag.pluck(:id, :name).map{ |id, name| {id: id, name: name} }
One possible solution:
Hiring::Tag.all.map {|h| {id: h.id, name: h.name} }
See the documentation for map.
You can try below code.
Hiring::Tag.all.inject({}) { |h, f| h[f.name.to_sym] = f.value; h }
OR
Hiring::Tag.all.map { |f| [f.name.to_sym, f.value] }]

Rails destroy_all undo

I've accidentally erased all the records from one my model.
Model.destroy_all
For the output I've received a large list for all the records that have been destroyed.
=> [#<Model id: 1, some_attribute: "Hello World">, #<Model id: 2, some_attribute: " Hello World 2">, etc etc etc]
But, I've got it a text.
Can I do anything, using IRB, to return the records back ?
This is very, VERY urgent! Any help is appreciated.
Thank you so much
The following script should do the trick:
require 'bigdecimal'
str = "#<Model id: 1, some_attribute: #<BigDecimal:4ba0730,'0.0',9(18)>, another_attribute: \"Hello World\">, #<Model id: 2, some_attribute: \" Hello World 2\">"
str.scan(/#?<(\w+) (.+?)>(?=, #|$)/) do |m|
model = Object.const_get(m[0])
m[1].gsub!(/#<BigDecimal:.+?('.+?').+?>/, "BigDecimal.new(\\1)")
eval("model.create(#{m[1]})")
end
This also handles instances of BigDecimal. In case you need to handle other special types you can just add another call to gsub!.
here's a quick test I made on my model:
1.
pry(main)> output = JobUser.first(10).to_s
=> "[#<JobUser id: 10001, instagram_user_id: 297705889, job_id: 2, invited: true, created_at: \"2013-09-23 21:53:37\", updated_at: \"2013-09-23 21:53:37\">, #<JobUser id: 10002, instagram_user_id: 36823356, job_id: 2, invited: true, created_at: \"2013-09-23 21:53:37\", updated_at: \"2013-09-23 21:53:37\">, #<JobUser id: 10003, instagram_user_id: 509682835, job_id: 2, invited: true, created_at: \"2013-09-23 21:53:37\", updated_at: \"2013-09-23 21:53:37\"> ....
2.
parsed = output.gsub('#<', '').gsub('>', '').gsub(/^\[/, '').gsub(/\]$/, '').split('JobUser').map(&:strip)
=>
"id: 10001, instagram_user_id: 297705889, job_id: 2, invited: true, created_at: \"2013-09-23 21:53:37\", updated_at: \"2013-09-23 21:53:37\",",
"id: 10002, instagram_user_id: 36823356, job_id: 2, invited: true, created_at: \"2013-09-23 21:53:37\", updated_at: \"2013-09-23 21:53:37\",",
"id: 10003, instagram_user_id: 509682835, job_id: 2, invited: true, created_at: \"2013-09-23 21:53:37\", updated_at: \"2013-09-23 21:53:37\"...
3.
parsed.shift because the first element in array will be a blank string
4.
records = parsed.map { |serialized_record| JobUser.new(eval "{ #{serialized_record} }") }
then you should probably run something like records.each { |record| record.save }
Please note that you should replace JobUser with your model name.
The point is you'll have to parse the string and insert it back into database
good luck!

How i can find uniq records on base of some attribute in sort_by rails

Hi i have these records how i can find unique records in sort_by methods block
my array is like this
[#<Post id: 1, name: "ali", team_elo: 0, team_name: "solo", created_at:
"2012-12-09 16:11:17", updated_at: "2012-12-11 03:39:43">,
#<Post id: 2, name: "ramiz", team_elo: nil, team_name: "roko", created_at:
"2012-12-11 03:40:31", updated_at: "2012-12-11 03:40:31">,
#<Post id: 3, name: "ramizrt", team_elo: nil, team_name: "joko", created_at:
"2012-12-11 03:40:47", updated_at: "2012-12-11 03:40:47">,
#<Post id: 4, name: "lee", team_elo: nil, team_name: "roko", created_at:
"2012-12-11 03:41:15", updated_at: "2012-12-11 03:41:15">]
how i can sort this array on base of unique team_name.The result should like this
[#<Post id: 1, name: "ali", team_elo: 0, team_name: "solo", created_at:
"2012-12-09 16:11:17", updated_at: "2012-12-11 03:39:43">,
#<Post id: 2, name: "ramiz", team_elo: nil, team_name: "roko", created_at:
"2012-12-11 03:40:31", updated_at: "2012-12-11 03:40:31">,
#<Post id: 3, name: "ramizrt", team_elo: nil, team_name: "joko", created_at:
"2012-12-11 03:40:47", updated_at: "2012-12-11 03:40:47">]
Thanks
You could do something like:
arr = arr.uniq { |x| x.team_name }
or its brother
arr.uniq! { |x| x.team_name }
which will set arr to only the elements you want.

Resources