Rails Has_One Association Seems Illogical, Wrong Way Around - ruby-on-rails

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.

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.

Cost of constantly querying an associated nested model (does activerecord cache results?)

Let's say I have User model with a boolean flag called email_notifications. This lets us know whether this user cares to receive email notifications from the app.
Recently I've been moving all these flags and settings into a separate sub-model call Preference to keep it away from the core user model. A User has_one Preference.
class User < ActiveRecord::Base
has_one :preference, dependent: :destroy
accepts_nested_attributes_for :preference
scope :email_recipients, -> { where(preference: { email_notification: true} ) }
def can_receive_email?
preference.email_notification
end
end
As you can see, I have a helper scope and a helper method on the model.
However, now that it lives in another table, I have always query the association :preference first and then get the value I need. It's not directly available from the User model itself any more.
Is this considered bad practice? Or does Rails help out and cache associated models so it doesn't have to re-query every time? I like organizing my various configs in a separate model, which I DO think is good practice, but this potential cost of constantly re-querying is stopping me.
Thanks!
EDIT:
I'm aware that I can do User.includes(:preference).blah_blah, however I want to avoid updating this in EVERY place where I call the user, and it may not always be known ahead of time whether I'm going to query the sub-model and need to include an .includes()
Rails associations are stored in memory after they're accessed so calling user.preference wouldn't hit the database except for the first time it's referenced.
Also, includes wouldn't have much of an effect in this case since this is a has_one. includes is usually useful for eager loading many associations in a single larger query rather than hitting the database each time a child object is called.

Organization model extends user model

I have User model and Organization model. The only difference is that organization has_many users, all other properties are same. I don't want to put it in one table/model. How can I remove tons of code duplicating in this models? Should I use Concerns? I think, it will be not normal if User model will looks like :
class User < ActiveRecord::Base
include user_concern
end
So, how can I extend user model in other model? And how to generate this model with rails g with all User's fields inside?
beware STI
I would keep with concerns rather than using STI. STI often causes more problem that it solves (type mismatches, form urls, etc), plus inheritance won't make sense, here : an user is not a kind of company, and a company is not a kind of user.
That's a naming problem
I think your problem is a naming one. Obviously, your concern should not be "UserConcern". The question is : what kind of methods do you group in that concern ?
Are your methods about social relation between users ? Then, you need a Socializable concern. Are they about subscribing to mailing list ? Then you need a Subscribable concern.
It's ok to have several ones, even if they have a single method in it, because developers won't wonder "what the hell does this do ?" if all concerns are correctly named.
What to duplicate anyway
You should also probably let class level method calls out concerns.
If it's ok for scopes to be embedded in concerns (after all, they resolve in method definitions), it feels less natural to me to put relations in there.
It's ok to duplicate #has_many :foos, we do it all the time in separate models, and it's already difficult enough to get an idea of table schema from a model without hiding more information.
You could use single table inheritance (STI) for this. To get it to work, your model needs a type-field of type string, in which ActiveRecord stores the actual type of your record. Then, you just extend your base model for this.
migration
add_column :users, :type, :string
models
class User < ActiveRecord::Base and class Organisation < User.
ActiveRecord will now fill your type-field with the model-name, and store both in your users table (since this is the one the organisation model is inheriting from).
Have a look at the according section on http://api.rubyonrails.org/classes/ActiveRecord/Base.html .
However, in your case, I'd create a base model, e.g. Address, and then extend User and Organisation from it, to maintain semantically correct models.

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. :)

Rails Model Association Confusion

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.

Resources