Setting up a rails model association - ruby-on-rails

My rails app has a user model that has a HABTM relationship with interests and holidays. Both of these (interests and holidays) only have one attribute that needs to be edited and related to the user. This is setup and working fine.
I need to create a new model called friend_birthday thats contains information regarding the birthdays of the users friends (and their respective interests). This model (friend_birthday) needs to have several attributes ( :name, :gender, :dob, and :interests).
I was thinking on using a has_many/belongs_to for this one. User has many friends_birthdays and friends_birthdays belongs_to a user.
Does this sound right? How could i implement this?
Thanks!!!!

Yes this sounds right, but i think it is better to name model Friend
class Friend
belongs_to :user
#also u can use HABTM for interests,
#but it is better to use rich join table and polymorphic association
has_and_belongs_to_many :interests
end
class User
has_many :friends
end
Ofc if friends are not users)) just RL friends

Related

Rails Data Modelling: How can I model a has_many relationship that's actually a collection of another model?

To be more specific, I have a User model that has_one Profile, now I'm in the need to add a has_many relationship from User to a new model Contact, but Contact is really a collection of Profiles ("User has_many Profiles" behind the scenes).
How do I correctly model this? Is there a way to avoid creating the new Model Contact altogether?
My concern, and reason to ask this question is having to perform an inefficient query to retrieve the User Contacts collection: user.contacts and then for each Contact I'd have to create a Query to retrieve each Profile, right?
How I can make it so that when I do: user.contacts it retrieves a Collection of Profiles that Doesn't interfere/is independent of the user.profile relationship?
Thanks in advance!
You wouldn't be necessarily need a new Model, but it's easiest (at least, in my opinion) to have one, just not in the way presented above.
Rails aside, you need a join table, like user_profiles, which contains foreign keys for user_id and profile_id. Now, how you make that work is up to you.
Your Contact model here is actually, in a more Rails-y way, a UserProfile model. So your User could look like:
class User
has_many :user_profiles # the join table
has_many :contacts, through: :user_profiles
has_one: profile
end
Here, user.contacts would get you the profiles. You still have that extra model, UserProfile, you just don't use it in practice:
class UserProfile
belongs_to :user
belongs_to :profile
end
Which you can build via:
rails g model UserProfile user:references profile:references
Hope that helps!

Validate uniqueness through join model in rails

I have a has_many :through association setup between two tables (Post and Category). The reason I'm using has_many :through instead of HABTM is that I want to do some validation on the join table (PostCategory).
So I have 4 models in use here:
User:
has_many :posts
has_many :categories
Post:
belongs_to :user
has_many :post_categories
has_many :categories, :through => :post_categories
Category:
belongs_to :user
has_many :post_categories
has_many :posts, :through => :post_categories
PostCategory:
belongs_to :post
belongs_to :category
Basically what I want is: Users can create posts, users can also create their own categories. A user can then categorize posts (not just their posts, any posts). A post can be categorized by many different users (in different ways potentially), and a category could contain many different posts (A user could categorize N posts under a specific category of theirs).
Here's where it gets a little bit tricky for me (I'm a Rails noob).
A post can ONLY belong to ONE category for a given user. That is, a post CANNOT belong to more than ONE category for any user.
What I want to be able to do is create a validation for this. I haven't been able to figure out how.
I've tried things like (inside PostCategory)
validates_uniqueness_of :post_id, :scope => :category_id
But I realize this isn't correct. This would just make sure that a post belongs to 1 category, which means that after one user categorizes the post, no other user could.
Really what I'm looking for is how to validate this in my PostCategory model (or anywhere else for that matter). I'm also not against changing my db schema if that would make things easier (I just felt that this schema was pretty straight forward).
Any ideas?
The simpliest way is to add user_id to PostCategory and to validate uniqueness of post_id with user_id scope.
Another way is to create custom validation which checks using sql if category owner has added category to that post.
Option 1 : use a before_save. In it, do a SQL look up to make sure a post with a similar category for your user doesn't exist (take care that on edit, you'll have to make sure you don't look-up for the current Post that is already in the DB)
Option 2 : custom validators :
http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#custom-validators
Never used them, but sounds like it can do what you want

Best way to create an association in Rails

