Environment: Rails 3.2.13 with SQLite in development and PostgreSQL in production
Using Active Record, I'm trying to get a list of unique first letters from all first names in the DB. For example, if I have names (Alex, Billy, Bob, Dave, Jack, James, Jen, Sam, Steve, Stewart, Victor) I'm trying to get the letters (A,B,D,J,S,V) from the DB.
I've been able to go into the Rails DB Console and query SQLite and get what I want using:
SELECT DISTINCT SUBSTR(last_name,1,1) FROM people ORDER BY last_name;
But haven't been able to get it to work within Rails.
you can use, for instance
User.all.map{|u| u.name[0]}.uniq
but this is in memory. If you need to do it in SQL, you can use find_by_sql
Related
As the title says, for example we have a library system with two tables Books and RentalRecord with a one to many relationship. It looks like
Book1
--name
--RentalRecords
----record11
----record12
Book2
--name
--RentalRecords
----record21
----record22
----record23
----record24
Each record contains 2 time stamps for date rented, and date returned
and I want to query for the Books that hasn't been rented out in the past 2 weeks.
I'm new to Ruby and couldn't think of any way to do this without using multiple queries.
Using two queries sometimes is a viable option. If you prefer constructing a single query, use something along the lines of
Book.joins(:rental_records)
.where("max(rental_records.created_at) < ?", 2.weeks.ago)
Things to note:
You need to join the required tables explicitly (but by association name)
You can use a plain string in a Rails where statement
You can bind a Ruby value to a question mark within such a string
If your queries get out of hand or you don't like using plain SQL strings like that, then take a look at the gem squeel. It provides an fully-fledged SQL algebra for Ruby on Rails.
HTH
I have a Ruby on Rails application that usually communicates with MongoDB through the Mongoid gem, but for performance reasons I need to insert documents directly into MongoDB like this:
Order.collection.insert(Array.new << {order_id: order_id, mail_address: mail_address}) # this creates the document, but does not return anything useful that can be referenced: {"n"=>0, "connectionId"=>53675, "wtime"=>0, "err"=>nil, "ok"=>1.0}
Customer.collection.insert(Array.new << {mail_address: mail_address})
I have defined a relationshop where a Customer has many Orders, so if I used Mongoid I could create the relation with customer.orders << order.
But how do I create the relation when I'm not using Mongoid?
None of Moped's insert methods return anything terribly useful to you so your documents are getting normal ObjectId's in their _id but you have no easy way of knowing what they are. You're on the right track by trying to assign your own _ids but you don't have to use Strings, you can simply say Moped::BSON::ObjectId.new to generate a new _id. Assuming that your Orders have a customer_id which points at the Customer, you could:
customer_id = Moped::BSON::ObjectId.new
Customer.collection.insert(_id: customer_id, mail_address: mail_address)
Order.collection.insert(customer_id: customer_id, ...)
Don't be afraid to poke around inside MongoDB using the mongo shell to see how things are structured internally. All the helpful relations and embedding conveniences that Mongoid provides are nice but you still need to know what they're doing to your database.
I got an email from Heroku saying I have too many rows in my Postgres DB.
How can I see how many rows I have in each table (so I can prioritize deletion)?
heroku pg:psql (specify database name here if you have more than one)
Then check out this post to get a row count in postgres
How do you find the row count for all your tables in Postgres
A better way to look at this might be:
How many records do I have for each of my AR models?
While it may not exactly match the numbers Heroku gives (may be a bit lower), and may have some extra stuff (that are not models), but for practical purposes, this is best option and it avoids the need to use SQL.
ActiveRecord::Base.descendants.map { |d| [d.all.size, d.name] }.sort
Explanation:
ActiveRecord::Base.descendants is a quick way to get all of the AR models. This is used to create an array of arrays that contains the [number of records, model name] to allow for simple lexicographic sorting. This should be enough to quickly determine where all your rows are going.
I'm trying to seed a Rails application with some sql statements in the seed.rb file. There are 12 values supplied, however, the table has 15 columns. The extra three columns are the automatically generated id, created_at and updated at columns that Rails includes by default. If I run a custom sql statement in the seed.rb file in the following manner....
connection = ActiveRecord::Base.connection()
query = "random sql"
connection.execute(query)
Rails doesn't create those columns for me in the way it would if I did
Employee.create!(name: "Joe")
Is there anyway to indicate to rails that I need the id and timestamp columns filled with values when I run an sql statement in seed.rb?
No, because Rails has no way of knowing whether your "random sql" even creates any records for it to fill in ids/timestamps.
When you connection.execute you are on your own, you have forsaken your ORM and given in to the temptation of SQL.
If you can do it using ActiveRecord, then do so! If not, well, that is why Rails lets you drop down to SQL (but think again. Can you really not write it in Ruby?).
I have a Rails 3 app which keeps high scores. I'm hosting it on Heroku which uses postgresql as the db.
I need to extract the top scores from the scores table. The table has columns score and user_id. It was working in mysql with the following:
Score.order('score DESC').group('user_id').limit(25)
This ranks each user's top score.
When I put the app on Heroku, I get the following psql error PGError: ERROR: column "scores.id" must appear in the GROUP BY clause or be used in an aggregate function
I've read around but haven't found a clear answer. What is the most optimal way to recreate the above query to work with PostgreSQL?
Thanks!
Tim
That means your select query is selecting the "id" column but not including it in the group by clause. I'm not familiar with rails but could it be selecting * or all columns?
Could you do
select id, max(score) group by id;