Rails Model Association Confusion - ruby-on-rails

Hey guys. I have the following models:
Category
Event
Lock
Item
Site
User
Events are basically a "log item". In other words, they will store what action was done on what Item by what User in what Category. Naturally, when I thought about this, I figured it "has one User", "has one Category", "has one Item", and so on. However, this would mean that there would be a foreign key for the Event in any given User row, but this isn't what I want. I want the foreign key in the Event row, since the Event is just giving information as to what User, what Category, etc.
So my understanding is that I should instead say that an Event "belongs to a user", "belongs to a category", etc. and that they each "have many Events" in return, correct? I'm just making sure, because this doesn't read logically as most other associations. I don't need/want to be able to access an event from the other side (i.e. user.event) because it wouldn't make much sense. So if I do this, would I just add the belongs_to call and not the has_one on the other side?
Perhaps I designed this incorrectly.
I eventually want to be able to render a 'log page' filled with rows, reach row described a little something like:
event.user event.action event.item event.category

I don't need/want to be able to access
an event from the other side (i.e.
user.event) because it wouldn't make
much sense. So if I do this, would I
just add the belongs_to call and not
the has_one on the other side?
Add them both(belongs_to and has_many). Sure, user.event doesn't make sense, but user.events does make sense.

Yes, here you want to use a has_many & belongs_to association. In the context of Activerecord, it is the has_many that defines the need for the belongs_to. "If a model (a) has_many of another model (b) then that associated model (b) belongs_to the first model (a)".
Since a user will have many events associated with it, then an event will belong_to a user.
If on the other hand, a user were to only ever have one event associated with it, then these models would have a "has_one" association.

Related

Rails Polymorphic Association with multiple models

This is the case: I have 4 models which are "owner", "user", "location" and "landlord". All of these models share email addresses and phones. So I'm thinking to use Polymorphic Association and I made a research but I just see cases for 3 models. In my case as you can see I will have more than 3 models.
So, do you think is a good idea to implement this kind of logic where I want to use a model like the "repository" for all emails and phones numbers?
There is a limit or something in order to use that kind of association?. I'm thinking in some models like:
email
emailable
user
owner
landlord
location
Each model will have their necessary fields.
Thanks in advance.
There's no limit. A polymorphic association is an open interface that any other model can plug into. In your example, maybe you have a Contact model, which belongs_to :contactable, polymorphic: true. The contacts table will need two indexed columns: contactable_id:integer, and contactable_type:string. Any other model can be contactable, as long as it has_one :contact, as: :contactable.
As far as if it's a good idea, I'd say if you think you will need to work with contacts as a separate entity from the contactable models, then this is a good solution. However, if you won't need to deal directly with contacts then it might be overcomplicating when you could just add email and phone fields to these models.

Rails Has_One Association Seems Illogical, Wrong Way Around

Sorry if this is obvious. I've been using Rails for a while now, but the way the has_one association works still messes with my head. It just hasn't clicked yet.
I am creating a specialized table that creates a list of companies that meet certain criteria necessary for an email mail-out, and which contains info on whether they have been emailed, and have responded to the email (or not.)
Each entry in the email_responder table links to a single company record. So it seems logical to me to say that each responder record has_one company.
However, if I add the has_one to the responder model and then use responder.company I get an error telling me that I need to have a responder_id field in the company record. Which makes no sense to me, the company knows nothing about responders. I'd expect that since the responder has one company, that there'd be a company_id in the responder record not the other way around. It seems bass ackwards.
So, obviously what I've done isn't Railsy, but other than hacking a company method into the responder model I'm not sure what to do about it. Is there another association type in Rails that I haven't discovered yet?
Each entry in the email_responder table links to a single company
record. So it seems logical to me to say that each responder record
has_one company.
That means one company can have multiple responders.
So you need to add company_id column in the responders table.
And the association is like
class Company < ActiveRecord::Base
has_many :responders
end
class Responder < ActiveRecord::Base
belongs_to :company
end
So each record of responder has one company and one company has multiple responders.
It sounds like you want a belongs_to association.

Rails: Designing relations between models