I would like my User to be associated with specific Email's, when they receive them.
In this way, I can look up an array of what emails they have received.
Originally, I was thinking of just creating a string field for the User table, and adding the unique ID to the array..
User.find(x).received_emails << Email.find(x).id
But there may be a better way to do this with associating models.
Recommendations?
You should check this link out:
Rails association guide
It sounds like you're talking about a one to many sort of thing. If you use the association mechanism you'll get all the behavior you want, basically for free.
class Email < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :received_emails, :class_name => 'Email'
end
User.find(x).received_emails << Email.find(y)
This approach would require adding a user_id column to the Email table.
You probably want to change this to a many-to-many association by adding a join table such as user_emails with a UserEmail model. That table would have user_id and email_id columns.

Rails HABTM and belongs_to for associating users/projects

I have a User and Project model. A user can have multiple projects, and a project can have multiple users. This of course is simple with a has_and_belongs_to_many association. My problem is that I'd also like to track the user who created the project. This would be simple with a belongs_to :user for my Project model. The problem then is that doing a has_many :projects for a User when a user already has a HABTM relationship with a Project makes little sense.
Here's what I would eventually like to achieve:
# building a project with the currently logged in user
current_user.projects.build(...)
# now when a user wants to add another user to this project
project = current_user.projects.find(...)
project.users << User.find(...)
# grabbing information
some_project.user #=> The user who created this project
some_project.users #=> The array of User objects associated
some_user.projects #=> The array of Project objects associated
In the future it's likely a User will have the same sort of relationship with a Group, where a User would both have many and belong to many groups. But again I would also like to track the creator of this Group.
It's quite likely I'm missing something. What's a common way to achieve this?
If it helps to clarify, a possible configuration is laid out below:
Group
has_and_belongs_to_many :users
belongs_to :user
has_many :projects
Only a User should have the ability to create a Group
User
has_and_belongs_to_many :groups
has_many :projects
Can great a group or a project, and can also belong to both
Project
has_and_belongs_to_many :users
belongs_to :group
both a User and a Group should have the ability to create a Project
I've also tried doing simple has_and_belongs_to_many for each association and including a creator_id for example, and tracking this myself. For example.. Project.create(:creator_id => current_user.id) but this seemed hackish and I was sure they would be a better way to do this. Apologies for my ignorance if I've missing something simple.
Reading this again you want to have one owner of the project, either a group or a user. Store that as a polymorphic belongs_to relationship from the project model. ie. owner_type => 'User'/'Group' owner_id => 123
Other users associated with the group are many to many so you need a join table.
Your group model is a separate model with a many to many relationship with users so you can simply store the user who created it as a field of the group model ie. :user_id 123.

Help with rails content filtering

Im creating my own blog managing app in rails (for experimental purposes).... What would the best way to get this done?
I have posts and categories.
I want to have a dropdown of categories for the user to select one when they create a new post.
Now, each user will have different privileges so not all categories should appear for all users....
Right now Im at the point where I can create posts and choose which category I want... I havent added any filter per user support....
please help me on where should I go now??
First you will need to implement authentication and authorization. There are many good Rails tutorials on these subjects so I won't go into more detail here.
At this point you will have models for User, Post, and Category. You need a list per-user of authorized categories. A naive model:
class User < ActiveRecord::Base
has_and_belongs_to_many :categories
end
But that is misleading, because a user isn't actually "in" any categories. You probably want something like a join model like so:
class UserCategoryAuthorization < ActiveRecord::Base
belongs_to :user
belongs_to :category
// More fields here; possibly:
// belongs_to :authorized_by, :class_name => 'User'
end
class User < ActiveRecord::Base
has_many :user_category_authorizations
has_many :authorized_categories,
:through => :user_category_authorizations,
:source => :category
end
To start with I would give Users a has_many categories relationship(Which you could turn into its own model object at some point if this idea gets more complicated..or now if it already makes sense) and then assuming you already have log in functionality you can ask the logged in user for its categories and populate the drop down appropriately.
If this is a security issue rather than just convenience then you will need to validate the chosen category is in the users categories when the form is submitted back to the server.
If you don't already have logins I believe there are several rails plug-ins that attempt to help you get this functionality quickly.

Resources