nested resources rails has and belongs to many - ruby-on-rails

Sorry for the generic title, but I'm not sure how to phrase it better at the moment. I finally had some time to start picking up rails again and came across this issue as I was building my models:
Essentially I have a parent resource that has two nested resources. The parent can have many of each child resource and each child resource can have one parent. This part is working fine. The difficulty comes when I want to have a has_and_belongs_to_many relationship between the two child resources. I'm not sure how to implement this so that when I create a new Child 1, I can associate it with multiple existing Child 2's.
Imagine this like I have a User, Dog, and Walk models. The User is the parent, but each dog will have gone on many walks and each walk may have many dogs in it.
I've been looking for any tutorials for this part and have not had much luck. Can someone point me in the direction of a potential solution?

dog.rb
has_and_belongs_to_many :walks
walk.rb
has_and_belongs_to_many :dogs
Creation of object:
#walk = Walk.last
#dog = Dog.last
#walk.dogs << #dog
For this association, you will be having a join table as dogs_walks who won't have a model and will have attributes as dog_id, walk_id and it won't have id as primary key

Related

How do I create a self join item when it also belongs to another model?

I’m trying to make a self join relation for a model named: Subsystem. In this case a Subsystem represents a java package, class or method.
I’ve read the rails documentation where I saw I could use it like this:
class Subsystem < ActiveRecord::Base
has_many :child_subsystems, class_name: "Subsystem",
foreign_key: "parent_id"
belongs_to :parent, class_name: "Subsystem"
end
I also looked at a couple examples where in most cases the “create part” is not described.
My problem is that i’m looking for the best way to create the subsystems, because:
The Subsystem model also belongs to a Project.
Right now I create subsystems like:
project.subsystems.create(params)
I hope this image make’s it better to understand. A project, can have 0 to multpiple subsystems, and every subsystem can also have 0 to multiple subsystems.
Subsystems
I’ve seen examples of making a self join, where people created the item relation with build, but I’m not sure how to combine that with my existing create: project.subsystems.create.
Can someone help me out? Thanks in advance!
The way you created your self join association is spot on.
If you want to create a subsystem that belongs to a project you can do project.subsystems.create(...) and if you want to create a subsystem belonging to a subsystem you can do subsystem.child_subsystems.create(..). You effectively call the name of the association defined in the model (pluralised for has many associations).
The difference between build and create methods is that build effectively calls new whereas create calls new and save. When you create or build instances associated with other instances as defined in their models, the returned objects will contain the foreign keys of the records they are built or created from.

How to implement a HABTM in Ember?

Ive got the same HABTM (has many and belongs to many) as described at http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
In ember-data, how does one define the relationship between physician, appointment and patient?
In Rails, it is easy enough via has many through. Or, is there no need to do a HABTM association in Ember, since it is pulling/sending data out from/to an API?
Unfortunately, http://emberjs.com/guides/models/defining-models/#toc_many-to-many shows a many-to-many association with TWO models only.
Well, at a minimum you're going to need to add a couple of belongs-to relationships on your appointment model:
App.Appointment = DS.Model.extend({
...
physician: DS.belongsTo('physician'),
patient: DS.belongsTo('patient'),
...
});
Thus, whenever an appointment is saved, its child relationships will be saved with it. I assume that's what you want, since that's how the db is structured in the link you posted to the Rails guide.
The rest depends heavily on how your application is structured, especially your server's JSON API. For example, if you've got a model physician and you might be able to do something like this:
var query = { physician: physician.get('id') };
this.get('store').findQuery('appointment', query).then(function (results) {
...
});
If you then wanted to find all of a physician's patients, you could simply return an array of the unique patients belonging to the appointments that were found. This approach is pretty straightforward and easy to reason about, but it doesn't take full advantage of Ember Data.
Alternatively, you could try defining a has-many relationship on your physician and patient models: appointments: DS.hasMany('appointment'), which has some advantages but also requires much better knowledge of Ember Data.

How to structure this so I get all the benefits from STI with none of the consequences? (Pretty irresponsible, I know.)

