Reputation: 1370
I'm working on sorting a list of employees by their title with the following:
TAGS = {
'Region Manager' => 1,
'Region Sales Manager' => 2,
'General Manager' => 3,
'Residential Sales Manager' => 4,
'Commercial Sales Manager' => 5,
'Other' => 6
}.freeze
def sorting_by_title(employees)
employees.sort_by do |x|
TAGS[x[:title]]
end
end
Works fine but...I also need to do an additional sort if an employee last name is Smith and needs to go before other individuals.
So I've tried doing something like:
return TAGS[x[:title]] unless x.last_name == "Smith"
Not working. It's erroring out on the show page with undefined method `each' for 2:Integer.
So my thought was I would build out another method to look for the last name.
def nepotism(employees)
employees.group_by do |emp|
case emp.last_name
when /Smith/ then :moocher
end
end
end
So I tried then referencing it like:
return TAGS[x[:title]] unless x.nepotism
return TAGS[x[:title]] unless x.moocher
Neither of those work. Nepotism ends up with undefined method `nepotism' for # and Moocher ends up with the same. Then I realized a simple query would work a bit better:
def nepotism
@nepotism = Employee.where(last_name: "Smith")
end
Is there a better way to sort_by a last_name if it matches Smith and THEN by the tags?
Upvotes: 1
Views: 942
Reputation: 3773
Combine them like this
employees.sort_by do |x|
x.last_name == "Smith" ? 0 : TAGS[x[:title]]
end
You can do it in the database as well (assuming Postgresql here)
def nepotism
tagstring = "array_position(ARRAY"+TAGS.keys.to_s.gsub(/\"/,"'")+", last_name)"
@nepotism = Employee.order("last_name = 'Smith' desc, " + tagstring)
end
Upvotes: 3
Reputation: 230346
Here's a nice trick: in ruby you can compare arrays. And, consequently, use them as value in sort_by
. They are compared element by element. If ary1[0] < ary2[0]
, then ary1 will be less than ary2, no matter the rest of the elements.
employees.sort_by do |x|
[
x.last_name == "Smith" ? 0 : 1, # all zeroes come before all ones
TAGS[x[:title]] # your main ordering parameter
]
end
This would work very well, if there were many Smiths and you needed to sort them by titles between themselves. If there's only one Smith, then @Björn's solution is simpler.
Upvotes: 3