Sorting objects based on condition - ruby-on-rails

#products = [#<Product id: 15, name: "abcd", revision: 100>,
#<Product id: 19, name: "test", revision: 1080>,
#<Product id: 5, name: "abcd", revision: 109>,
#<Product id: 450, name: "test", revision: 9>,
#<Product id: 2, name: "example", revision: 150>]
Question: I want to output all the products but the only condition is that if the name is duplicated more then once, then I would want to output the product which has the latest revision.
Expected Output:
#products = [#<Product id: 19, name: "test", revision: 1080>,
#<Product id: 5, name: "abcd", revision: 109>,
#<Product id: 2, name: "example", revision: 150>]
As there were two products named "abcd" it should display the one with the latest revision and the same applied to "test", but as there was no duplicates for "example" it is rendered normally.
Any help will be really appreciated, have been stuck on this.

This should do the trick:
temp_array = #products.group_by(&:name)
#filtered_products = temp_array.map do |name, products|
products.sort{ |p1, p2| p2.revision <=> p1.revision }.first
end
Don't hesitate to ask details if you need ;)

ActiveRecord only:
Product.select("name, MAX(revision) AS max_revision, COUNT(*) AS count")
.group("name")
.having("count > 1")

Related

Globalize duplicated locales

When I create a new admin user, there are three objects of translations:
Admin.last.translations.map(&:locale) # => [:ru, :uz, :uz]
Why are the locales duplicated?
Example:
admin.position_uz = 'CTO'
admin.position_ru = 'CTO'
admin.save!
admin.translations.count = 3
admin.translations.first.position = 'CTO'
admin.translations.second.position = 'Another value or empty'
admin.translations.third.position = 'CTO'
Every time the locale is set to uz, it shows the second variant.
Admin translations loo like
[
#<Admin::Translation id: 1, admin_id: 2, locale: "ru", position: "CTO", created_at: "2019-01-16 06:24:17", updated_at: "2019-01-16 06:30:31">,
#<Admin::Translation id: 2, admin_id: 2, locale: "uz", position: "Board Member", created_at: "2015-07-26 20:42:18", updated_at: "2015-07-26 20:42:18">,
#<Admin::Translation id: 3, admin_id: 2, locale: "uz", position: "CS manager", created_at: "2019-01-16 06:24:17", updated_at: "2019-01-16 07:09:21">
]

Rails sort with custom method

I have a large set of #clients that I'd like to sort by the client's last name but I cannot seem to get it working. I need to select :name and :id to speed up the query.
#clients = Client.all.select(:name, :id)
#clients.sort { |a, b| a.name && b.name ? a.name.split(" ").last[0] <=> b.name.split(" ").last[0] : a ? -1 : 1}
The result I get is:
#<ActiveRecord::Relation [#<Client id: 460, name: "Jim Jimmy">, #<Client id: 440, name: nil>, #<Client id: 231, name: "Paigetest Doyle">, #<Client id: 441, name: "Jeremy Lopez">, #<Client id: 462, name: "blah blah">, #<Client id: 348, name: "Jan Aldrich">, #<Client id: 464, name: "fefw fewfew">, #<Client id: 466, name: nil>, #<Client id: 67, name: "Jeremy Lopez">, #<Client id: 449, name: nil>, ...]>
There's a cool feature called split_part in Postgres that allows to split a string and get the word on specified position.
I believe the last_name is on the second position, hence SQL syntax will look something like this.
SELECT *, split_part(name, ' ', 2) AS last_name FROM clients ORDER BY last_name;
ActiveRecord syntax is going to look like:
Client.select("id, name, split_part(name, ' ', 2) as last_name").order("last_name")
I have no access to your env, so here can be some mistakes, but I wanted to make sure you got the idea.
Hope it helps.

Search in jsonb and array combination in postgres with rails4 stored_accessor