Say I have the following example of associations in a Rails app:
I'm considering combining the *Posting models under STI. One problem with STI is the potential for many attributes that are only related to one subclass (i.e., a lot of denormalized nil values). This is especially worrisome when your subclasses and going to evolve and grow in the future. I've read a few related posts (such as this), however, as you can see in my example, the potential subclass-specific fields will not necessarily be just attributes, but rather, a lot of belongs_to associations.
My question is, how could I restructure this to use STI from a Posting model for all the common attributes/methods (of which there will be quite a few in my actual app), but keep the unique subclass-specific attributes and belongs_to associations from piling up in the Posting model? Also, the ability to access #board.postings and work with those standard methods is important.
For example, I've thought about moving the type-specific attributes to another model:
class CarPosting < Posting
has_one: car_posting_detail
end
class CarPostingDetail < ActiveRecord::Base
belongs_to :car_posting
belongs_to :car_make
belongs_to :car_model
end
Although, this starts to create a lot of joins, I'm not sure I have the has_one/belongs_to declarations in the right direction, and you have to start chaining calls (e.g., #posting.car_posting_detail.car_make).
Are there other design patterns you have seen for accomplishing this?
You basically have to 2 options for accomplishing inheritance.
First, you can use rails STI as you suggested. The downside is that end up with nil attribute for the child classes that do not use all of the fields. Your idea to reduce this by adding type-specific attributes to another model is a great way to reduce this. However, you should keep the implementation as DRY as possible by defining a has_one :detail for the Posting. Then you can simply assign specific detail types in the Posting childs. For example, CarPosting's detail would be CarPostingDetail. This is convenient because then all Posting children will have their details accessed identically, but will still have different details. So the query now looks like #posting.detail.car_make. To take this one step further, you can define a custom helper method in your Posting model to grab each attribute in the current Posting's detail and create an accessor for it. Now the entire detail layer is transparent and you can simply access those attributes by saying #posting.car_make.
Second, you can use an abstract class. This is essentially the reverse of STI. You create an abstract model class which can never be instantiated. Thus, you cannot define any relationships in the Posting class because it has no table. Each child of the abstract Posting class has its own separate table. The main advantage of doing this would be the ability to define methods for all of your Posting types without copy and pasting them into every model. So this options is better if there are some overlapping functionality across the models, but very little data overlap.
You could use polymorphic associations for this.
Post model belongs_to :postable, :polymorphic => true
car, event and all the other "postable" classes would have this relationship
has_many :posts, as: :postable
Post would hold the postable_id and postable_type
More info here
http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

How to save 2 id in joint table for many-to-many relationship in rails 3.1

There are two models. One is rfq and another one is standard. It is like:
class Rfq << ActiveRecord::Base
has_and_belongs_to_many :standards
end
class Standard << ActiveRecord::Base
has_and_belongs_to_many :rfqs
end
Table rfqs_standards has been created. My question is when creating rfq, how to save the paid of rfq_id and standard_id in table rfqs_standards automatically.
Thought adding accepts_nested_attributes_for :standard in rfq model. However since there is no real attributes (but just pair of id) saved for this many-to-many relationship, this seems not the right way.
Both rfq and standard was declared in routes.rb as resources :rfqs and resources :standards.
The procedure is when creating rfq, standard will be picked up via a drop down list. Then rfq is saved and at the same time, a new entry in joint table is created. When creating new standard, there is no need to create entry in joint table.
Any suggestion to save the id in joint table? Thanks.
this is easier than you might think because it's handled automatically by ActiveRecord.
When you say "has_and_belongs_to_many", you're telling AR to associate those two models with a many-to-many relationship using the table, and for the most part you no longer need to worry about the join table. When you add an instance of Standard to an Rfq's list of standards, this will be done for you.
Here's an example:
rfq = Rfq.create
standard = Standard.create
rfq.standards << standard
We've created each of the objects, and the third line creates the connection, saving a new record in the rfqs_standards table with the proper ids. rqf.standards looks and acts like a normal array, but when you assign objects to it, ActiveRecord does the database work for you.
After creating the records, you could have also done:
standard.rfqs << rfq
You could also do both at the same time:
rfq = Rfq.create
standard rfq.standards.create
This created an rfq, then created a standard that is automatically connected to the rfq. You can do the same thing in reverse:
standard = Standard.create
rfq = standard.rfqs.create
I hope this helps!
UPDATE: Since you mentioned forms and automatic saving, read my article on nested attributes that shows how to implement that, including full code samples.

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

Resources