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.
Related
I am using rails 5. When I perform the following straight SQL query in the rails console, I get the following expected result:
2.3.5 :053 > w = ActiveRecord::Base.connection.exec_query("SELECT * FROM students s LEFT JOIN (SELECT student_id, MAX(urgent) AS has_urgent,MAX(created_at) AS last_contact FROM reports GROUP BY student_id) r ON r.student_id = s.id")
(0.5ms) SELECT * FROM students s LEFT JOIN (SELECT student_id, MAX(urgent) AS has_urgent,MAX(created_at) AS last_contact FROM reports GROUP BY student_id) r ON r.student_id = s.id
=> #<ActiveRecord::Result:0x00000000051e1518 #columns=["id", "name", "cwid", "email", "phone", "company", "role", "advisor", "advisor_email", "mentor", "created_at", "updated_at", "student_id", "has_urgent", "last_contact"], #rows=[[1, "Johnny Smith", "71419940", "jsmith#gmail.com", "8435550001", "foxtrot", "mentor", "John I. Moore, Jr.", "john.moore#citadel.edu", "", "2017-11-13 14:58:50.128114", "2017-11-13 14:58:50.128168", nil, nil, nil], [2, "Shelly", "12345678", "shelly#gmail.com", "8435550002", "bravo", "mentee", "Michael P. Verdicchio", "mv#citadel.edu", "Johnny Smith", "2017-11-13 14:58:50.160195", "2017-11-13 14:58:50.160243", "2", "t", "2017-11-13 14:58:50.210105"], [3, "Max", "87654321", "max#gmail.com", "8435550003", "palmetto", "unassigned", "Mei-Qin Chen", "mei.chen#citadel.edu", "", "2017-11-13 14:58:50.179220", "2017-11-13 14:58:50.179258", nil, nil, nil], [4, "George", "87654325", "george#gmail.com", "8435550004", "palmetto", "mentee", "Deepti Joshi", "djoshi#citadel.edu", "Johnny Smith", "2017-11-13 14:58:50.189733", "2017-11-13 14:58:50.189762", "4", "f", "2017-11-03 14:58:50.260914"]], #hash_rows=nil, #column_types={}>
However, this returns an ActiveRecord::Result type, but I really want is to use the Rails ActiveRecord to do the same query but return an ActiveRecord::Relation instead, I thought like so:
2.3.5 :054 > w = Student.joins("LEFT JOIN (SELECT student_id, MAX(urgent) AS has_urgent,MAX(created_at) AS last_contact FROM reports GROUP BY student_id) r ON r.student_id = students.id")
Student Load (0.5ms) SELECT "students".* FROM "students" LEFT JOIN (SELECT student_id, MAX(urgent) AS has_urgent,MAX(created_at) AS last_contact FROM reports GROUP BY student_id) r ON r.student_id = students.id LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Student id: 1, name: "Johnny Smith", cwid: "71419940", email: "jsmith#gmail.com", phone: "8435550001", company: "foxtrot", role: "mentor", advisor: "John I. Moore, Jr.", advisor_email: "john.moore#citadel.edu", mentor: "", created_at: "2017-11-13 14:58:50", updated_at: "2017-11-13 14:58:50">, #<Student id: 2, name: "Shelly", cwid: "12345678", email: "shelly#gmail.com", phone: "8435550002", company: "bravo", role: "mentee", advisor: "Michael P. Verdicchio", advisor_email: "mv#citadel.edu", mentor: "Johnny Smith", created_at: "2017-11-13 14:58:50", updated_at: "2017-11-13 14:58:50">, #<Student id: 3, name: "Max", cwid: "87654321", email: "max#gmail.com", phone: "8435550003", company: "palmetto", role: "unassigned", advisor: "Mei-Qin Chen", advisor_email: "mei.chen#citadel.edu", mentor: "", created_at: "2017-11-13 14:58:50", updated_at: "2017-11-13 14:58:50">, #<Student id: 4, name: "George", cwid: "87654325", email: "george#gmail.com", phone: "8435550004", company: "palmetto", role: "mentee", advisor: "Deepti Joshi", advisor_email: "djoshi#citadel.edu", mentor: "Johnny Smith", created_at: "2017-11-13 14:58:50", updated_at: "2017-11-13 14:58:50">]>
For this second approach, the Right table columns do not appear in the result, even though the generated SQL looks very similar. I am new to Rails and ActiveRecord, so if someone can help me understand why these two results are different and what I should do to make the second ActiveRecord query work like the straight SQL query I would appreciate it.
If you are using rails 5 then use left_joins or left_outer_joins.
Try this and let me know if it work for you.
Student.left_outer_joins(:reports).select("student.*, MAX(urgent) AS has_urgent,MAX(created_at) AS last_contact").group("student.id").
If you want to go with your first approach then these methods may helpful for you.
result.columns #Get the column names of the result.
result.rows #Get the record values of the result.
result.to_hash #Get an array of hashes representing the result (column => value)
#ActiveRecord::Result also includes Enumerable.
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.
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
When I call:
preivous_lessons = #item.where("track_id = ?", lesson.track_id)
I get this active record realtion:
[#<CodeLesson id: 2, name: "Python", permalink: "python", lesson_content: "", instructions: "Print your name to the console.", hints: "", starting_code: "\"\"\"\r\nThis is a comment\r\n\"\"\"\r\n\r\nprint(\"Hello, World\"...", language_id: "12", order: 1, track_id: 2, user_id: 1, created_at: "2014-02-14 16:01:12", updated_at: "2014-02-15 21:14:43", visible: true>, #<CodeLesson id: 8, name: "Test Lesson", permalink: "test-lesson", lesson_content: nil, instructions: nil, hints: nil, starting_code: nil, language_id: "26", order: nil, track_id: 2, user_id: 1, created_at: "2014-02-20 19:23:15", updated_at: "2014-02-20 19:23:15", visible: false>]
How do I convert this into a usable array of models so I can do something like this:
preivous_lessons.each do |i|
highest = i.order if i.order > highest
end
As OP confirmed from my comment, that my hint solved his problem, I am putting it as an answer to the post :
preivous_lessons = #item.where("track_id = ?", lesson.track_id)
highest = preivous_lessons.maximum(:order)
Documentation of maximum :
Calculates the maximum value on a given column. The value is returned with the same data type of the column, or nil if there's no row.
preivous_lessons = #item.where("track_id = ?", lesson.track_id).all
On rails console output what does it mean #< at the start of the hash on the following example?:
irb(main):003:0> a=Movie.all
Movie Load (0.5ms) SELECT "movies".* FROM "movies"
=> [#<Movie id: 1, title: "Aladdin", rating: "G", description: nil, release_date: "1992-11-25 00:00:00", created_at: "2013-07-27 21:29:01", updated_at: "2013-07-27 21:29:01">, # <Movie id: 2, title: "The Terminator", rating: "R", description: nil, release_date: "1984-10- 26 00:00:00", created_at: "2013-07-27 21:29:01", updated_at: "2013-07-27 21:29:01">, #<Movie id: 3, title: "When Harry Met Sally", rating: "R", description: nil, release_date: "1989-07-21 00:00:00", created_at: "2013-07-27 21:29:01", updated_at: "2013-07-27 21:29:01">,... more output
That's how an object is printed in ruby, for example and instance of class Movie would be printed something like this:
<#Movie:0x003247fa... >
| |
class memory position I think
What you have there is a set of this previous writing:
[ one_object, other_object ... ]
To have a better display you could use hirb.
#< means that this is an instance of the Movie class.