My application needs to implement a functionality for performing competitions of photographers. Process looks like this: Administrator creates a competition, then user can apply a request for participating. Admin can approve request or it can deny it. Admin does it by creating a response with response status field assigned to ACCEPTED (0) or BANNED (100).
class Competition
end
class User
end
class CompetitionRequest
belongs_to :user
belongs_to: competition
end
class CompetitionResponse
ACCEPTED = 0
BANNED = 100
belongs_to :competition_request
end
class Photo
belongs_to :competition
end
But later i need to figure out how to filter banned photos from showing them to users and jury.
And Photo has no direct connection to CompetitionResponse. Photo and CompetitionResponse have relations to Competition but i can not figure out how to make filtration possible. I tried doing it via plain sql (find_by_sql) inside Photo model (it returns records only if appropriate request was approved) but it does not seems to be a good design, because i reference value defined in CompetitionResponse class in Photo model.
Later i changed design and make a before_save filter inside CompetitionResponse model, it checks if status == BANNED and if true, marks all the photos posted to competition by user (who's request was banned) as banned (i added a status field to Photo model).
But now i feel it looks not good. CompetitionRequest model takes too much responsibility.
What is the best way to design it ? May be there must some kind of Observer or something like this or another design pattern ?
First step I would take is assign each Photo to the user it "belongs_to". This will allow you to, at any time, check whether the "owning" user was indeed accepted or banned for the competition that photo refers to...
It seems to me that you should have a many-to-many relation between Competition and User. When the admin accepts a user into the competition, you associate the records. This keeps things simple in your data model and also allows for cases where Users get into a Competition without requesting it (perhaps as part of a tournament?).
Also consider getting rid of CompetitionResponse - it seems like this should just be an attribute of CompetitionRequest, as there would only be one response to a request, right?

Rails 3, ActiveRecord, Detecting changes in has_many association

I have the following associations
class User < ActiveRecord::base
has_many :memberships
end
What I would like to do is to detect in the users_controller update action that some memberships have been added or removed from the user.memberships.
Any idea or suggestion on how to implement this?
Thanks for any help.
EDIT: My apologies if the question was not clear.
Users are linked together by a parent-child relationship. This relationship is implemented through memberships to a Family circle.
What I want is that when a child user joins a Classroom circle automagically the parent of the child also joins the same Classroom circle. In other words adding/removing memberships to a child user needs to be propagated to his parents users.
My apologies if the context was not very clear.
So first some context clarification:
Users are linked together by a parent-child relationship. This relationship is implemented through memberships to a Family circle.
What I want is that when a child user joins a Classroom circle automagically the parent of the child also joins the same Classroom circle. In other words adding/removing memberships to a child user needs to be propagated to his parents users.
Now the solution:
The way I have solved this is by adding the after_save and before_destroy methods to the Membership model to check is the user is a child and in that case to create/destroy membership for the parents. There are several tricky edge-cases I had to solve but the code seems to be working fine.
A final note: my first idea was to somehow detect in the user controller that memberships have been added or removed and then check if the user was a child user....
I know I'm late to the party here, but for future travelers ActiveRecord exposes before_add, after_add, before_remove, and after_remove hooks for exactly these scenarios.
Added how? Since the last visit?
If so, then make a "read" boolean column that updates when you visit.
Otherwise, elaborate. :)

Understanding MongoMappers many relationship

Ok, so firstly Im not very in the know when it comes to Ruby, Rails, Mongo or even ActiveRecord so I apologise if these questions are fairly basic. Firstly, I have an "Event" model and I have added a many relationship to my "Comment" model. Now it is my (basic) understanding of mongo (or any document db) that foreign key lookups (or whatever they are called in mongo) are not advised, instead opting for storing as much as possible in a single document. With this in mind I would expect to have a single Events collection with the Comment JSON/BSON embedded in each document i.e.
event:
{
Title: "some event"
Comments : [
{ user_id: [object id], comment: "comment"},
{ user_id: [object id], comment: "other comment"}
]
}
Instead I am seeing that a comments collection has been created as well as the event collection. Would this be the correct way to map this relationship, if so how do I stop the comment collection been created and instead have the info embedded directly into the event? My guess is that I have to tell my Comment mapping not to have a _id property and thus not belong to its own collection.
EDIT: I found out that what I was looking for here in my first question was to use MongoMapper::EmbeddedDocument instead of including MongoMapper::Document
Secondly, I want users to be able to flag themselves as "attending" or just "interested" an event, which I assumed would be modelled as an array of reference user_id's on the event. So I initially thought it would be mapped as two "many" relationships, but as far as I can tell the name of the constant I am passing to the many method is used to create the getter/setters, which wouldn't work for me if I had two many relationships for the same type.
In other words, if I have this mapping:
class Event
many :users
end
Then it's my understanding that I will then have getters and setters generated for the users property. So I can do something like:
event.users << someAttendingUser
This is all good, and at this point in time I would want the reference to the user to be stored and not the whole user BSON (unlike with the comments example above). Now the problem is how do I do this when I have two many mappings to the user collection, as with my need for both "attending" and "interested" users?
So to summarise this rambling:
Sometimes I want to store many relationships directly as BSON in the orinal document, and not as a reference to a document in another collection. How do I do this?
Sometimes I want to store many relationships of the same type on a document and I DO want them to be references to a document in another collection. How do I do this?
Hope this made sense, and I apologise if Im asking the obvious here.
EDIT 2:
Ok, well I really did search before asking this question, but it appears that I have now found the answer to both of my problems so I will close the question myself.
The second part required me to specify a class name option for the mapping i.e.
class Event
many :attendees, :class_name => "User"
many :interested, :class_name => "User"
end
Ok, well I really did search before asking this question, but it appears that I have now found the answer to both of my problems so I will close the question myself.
The second part required me to specify a class name option for the mapping i.e.
class Event
many :attendees, :class_name => "User"
many :interested, :class_name => "User"
end

Resources