How to use foreign keys in Ruby on the Rails query? - ruby-on-rails

I have three models; events, users and entries. I would like on my users page for to be able to retrieve information relating to the events associated with the event associated with the user.
def show
#user = User.find(params[:id])
#entry = #user.entries.paginate(page: params[:page])
end
It is more than happy with #user.entries.count but I would like to link up in a table something like this:
Event Name - Event Location - Course
My models are bellow:
class Event < ApplicationRecord
has_many :entries, dependent: :destroy
class User < ApplicationRecord
has_many :entries, dependent: :destroy
class Entry < ApplicationRecord
belongs_to :user
belongs_to :event

If they're related as:
class User < ApplicationRecord
has_many :events
end
class Event < ApplicationRecord
has_many :entries
belongs_to :user
end
class Entry < ApplicationRecord
belongs_to :event
end
Then you can use joins starting from Entry, up to User and check events where the user id is the one what you need:
Entry.joins(event: :user).where(users: { id: user_id })

Related

How can I implement a has_many :through association two ways?

I have a property model and a user model.
A user with the role of 'admin', which is represented by a column on the users table, can have many properties.
A user with a role of 'guest' can also belong to a property, which gives them access to that property.
How should I do this in Rails?
authorizations table -> user_id, property_id
class Authorization < ActiveRecord::Base
belongs_to :user
belongs_to :property
end
class User < ActiveRecord::Base
has_many :authorizations
has_many :properties, through: :authorizations
end
class Property < ActiveRecord::Base
has_many :authorizations
has_many :users, through: :authorizations
end
then you can do User.find(id).properties
First, you need a has_many :through association between your models User and Property. So, create a new table properties_users with columns user_id and propety_id. And do following changes to the models:
class PropertiesUser < ActiveRecord::Base
belongs_to :user
belongs_to :property
end
class User < ActiveRecord::Base
has_many :properties_users
has_many :properties, through: :properties_users
end
class Property < ActiveRecord::Base
has_many :properties_users
has_many :users, through: :properties_users
end
Now, we need to make sure that a guest user does not have more than one property. For that we can add a validation to model PropertiesUser like below:
class PropertiesUser < ActiveRecord::Base
validate :validate_property_count_for_guest
private
def validate_property_count_for_guest
return unless user && user.guest?
if user.properties.not(id: self.id).count >= 1
self.errors.add(:base, 'guest user cannot have more than one properties')
end
end
end
class User < ActiveRecord::Base
def guest?
# return `true` if user is guest
end
end
Finally, to access a guest user's property, define a dedicated method in model User:
class User < ActiveRecord::Base
def property
# Raise error if `property` is called on non-guest users
raise 'user has multiple properties' unless guest?
properties.first
end
end
Now, you can fetch a guest user's property by running:
user = User.first
user.guest?
=> true
user.property
=> <#Property 1> # A record of Property

Setting up Rails model

I have a User model, Post model and Bookmark model. How do i need to set up relationship among them so that I can use current_user.bookmarks.posts.
Maybe:
class User < ApplicationRecord
has_many :bookmarks
end
class Bookmark < ApplicationRecord
belongs_to :user
has_many :posts
end
class Post < ApplicationRecord
belongs_to :bookmark
end
If you're wanting to get all the posts that belong to the user, then you can use the has_many :through association:
class User < ApplicationRecord
has_many :bookmarks
has_many :posts, through: :bookmarks
end
class Bookmark < ApplicationRecord
belongs_to :user
has_many :posts
end
class Post < ApplicationRecord
belongs_to :bookmark
end
Then you can just call:
user = User.first
all_posts = user.posts
It will return an array containing all the posts for each of the bookmarks belonging to the user.

Rails has_many_belongs_to, has_many :through

