I want to build a rails request with 2 models.
I think it's quite simple, but I don't want to do a loop myself.
I'm in my country model:
def self.find_for_user(user_id)
wines = Wine.where("user_id = ?", user_id).group(:country_id)
where("countries.id IN ?", wines.map())
end
I want to get all countries depending the first request (the wines grouped by countries, I just need the countries)
I think I can do this in a single line where I put map() or another instruction. I just need to get all country_id fields for wines.
Thanks.
Assuming that you've got an association set up between wines and country (ie. has_many :wines in country.rb), I think this is what you're looking for:
def self.find_for_user(user_id)
joins(:wines).where('wines.user_id = ?', user_id).uniq
end
If all you want is all countries that have wine for a specific user, you can do that in SQL:
where("countries.id in (select country_id from wines where wines.user_id = ?)", user_id)
Related
I need to create a live chat app and now I have three models :
ChatRoom
ChatRoomMember
ChatRoomMessage
From this three models, I use includes and references to get the list of chat_rooms for current login user. Here is the code that I have wrote.
#chat_rooms = ChatRoom.includes(:members).references(:members)
#chat_rooms = #chat_rooms.includes(:messages).references(:messages)
#chat_rooms = #chat_rooms.where 'chat_room_members.user_id = ?', #current_user.id
#chat_rooms = #chat_rooms.order 'chat_room_messages.created_at DESC'
#chat_rooms = #chat_rooms.limit(limit).offset(offset)
However, the order didn't work as I expected. What I want is that the chat_rooms are sorted by created_at column from the last message in that room. How can I do this ?
Here is the database structure :
Use association to avoid where 'chat_room_members.user_id = ?', #current_user.id
Here is my suggestion, assuming User has associations looking like:
class User
has_many :chat_room_members
has_many :chat_rooms, through: :chat_room_members
end
# list only rooms with at least on message
#chat_rooms = #current_user.chat_rooms.joins(:messages).order('chat_room_messages.created_at DESC').limit(limit).offset(offset)
# list all rooms even if there is no message attached
#chat_rooms = #current_user.chat_rooms.distinct.left_joins(:messages).order('chat_room_messages.created_at DESC').limit(limit).offset(offset)
Try this:
ChatRoom.includes(:messages).order('chat_room_messages.created_at DESC')
Thanks for everyone has help me to solve this probel. I have my own answer. Here is it.
SELECT chat_rooms.*, (SELECT chat_room_messages.created_at FROM chat_room_messages WHERE chat_room_messages.chat_room_id = chat_rooms.id ORDER BY chat_room_messages.id DESC LIMIT 1) AS last_message_at FROM chat_rooms INNER JOIN chat_room_members ON chat_room_members.chat_room_id = chat_rooms.id WHERE chat_room_members.user_id = #{#current_user.id} ORDER BY last_message_at DESC
I use raw query for solve this problem. Hope this can help anyone who need it !
My BookingGroup has_many Booking. Booking contains column category where the data can be "adult" or "child_infant" or child_normal.
Now I want to count all total %child% and display it in my index view table
I was'nt sure whether this could be done in one line or I have to use a scope, this is where I stucked.
BookingGroup model
def search_by_category
bookings.visible.map(&:category).inject(:+)
end
Assuming category is a string column, you should be able to count it like that :
bookings.visible.where("category LIKE ?", "child%").count
bookings.visible.where(category: ["child_infant", "child_normal"]).count
We can use LIKE just as in SQL with active record
In your BookingGroup model
def search_by_category
bookings.visible.where('category LIKE ?', '%child%').size
end
But, if you do so for many booking_groups, your code will have N+1 queries issue. You can use eager load in your controller
#booking_groups = BookingGroup.joins(:bookings).select('booking_groups.*', 'count(*) as total_bookings').where('bookings.category LIKE ?', '%child%').group(:id)
Then you can
#booking_groups.first.total_bookings
I'm building a search for and got stuck on a cross-database references error
activities = Activity.order(:name).includes([:profile => :country])
activities = activities.where("lower(activities.city) like ?", "%#{params[:activity_search][:city].downcase}%") unless params[:activity_search][:city] == ""
activities = activities.where("activities.sport_id =?", params[:activity_search][:sport_id])
I'm trying to add something like this:
activities = activities.where("activities.profiles.country.id =?", params[:activity_search][:country_id])
an activity's country is the same as the activity creator's country.
How can I add this constraint in my query?
Thanks for your help
You need to use joins here to include the associations:
activities.joins(profiles: :country).where('countries.id = ?', params[:whatever])
This assumes Activity has_many :profiles and Profile has_one :country and countries is your table name, but I think all that is true based on your post. This will include the associated profiles and country with activities and allow you to use their attributes in the where method call.
I am working on a simple Rails with the following structure:
Product
has_and_belongs_to_many :subscribers
Subscriber
has_and_belongs_to_many :products
How can I get all products that has subscribers which is products with subscribers > 0 ?
def self.has_subscribers
#subscribers > 0
end
well have you tried doing,
#product.subscribers.count > 0
so you can do something like
def has_subscribers?
subscribers.count > 0
end
def self.has_subscribers
Product.joins("LEFT JOIN products_subscribers ON products_subscribers.product_id = products.id").where("products_subscribers.product_id IS NOT NULL")
end
HTH
edit: I am not sure, if below will work, but you may try it:
def self.has_subscribers
Product.joins(:products_subscribers)
end
Since, joins use INNER JOIN, it should return only those records of products which have a relationship with subscribers in the joining table.
Edit 2: Just joining with joining table may not (in fact should not) work because joining table usually do not have a model.
The above is working for me, except I forgot to GROUP the results.
Product.joins("LEFT JOIN products_subscribers ON products_subscribers.product_id = products.id").where("products_subscribers.product_id IS NOT NULL").group("products.id")
If you are still getting Subscribers, then it is kinda odd. Please post your function and querying code.
Product.where( '(select count(1) from products_subscribers where product_id = products.id > 0)')
I have 2 models in my Rails 3 app which I use to describe people and where they live
Unfortunately I set these up without using associations
The 2 tables are setup like this
People
id
name
location_id
Locations
id
name
what I want to do is list all entries in the Peoples table ordered by Locations.name alphabetically and People.name alphabetically
I can do a simple sort using this code which groups each person by a location but I need to drill into the Locations table as well
#people = People.all(:order => '"location_id" ASC, "name" ASC')
Anyone have any idea?
Also is it a good idea to set up an association in the People class to say location_id is Locations.id
Add
belongs_to :location
To the People class
Then you can query the following way:
#people = People.joins(:location).order("locations.name ASC, people.name ASC")