Replace hash keys with new string in ruby - ruby-on-rails

Company model: There is aa attribute name and company has_many users.
Users model: User belongs to company.
Query:
After the query execution, below is my result.
users = {1360=>[#<User id: 2183, company_id: 1360, name: "XYS">, #<User id: 2184, company_id: 1360, name: "XYS1">], 1361=>[#<User id: 2185, company_id: 1361, name: "ABC">]}
In users object, there is one more column that is company_name which is fetch in query as alias, because I want only company_name not other attributes.
users = {1360=>[#<User id: 2183, company_id: 1360, name: "XYS", company_name="One">, #<User id: 2183, company_id: 1360, name: "XYS", company_name="One">], 1361=>[#<User id: 2185, company_id: 1361, name: "ABC", company_name="Two">]}
Here is the my desired output.
(Key would be company_name and its velue will be array of users info(name and id))
users = {"One"=>[["XYS", 2183], ["XYS1", 2184]], "Two"=>[["ABC", 2185]]}
How can I do that. Because when I try to replace the key(id) with name throughs an error

Try this
users.map{ |_,array| [array.first.company_name, array.map{ |a| [a.name, a.id] }] }.to_h

Related

Move one object in collection of objects in rails

Here is the scenario, I have these objects. Let's assume that this is a User:
The object came from:
#user = User.all
User Object
[<#User id: 1, firstname: "John", lastname: "Pond">,<#User id: 2, firstname: "Paul", lastname: "Rich">,<#User id: 3, firstname: "Jasmine", lastname: "Ong">]
How can I move one object up, for example I want to move User.id == 2? The result I want is shown below.
[<#User id: 2, firstname: "Paul", lastname: "Rich">,<#User id: 1, firstname: "John", lastname: "Pond">,<#User id: 3, firstname: "Jasmine", lastname: "Ong">]
I already got the answer. Here is what I made to made my question above worked.
#users = User.all
user_ids = User.pluck(:id)
user_ids.delete(2)
new_user_ids = [2]
user_ids.each do |id|
new_user_ids << id
end
#users.sort_by { |user| new_user_ids.index(user.id) }
And this made perfect!
We can also do it in a way like this:
Add a new method to Array. lib/rails_extensions.rb
class Array
def swap!(a, b = a - 1)
self[a], self[b] = self[b], self[a]
self
end
end
Then add this in config/environment.rb
require 'rails_extensions'
So we can use the method swap! for arrays and it will swap the object with the one before it. We can do something like this:
#users = User.all #[<#User id: 1>, <#User id: 2>]
user_id = #users.rindex {|user| user.id == 2}
#users = #users.swap!(user_id) #[<#User id: 2>, <#User id: 1>]
is this too ugly?
hash = [{ id: 1}, {id: 2}, {id: 3}]
hash.unshift(hash.delete(hash.select {|h| h[:id] == 2 }.first))
=> [{:id=>2}, {:id=>1}, {:id=>3}]

Query of searchkick get wrong result

Query of searchkick get wrong result.
I have this one record in db:
2.2.0 :047 > Product.first
#<Product id: 1, title: "Ball", description: "<p>Ball</p>\r\n", price: 10, material: "lalala", created_at: "2015-04-21 04:30:53", updated_at: "2015-04-21 04:30:53", preview: "images__1_.jpg", count: 20>
in controller Product and action search i have this code:
def search
#products = Product.search "*", where:
{
count: 10..18
}
end
and after this, a get result, that the with this values, count is exist.
But in db count = 20. And all time, get wrong result. I don't know why?
I get not correct result, 'cause i don't have hash, in model and need reindex of Model.
In model:
def search_data
{
count: count,
price: price,
title: title,
category_id: categories.map($:id)
}
end
and after that, in rails console wrote:
Product.reindex

RSpec Matchers When Working With ActiveRecord::Relation

So here's the method I want to test:
def self.by_letter(letter)
where("lastname LIKE ?", "#{letter}%").order(:lastname)
end
Quick question here, what exactly does the percent sign after #{letter} do? Something to do with formatting?
Here's part of the spec that tests that method:
context 'method "by_letter"' do
it 'returns and ordered list by letter' do
theon = Contact.create!(
firstname: "Theon",
lastname: "Greyjoy",
email: "tgreyjoy#ironprice.com"
)
rob = Contact.create!(
firstname: "Rob",
lastname: "Stark",
email: "rstark#winterfell.com"
)
tyrion = Contact.create!(
firstname: "Tyrion",
lastname: "Lannister",
email: "tlannister#kingslanding.com"
)
result = Contact.by_letter("S")
expect(result).to include("Snow")
end
end
And here's the logs I get for an output after running said test (oh, bare in mind, earlier in the spec I created a "Jon Snow", and he should pop up before "Stark" alphabetically):
Failures:
1) Contact method "by_letter" returns and ordered list by letter
Failure/Error: expect(result).to include("Snow")
expected #<ActiveRecord::Relation [#<Contact id: 1, firstname: "Jon", lastname: "Snow", email: "lordcommander#nightswatch.com", created_at: "2014-11-14 17:17:55", updated_at: "2014-11-14 17:17:55">, #<Contact id: 3, firstname: "Rob", lastname: "Stark", email: "rstark#winterfell.com", created_at: "2014-11-14 17:17:56", updated_at: "2014-11-14 17:17:56">]> to include "Snow"
Diff:
## -1,2 +1,3 ##
-["Snow"]
+[#<Contact id: 1, firstname: "Jon", lastname: "Snow", email: "lordcommander#nightswatch.com", created_at: "2014-11-14 17:17:55", updated_at: "2014-11-14 17:17:55">,
+ #<Contact id: 3, firstname: "Rob", lastname: "Stark", email: "rstark#winterfell.com", created_at: "2014-11-14 17:17:56", updated_at: "2014-11-14 17:17:56">]
What am I missing? Shouldn't my test pass because I return a collection that includes a string I specified? Is there some complication because it's not a regular array but some sort of proxy array? What do I need to do to get my test to pass?
Your result is an ActiveRecord::Relation object. So you should do as below :-
expect(result).to include(rob)
rob has the last name as "Stark", thus Contact.by_letter("S") will include rob in the filtered list.
Try expect(result.first).to include("Snow")
You can also say (preferably):
expect(result.first.lastname).to eq("Snow")

active record all query from instance

Maybe somebody has an idea how I could solve following problem:
I have a Model and want to query it.
def MyModel < ActiveRecord::Base
# instance method
def all
my_models = MyModel.all
my_models.?? # order my_models ActiveRecord::Relation, that the instance which calls the .all instance method is at first position, and the rest is sorted somehow,..whatever.
end
end
How could I solve that?
EDIT:
Example:
MyModel has a name.
I have four instances of MyModel
MyModel.all => #<ActiveRecord::Relation [#<MyModel id: 1, name: "name1">, #<MyModel id: 2, name: "name2">, #<MyModel id: 3, name: "name3">, #<MyModel id: 4, name: "name4">]>
And I want now:
MyModel.find(1).all => #<ActiveRecord::Relation [#<MyModel id: 1, name: "name1">, #<MyModel id: 2, name: "name2">, #<MyModel id: 3, name: "name3">, #<MyModel id: 4, name: "name4">]>
MyModel.find(2).all => #<ActiveRecord::Relation [#<MyModel id: 2, name: "name2">, #<MyModel id: 1, name: "name1">, #<MyModel id: 3, name: "name3">, #<MyModel id: 4, name: "name4">]>
MyModel.find(3).all => #<ActiveRecord::Relation [#<MyModel id: 3, name: "name3">, #<MyModel id: 1, name: "name1">, #<MyModel id: 2, name: "name2">, #<MyModel id: 4, name: "name4">]>
I believe this accomplishes what you're asking.
def all
self.class.order("case when id = #{id} then 0 else id end")
end
A possible solution would be taking advantage of the fact that an ActiveRecord::Relation instance responds to many of the Array instance methods:
def all
ary = self.class.order(:id)
ary = ary.unshift(self)
ary.uniq
end
However this returns an instance of Array so you can't keep appending additional scopes. Up to you to decide whether that's acceptable in your case.

How to populate select box from db query

I am trying to populate a ruby on rails select box from a database query, the data comes from 3 tables.
My query
#data = Session.all :include => { :term => :courses }
Object
!ruby/object:Session
attributes:
created_at: 2010-06-17 22:12:05
term_id: "15"
updated_at: 2010-06-17 22:12:05
id: "3"
course_id: "1"
attributes_cache: {}
term: &id003 !ruby/object:Term
attributes:
number: "1"
start_date: 2010-06-17
created_at: 2010-06-17 22:12:05
updated_at: 2010-06-17 22:12:05
id: "15"
attributes_cache: {}
courses:
- &id001 !ruby/object:Course
attributes:
created_at:
updated_at:
course_name: Beginner
id: "1"
date:
course_type: Programming
attributes_cache: {}
what i am trying to do is to have the term number followed by the data data and then the course
like this
1 01-09-10 Programming Beginners
The id for the option would be the session_id
any ideas ?
Thanks
Alex
in your erb template you can put the following code withing you form:
<%= select("session","id", #data.map{|d| ["#{d.term.number} #{d.term.start_date} #{d.course.course_type} #{d.course.course_name}",d.id]} %>

Resources