I have a model called Event, where I have stored_accessor "list" (stored like data: {"list"=>[{"key"=>"key1", "value"=>"value1"}]}).
I need to make a search query o
#<Event id: "1", title: "HHHH", description: nil, data: {"list"=>[{"key"=>"key1", "value"=>"value1"}, {"key"=>"key2", "value"=>"value2"}]}, created_at: "2017-04-14 21:06:22", updated_at: "2017-04-20 10:36:08">
#<Event id: "2", title: "HHHH", description: nil, data: {"list"=>[{"key"=>"key1", "value"=>"value1"}]}, created_at: "2017-04-14 21:06:22", updated_at: "2017-04-20 10:36:08">
#<Event id: "3", title: "HHHH", description: nil, data: {"list"=>[{"key"=>"key11", "value"=>"value11"}, {"key"=>"key12", "value"=>"value12"}]}, created_at: "2017-04-14 21:07:22", updated_at: "2017-04-20 10:37:08">
#<Event id: "4", title: "HHHH", description: nil, data: {"list"=>[{"key"=>"key111", "value"=>"value111"}, {"key"=>"key112", "value"=>"value112"}]}, created_at: "2017-04-14 21:08:22", updated_at: "2017-04-20 10:38:08">
I have a serach params like
1) {'key'=> 'key1', 'value'=> 'value1'}
2) ["key"=>"key1", "value"=>"value1"}, {"key"=>"key2", "value"=>"value2"}]
In first case, it should return Event id 1 and 2.
In second case, it should return Event id 1. (event if return 1 and 2 both could be acceptable).
I am not sure with json and array combination.
Please help.
You may do it with PostgreSQL jsonb's operator #>. Also you need to write the full path for search params: {'list' => [{'key'=> 'key1', 'value'=> 'value1'}]}. Try this code:
to_contain1 = {'list' => [{'key'=> 'key1', 'value'=> 'value1'}]}
to_contain2 = {'list' => [{'key'=> 'key2', 'value'=> 'value2'}]}
Event.
where("data #> ?", to_contain1.to_json})
# returns events 1 & 2
Event.
where("data #> ?", to_contain1.to_json).
where("data #> ?", to_contain2.to_json)
# returns event 1

Fetching wrong data in query in rails

I have done this
def show_selected_students(selected_students, students)
student = students.map{|a| a.name}
selected_students = selected_students.split(",")
#student_selected = selected_students.map {|i| student[i.to_i] }
end
in students I am fetching given data
#<ActiveRecord::Relation [#<Student id: 1, name: "XYZ",>, #<Student id: 2, name: "test1">, #<Student id: 3, name: "cherry">, #<Student id: 4, name: "mary">, #<Student id: 5, name: "hary">, #<Student id: 35, name: "hen">, #<Student id: 44, name: "duck">, #<Student id: 62, name: "try">]>
and in selected_students I am getting 2,3,4 Now I want to fetch those students whose id match with selected_students for this I had written this but it gives me this output ['cherry', 'mary', 'hary'] i.e id 3,4,5 but I want 2,3,4 Please guide me how to solve this. Thanx in advance.
You can try this:
def show_selected_students(selected_students, students)
selected_students = selected_students.split(",")
#student_selected = students.where(:id => selected_students).map{|a|a.name}
end

Acts As Taggable On

I'm having problems getting the acts-as-taggable-on gem working properly.
I have a model:
class Resource < ActiveRecord::Base
acts_as_taggable
end
I can add tags to it, and though its tag_list is populated:
$ a = ArchiveResource.new()
$ a.tag_list = ["one", "two", "three"]
$ a.tag_list # ["one", "two", "three"]
However, its tag association is not:
$ a.tags # []
If I check for all the tags, I can see they are being created:
$ ActsAsTaggableOn::Tag.all #<ActsAsTaggableOn::Tag id: 1, name: "one">,
#<ActsAsTaggableOn::Tag id: 2, name: "two">,
#<ActsAsTaggableOn::Tag id: 3, name: "three">
And if I check the model's taggings association I can see they exist there:
$ a.taggings #<ActsAsTaggableOn::Tag id: 1, name: "one">,
#<ActsAsTaggableOn::Tag id: 2, name: "two">,
#<ActsAsTaggableOn::Tag id: 3, name: "three">
Looking more closely at a call to a.tags.all I can see from the query that there is a mismatch:
ActsAsTaggableOn::Tag Load (0.9ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = 1 AND "taggings"."taggable_type" = 'ArchiveResource' AND (taggings.context = ('tags'))
However the taggings_context of the model's Taggings are all set to tag singular, so the query always fails:
<ActsAsTaggableOn::Tagging id: 1, tag_id: 1, taggable_id: 1, taggable_type: "Resource", tagger_id: nil, tagger_type: nil, context: "tag", created_at: "2013-09-10 17:12:20
<ActsAsTaggableOn::Tagging id: 2, tag_id: 1, taggable_id: 1, taggable_type: "Resource", tagger_id: nil, tagger_type: nil, context: "tag", created_at: "2013-09-10 17:12:20
<ActsAsTaggableOn::Tagging id: 3, tag_id: 1, taggable_id: 1, taggable_type: "Resource", tagger_id: nil, tagger_type: nil, context: "tag", created_at: "2013-09-10 17:12:20
If I run through all the Taggables and set context to tags, everything works:
ActsAsTaggableOn::Tagging.all.each{|t|t.context = "tags"; t.save!}
So why is this happening. Is it a bug or am I doing something wrong?
Looks like the default implementation is broken. By explicitly declaring the tags as :tags everything works OK:
acts_as_taggable_on :tags

Resources