I have 3 Models: Place, User, Reviews. Place and Users related with has_many_belongs_to - for favorites, and has_many :through - for reviews.
I want to insert to favorites some place, but this place inserted to reviews table, what is wrong?
Or create model Favorites?
class Place < ActiveRecord::Base
has_and_belongs_to_many :users
has_many :reviews
has_many :users, through: :reviews
end
class User < ActiveRecord::Base
has_and_belongs_to_many :places
has_many :reviews
has_many :places, through: :reviews
end
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :place
end
class FavoritesController < ApplicationController
def add_favorites
if User.first.places.push(Place.find(params[:place_id]))
render json: {desc:true, status:0, error:nil}
else
render json: {desc:false, status:1, error: "Problem insert to table places_users"}
end
end
Have you try having different names for the associations? Right now both your favorites and reviewed places are called the same.
Try something like:
class User < ActiveRecord::Base
has_and_belongs_to_many :favorite_places
has_many :reviews
has_many :reviewed_places, through: :reviews
end
And for the controller:
User.first.favorite_places.push(Place.find(params[:place_id]))
You could always use active record serializers to store a array of favorites ids in the User model.
class User < ActiveRecord::Base
serialize :favorites
end
user = User.create(favorites: [1, 4, 8, 9])

How to Model a multi-participant conversation system

I am new to Rails (and programming) and after going through a few tutorials, I am designing a messaging app to test my skills.
The situation I am modelling is where a user can message 2+ other users. Here's what I came up with
A conversation has many participants (users) and many messages
(message).
A user has many conversation and many messages.
A message belongs to users (sender + recipients) and belongs to a conversation.
The ActiveRecord model is then:
class User < ActiveRecord::Base
has_many :messages, :through :conversation
has_many :conversations # or is belongs_to :conversation
end
class Message < ActiveRecord::Base
belongs_to :user
belongs_to :conversation
end
class Conversation < ActiveRecord::Base
has_many :messages
belongs_to :user # or is it has_many :users
end
Or do I have to add a 4th interface inbox
class Inbox < ActiveRecord::Base
belongs_to :user
has_many :conversations
end
and I would change the user and conversation models to be
class User < ActiveRecord::Base
has_one :inbox
has_many :conversations, :through :inbox
has_many :messages, :through :conversation
end
class Conversation < ActiveRecord::Base
belongs_to :inbox
has_many :messages
belongs_to :users
end
The second option looks redundant.
So yeah, I am fuzzy about the relationship/association between a conversation and users. All input to enlighten me is greatly appreciated.
Your first way is better in my opinion, but it should look like this:
class User < ActiveRecord::Base
has_many :messages
has_many :user_conversations
has_many :conversations, through: :user_conversations
end
class Message < ActiveRecord::Base
belongs_to :user
belongs_to :conversation
end
class Conversation < ActiveRecord::Base
has_many :messages
has_many :user_conversations
has_many :users, through: :user_conversations
end
# join table between users and conversations
class UserConversation < ActiveRecord::Base
belongs_to :user
belongs_to :conversation
end
The reason is that a user can have many conversations, and a conversation can have many users. You need to create the join table UserConversation to accommodate this.
Also, the easiest way to find out which model should belong to the other model is to ask which model should have the foreign key of the other model. The one with the foreign keys belongs_to the other model.

Rails: How to store chat conversations

I am writing a rails application with conversations between clients and administrators. And i want the administrators respond to questions sent it by clients.
The administrators should be able to see the previous conversations with a reply box.
What is the best way to save these coversations:
Single table with marks of question and answer and view them as table entries?
Different tables and simply organise them by time?
class Administrator < ActiveRecord::Base
has_many :messages, as: :author
end
class Client < ActiveRecord::Base
has_many :messages, as: :author
end
class Message < ActiveRecord::Base
belongs_to :author, polymorphic: true
belongs_to :chat
end
class Chat < ActiveRecord::Base
has_many :messages
belongs_to :client
belongs_to :administrator
end
If you want to show messages of a particular chat you can do it this way:
#chat = Chat.find_by_client_id_and_administrator_id(client_id, administrator_id)
#messages = #chat.messages.order(:created_at)
If client and administrator belong to the same model, for instance User, then:
class User < ActiveRecord::Base
has_many :messages
end
class Message < ActiveRecord::Base
belongs_to :user
belongs_to :chat
end
class Chat < ActiveRecord::Base
has_many :messages
belongs_to :client, class_name: "User"
belongs_to :administrator, class_name: "User"
end

Resources