What if I had 3 Models that I wanted to connect.
For example:
A user can have many different permissions for many different applications.
So I need a table to store:
user_id
permission_id
application_id
Is that possible with has_and_belongs_to_many?
Thanks
I would do it with a has_many :through.
class Upa < ActiveRecord::Base
belongs_to :user
belongs_to :permission
belongs_to :application
end
class User < ActiveRecord::Base
has_many :permissions, :through => :upas
has_many :applications, :through => :upas
end
class Permission < ActiveRecord::Base
has_many :users, :through => :upas
has_many :applications, :through => :upas
end
class Application < ActiveRecord::Base
has_many :permissions, :through => :upas
has_many :users, :through => :upas
end
examples of has_many :through
Basically any sort of relationship that you can describe with a classical one to one, one to many and many to many relationships in relational databases can be described in ActiveRecord.
Yes, you can have has_and_belongs_to_many relationship. More help can be found here http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Related
This may be tough for me to explain, so if it's not clear just let me know so I can edit as needed!
I have the following example:
class User < ActiveRecord::Base
has_many :topics
has_many :memberships
end
class Topic < ActiveRecord::Base
belongs_to :user
end
#join model between User and Group
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
class Group < ActiveRecord::Base
has_many :memberships
has_many :members, :through => :memberships, :source => :user
has_many :topics, :through => :members
end
The problem I'm having is that I am trying to create a feed (#feed_topics) of all topics that are owned by all the members of the groups I am a member of, and I'm driving myself a little nuts.
Should I try to make this happen using associations, or make an instance method in my User model that has some ActiveRecord/SQL to union all the groups' members' topics into one ActiveRecord::Relation object?
My goal is to write current_user.feed_topics in my controller's action.
Sorry for not explaining earlier! The idea was to utilize 'Nested has_many_through's in order to get to your feed topics. This concept is documented here under the heading 'Nested Associations': http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html.
Let me know if this still is unclear (or if it doesn't work).
class User < ActiveRecord::Base
has_many :topics
has_many :memberships
has_many :groups, :through => :membership
has_many :group_members, :through => :groups, :source => :member
has_many :feed_topics, :through => :group_members, :source => :topic
end
So far these are the final versions of the models from the original question (topic and membership did not change):
class User < ActiveRecord::Base
has_many :topics
has_many :memberships
has_many :groups, :through => :memberships
has_many :feed_topics, :through => :groups, :source => :member_topics
end
class Group < ActiveRecord::Base
has_many :memberships
has_many :members, :through => :memberships, :source => :user
has_many :member_topics, :through => :members, :source => :topics
end
I am testing right now by adding more groups and members to see if it pulls in all the other members' topics of other groups.
EDIT: things seem to be working ok.
EDIT2: one little problem I had was seeing duplicate topics because a member was in multiple groups. I learned about :uniq => true and it saved the day.
I've started learning Rails recently and have completed the sample app at http://ruby.railstutorial.org. I am trying to add user-created groups to the sample social network. I've gotten stuck at how exactly I should model the group. I know there should be a user_id of who owns the group and there should be strings of the name and description. Aside from that I have no idea what the rest of the group data model should look like. Thank you in advance.
If you want a user to be in multiple groups your relations should be something like this
class Group < ActiveRecord::Base
belongs_to :owner, :class_name => "User"
has_many :memberships
has_many :members, :through => :memberships
end
class Membership < ActiveRecord::Base
belongs_to :member, :class_name => "User"
belongs_to :group
end
class User < ActiveRecord::Base
has_many :memberships
has_many :groups, :through => :memberships
has_many :owned_groups, :class_name => "Group", :foreign_key => "owner_id"
end
What about something like this?
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
Caution: I am a 4 week old at programming. I am having trouble with a has_many :through => relationship between my Neighborhood and Cta_train models.
Here are my models:
class CtaTrain < ActiveRecord::Base
belongs_to :Ctaline
has_and_belongs_to_many :searches
has_many :neighborhoods, :through => :CtaLocation, :foreign_key => :neighborhood_id
has_many :CtaLocations
end
class Neighborhood < ActiveRecord::Base
has_many :geopoints
has_many :listings
has_many :properties
has_and_belongs_to_many :searches
has_many :CtaTrains, :through => :CtaLocation, :foreign_key => :cta_train_id
has_many :CtaLocations
end
class CtaLocation < ActiveRecord::Base
belongs_to :neighborhood
belongs_to :CtaTrain
end
When I try to do this:
neighborhood.CtaTrains
I get this error:
ActiveRecord::HasManyThroughAssociationNotFoundError (Could not find the association :CtaLocation in model Neighborhood):
I have been slogging through this for several hours now....I have tried many iterations of ideas from stackoverflow....what I show above feels like the closest solution, but obviously still not working. Any thoughts would be appreciated!
I think the problem is that you're not following Rails conventions by using lowercase/underscore for your symbols. Class names have to be CamelCase but you should be doing the following everywhere else:
class CtaTrain < ActiveRecord::Base
belongs_to :cta_line
has_and_belongs_to_many :searches
has_many :neighborhoods, :through => :cta_locations, :foreign_key => :neighborhood_id
has_many :cta_locations
end
*Update: You should also be using :cta_locations (plural) in your has many through
I have 5 classes that are part of a point of sales program:
Customer, Technician, Order, Ticket, Service
Each Order has one customer and many tickets. Each Ticket has on technician and many services.
How should I make the associations so that I can do the following lookup:
customer.order.find_by_date(10/20/2010).service.technician.name
This is what I am planning:
class Customer < ActiveRecord::Base
has_many :orders
has_many :tickets, :through => :orders
has_many :technicians, :through => :tickets
end
class Technician < ActiveRecord::Base
belongs_to :ticket
belongs_to :service
end
class Service < ActiveRecord::Base
has_many :technicians
belongs_to :ticket
end
class Ticket < ActiveRecord::Base
has_many :services
has_many :technicians, :through => :services
end
class Order < ActiveRecord::Base
has_many :tickets
has_many :services, :through => tickets
has_many :technicians, :through => services
belongs_to :customer
end
The relationship between customer and order is one-to-many. And the relationship between order and service is also one-to-many. Therefore you cannot do:
customer.order.find_by_date('10/20/2010').service.technician.name
It should be:
customer.orders.find_by_date('10/20/2010').services.each do |service|
service.technician.name
end
It's a similar problem as in your other question.
I have a schema where:
Students
has_and_belongs_to_many :courses
has_many :grades, :dependent => :destroy
has_many :assignments, :through => :grades
Courses
has_many :assignments, :dependent => :destroy
has_and_belongs_to_many :students
Assignments
belongs_to :course
has_many :grades, :dependent => :destroy
has_many :students, :through => :grades
Grades
belongs_to :student
belongs_to :assignment
I would like to add functionality whereby if a grade is added and the student does not belong to the course that the grade's assignment belongs to, then this relationship is made. Any suggestions as to the best way to do this? The grades_courses table does not have it's own model, will this need to be made?
A friend has suggested using after_create, but I don't know how to pass the parameters to this.
How about an observer on grades? Something like this
class GradeObserver < ActiveRecord::Observer
def after_create(grade)
unless grade.assignment.course.students.include?(grade.student)
grade.assignment.course.students << grade.student
end
end
end