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.
Related
I am trying to update mulptile list_items that belong to a list, but do so without saving to the database immediately, and then when they are all temporarily updated, save them. My code looks like this
old_length = #list.list_items_count
new_length = #body['list_items'].length
#body['list_items'].each_with_index do |list_item, i|
if old_length < new_length
#list.list_items.new(item_id: list_item['item_id'], position: i+1)
else
#list.list_items[i].item_id = list_item['item_id']
end
end
#list.save!
The model.children.new part works, but not the model.children.attributes. The real issue is that there is a migration that prevents list_ids and item_ids to be duplicated:
add_index :list_items, [:list_id, :item_id], unique: true
Before this migration I would run:
#list.list_items[i].update_attributes!(item_id: list_item['item_id'])
However, since update_attributes saves immediately to the database, the restricting migration doesn't allow some changes to be made. These changes are when I change item_ids that are already ListItems and I just want to switch them around. Example:
Before:
#<ListItem id: 342, list_id: 57, item_id: 333, position: 1, created_at: "2018-02-02 18:10:45", updated_at: "2018-02-02 18:10:45">
#<ListItem id: 343, list_id: 57, item_id: 444, position: 2, created_at: "2018-02-02 18:10:45", updated_at: "2018-02-02 18:10:45">
After:
#<ListItem id: 342, list_id: 57, item_id: 444, position: 1, created_at: "2018-02-02 18:10:45", updated_at: "2018-02-02 18:10:45">
#<ListItem id: 343, list_id: 57, item_id: 333, position: 2, created_at: "2018-02-02 18:10:45", updated_at: "2018-02-02 18:10:45">
In the example above, 333 and 444 are just switching places, but the migration throws an error because one is done before the other, and not simultaneously.
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
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
When I run ActiveRecord queries, the Rails Console seems to be appending LIMIT 1 to my queries.
So I have a sheet which has_many slots. When I query Slot.find_by(sheet_id: 96), I get:
Slot Load (2.3ms) SELECT "slots".* FROM "slots" WHERE "slots"."sheet_id" = ? LIMIT 1 [["sheet_id", 96]]
=> #<Slot id: 153, label: "Foo", name: "Foo", email: "", phone: "", comments: "Fighters", sheet_id: 96, created_at: "2015-04-30 14:28:47", updated_at: "2015-04-30 14:28:47">
But when I query Sheet.find(96).slots:
Sheet Load (10.0ms) SELECT "sheets".* FROM "sheets" WHERE "sheets"."id" = ? LIMIT 1 [["id", 96]]
Slot Load (4.6ms) SELECT "slots".* FROM "slots" WHERE "slots"."sheet_id" = ? [["sheet_id", 96]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Slot id: 153, label: "Foo", name: "Foo", email: "", phone: "", comments: "Fighters", sheet_id: 96, created_at: "2015-04-30 14:28:47", updated_at: "2015-04-30 14:28:47">, #<Slot id: 154, label: "Bar", name: "James", email: "", phone: "", comments: "Foobar", sheet_id: 96, created_at: "2015-04-30 14:28:47", updated_at: "2015-04-30 14:28:47">, ... >
You have to do Slot.find_all_by_sheet_id(96)
EDIT The above code should have worked. Although I use Rails 4.1.8. Try following as well:
Slot.where(:sheet_id => 338)
The find_by method returns a single result, always.
If you want to get all of the slots for a particular sheet, there are a few options:
Sheet.find(96).slots or more likely #sheet.slots if you've already found the sheet
Slot.where(sheet_id: 96) would also work
To be clear, this has nothing to do with the Rails console and everything to do with the .find_by method.
I need to join output of a hash into a string.
The hash looks like this:
nas.location.walledgardens.to_s
=> "[#<Walledgarden id: 1, location_id: 12, url: \"polka.com\", created_at: \"2012-05-14 17:02:47\", updated_at: \"2012-05-14 17:02:47\">, #<Walledgarden id: 2, location_id: 12, url: \"test.com\", created_at: \"2012-05-14 17:02:47\", updated_at: \"2012-05-14 17:02:47\">, #<Walledgarden id: 3, location_id: 12, url: \"help.com\", created_at: \"2012-05-14 17:02:47\", updated_at: \"2012-05-14 17:02:47\">, #<Walledgarden id: 4, location_id: 12, url: \"yell.com\", created_at: \"2012-05-14 17:02:47\", updated_at: \"2012-05-14 17:02:47\">, #<Walledgarden id: 5, location_id: 12, url: \"sausage.com\", created_at: \"2012-05-14 17:02:47\", updated_at: \"2012-05-14 17:02:47\">]"
I need to join the url values into the following format:
polka.com,test.com,help.com
What the best way to do this? I can easily look through it but the output has line breaks and I need these removed plus the commas.
nas.location.walledgardens.collect { |w| w.url }.join(",")
The .collect method will collect all what that block returns and put it in an array, and then the join puts that array in a string, separated by whatever you give it (so a comma).
What you have is not a Hash, but an Array of Walledgarden objects (they look to be ActiveRecord::Base subclasses).
Try this:
nas.location.walledgardens.collect(&:url).join ","
(Note: #map and #collect are equivalent, so which one you choose should be a consideration of readability!)
Use Array#map:
nas.location.walledgardens.map(&:url).join ','