Uninitialized constant error on has_many through association - ruby-on-rails

I've got a question about active-record association in Rails.
I'm developing three active-record model: Team, Teamuser, users, testing on "has_many through" association.
basically, I just want to be able to call team.users and user.teams.
here are my model definitions
team.rb
#######
class Team < ActiveRecord::Base
has_many :teamusers, :foreign_key => :team_id
has_many :users, :through => :teamusers
end
and
teamuser.rb
###########
class Teamuser < ActiveRecord::Base
belongs_to :teams
belongs_to :users
end
then
user.rb
########
class User < ActiveRecord::Base
has_many :teamusers, :foreign_key => :user_id
has_many :teams, :through => :teamusers
end
every time I try this
team.users
it returns me an error saying "uninitialized constant Team::Users".
what might I be wrong he?
any advice would be very much appreciated.

Your Teamuser should be:
class Teamuser < ActiveRecord::Base
belongs_to :team
belongs_to :user
end

Related

issue with has_many, through association

For some reason, my has_many through association isn't working. Here are my models:
class Interest < ActiveRecord::Base
has_many :evints
has_many :events, through: :evints
has_many :images, through: :events
end
class Event < ActiveRecord::Base
has_many :evints
has_many :images
has_many :interests, through: :evints
end
class Evint < ActiveRecord::Base
belongs_to :events
belongs_to :interests
end
The Evints table has three columns: interest_id, event_id, and id.
When I call #interest.events, I get the error message
uninitialized constant Interest::Events
Obviously, there's something going wrong with the association if #interest.events is being read as a constant!
Does anyone have any ideas?
Thanks!
Check your Evint class, it should be:
class Evint < ActiveRecord::Base
belongs_to :event
belongs_to :interest
end
On a different note, I think Evint isn't really a very good name. It'd suggest that you go with EventInterest, and name the table event_interests.

Named many to many relations in Rails

How should I create following model in Rails 3.2? Project can have 1+ owners and 1+ users. Both of them are instances of class Person. I've thought about has_and_belongs_to_many but I don't know how to handle two separate collections of Persons for each Project.
You'll need a join model to represent each has-and-belongs-to-many relationship, and you would access using has-many-through as described here:
class ProjectOwnerLink < ActiveRecord::Base
belongs_to :project
belongs_to :owner, class_name: 'Person'
end
class ProjectUserLink < ActiveRecord::Base
belongs_to :project
belongs_to :user, class_name: 'Person'
end
class Project < ActiveRecord::Base
has_many :project_owner_links
has_many :owners, :through => :project_owner_links
has_many :project_user_links
has_many :users, :through => :project_user_links
end
class Person < ActiveRecord::Base
has_many :project_owner_links
has_many :owned_projects, :through => :project_owner_links, :source => :project
has_many :project_user_links
has_many :used_projects, :through => :project_user_links, :source => :project
end
You could define another model Participation that holds the type of the relationship, i.e. the role of the user. (Untested) code:
class Project < ActiveRecord::Base
has_many :participations
has_many :users, :through => :participations
def with_role(role)
includes(:participations).where('participation.role = ?', role)
end
def owners
users.with_role('owner')
end
def participants
users.with_role('participant')
end
end
 
class User < ActiveRecord::Base
has_many :participations
has_many :projects, :through => :participations
def with_role(role)
includes(:participations).where('participation.role = ?', role)
end
def projects_owned
projects.with_role('owner')
end
def projects_participating_in
projects.with_role('participant')
end
end
 
class Participation < ActiveRecord::Base
# has an attribute 'role'
belongs_to :project
belongs_to :user
end
Below is the demo application.
https://github.com/diatmpravin/habtm-demo.git
Please have a look, Let me know if you have any question?

How do you model "Likes" in rails?

I have 3 models: User, Object, Likes
Currently, I have the model: a user has many Objects. How do I go about modeling:
1) A user can like many objects
2) an Object can have many likes (from different users)
So I want to be able to do something like this:
User.likes = list of objects liked by a user
Objects.liked_by = list of Users liked by object
The model below is definitely wrong...
class User < ActiveRecord::Base
has_many :objects
has_many :objects, :through => :likes
end
class Likes < ActiveRecord::Base
belongs_to :user
belongs_to :object
end
class Objects < ActiveRecord::Base
belongs_to :users
has_many :users, :through => :likes
end
To elaborate further on my comment to Brandon Tilley's answer, I would suggest the following:
class User < ActiveRecord::Base
# your original association
has_many :things
# the like associations
has_many :likes
has_many :liked_things, :through => :likes, :source => :thing
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :thing
end
class Thing < ActiveRecord::Base
# your original association
belongs_to :user
# the like associations
has_many :likes
has_many :liking_users, :through => :likes, :source => :user
end
You are close; to use a :through, relation, you first must set up the relationship you're going through:
class User < ActiveRecord::Base
has_many :likes
has_many :objects, :through => :likes
end
class Likes < ActiveRecord::Base
belongs_to :user
belongs_to :object
end
class Objects < ActiveRecord::Base
has_many :likes
has_many :users, :through => :likes
end
Note that Objects should has_many :likes, so that the foreign key is in the right place. (Also, you should probably use the singular form Like and Object for your models.)
Here is a simple method to achieve this. Basically, you can create as many relationships as needed as long as you specify the proper class name using the :class_name option. However, it is not always a good idea, so make sure only one is used during any given request, to avoid additional queries.
class User < ActiveRecord::Base
has_many :likes, :include => :obj
has_many :objs
has_many :liked, :through => :likes, :class_name => 'Obj'
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :obj
end
class Obj < ActiveRecord::Base
belongs_to :user
has_many :likes, :include => :user
has_many :users, :through => :likes
# having both belongs to and has many for users may be confusing
# so it's better to use a different name
has_many :liked_by, :through => :likes, :class_name => 'User'
end
u = User.find(1)
u.objs # all objects created by u
u.liked # all objects liked by u
u.likes # all likes
u.likes.collect(&:obj) # all objects liked by u
o = Obj.find(1)
o.user # creator
o.users # users who liked o
o.liked_by # users who liked o. same as o.users
o.likes # all likes for o
o.likes.collect(&:user)
Models & associations as per naming conventions of rails modeling
class User < ActiveRecord::Base
has_many :likes
has_many :objects, :through => :likes
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :object
end
class Object < ActiveRecord::Base
belongs_to :user
has_many :likes
has_many :users, :through => :likes
end
Also, you can use of already built-in gems like acts-as-taggable-on to have same functionality without code :)

How to traverse multiple many to many associations in activerecord

I am building a authorization framework that will eventually use cancan at the code level. I am creating the model and associations and have things almost perfect, but I ran into a snag.
I have User, Roles and Rights with many to many join tables (user_roles and role_rights) and I have things setup so that you can do User.roles and User.roles.first.rights but I would like to be able to do User.rights
class User < ActiveRecord::Base
has_many :user_roles
has_many :roles, :through => :user_roles
end
class UserRole < ActiveRecord::Base
belongs_to :user
belongs_to :role
end
class Role < ActiveRecord::Base
has_many :user_roles
has_many :users, :through => :users_roles
has_many :role_rights
has_many :rights, :through => :role_rights
end
class RoleRight < ActiveRecord::Base
belongs_to :role
belongs_to :right
end
class Right < ActiveRecord::Base
has_many :role_rights
has_many :roles, :through => :role_rights
end
The following works:
User.roles
so does this:
User.roles.first.rights
but what I want to do is:
User.rights
but when I try, I get the follow error: NoMethodError: undefined method `rights'
I assume that I need to add something to the User model to let it transverse to the Right model but I can't figure out the associations.
I'm using Rails 2.3.4 and Ruby 1.8.7
Try something like this:
class User < ActiveRecord::Base
def self.rights
Right.joins(:roles => :user).all("users.id = ?", self.id)
end
end

Could not find the association problem in Rails

I am fairly new to Ruby on Rails, and I clearly have an active record association problem, but I can't solve it on my own.
Given the three model classes with their associations:
# application_form.rb
class ApplicationForm < ActiveRecord::Base
has_many :questions, :through => :form_questions
end
# question.rb
class Question < ActiveRecord::Base
belongs_to :section
has_many :application_forms, :through => :form_questions
end
# form_question.rb
class FormQuestion < ActiveRecord::Base
belongs_to :question
belongs_to :application_form
belongs_to :question_type
has_many :answers, :through => :form_question_answers
end
But when I execute the controller to add questions to application forms, I get the error:
ActiveRecord::HasManyThroughAssociationNotFoundError in Application_forms#show
Showing app/views/application_forms/show.html.erb where line #9 raised:
Could not find the association :form_questions in model ApplicationForm
Can anyone point out what I am doing wrong?
In the ApplicationForm class, you need to specify ApplicationForms's relationship to 'form_questions'. It doesn't know about it yet. Anywhere you use the :through, you need to tell it where to find that record first. Same problem with your other classes.
So
# application_form.rb
class ApplicationForm < ActiveRecord::Base
has_many :form_questions
has_many :questions, :through => :form_questions
end
# question.rb
class Question < ActiveRecord::Base
belongs_to :section
has_many :form_questions
has_many :application_forms, :through => :form_questions
end
# form_question.rb
class FormQuestion < ActiveRecord::Base
belongs_to :question
belongs_to :application_form
belongs_to :question_type
has_many :form_questions_answers
has_many :answers, :through => :form_question_answers
end
That is assuming that's how you have it set up.
You need to include a
has_many :form_question_answers
In your FormQuestion model. The :through expects a table that's already been declared in the model.
Same goes for your other models -- you can't supply a has_many :through association until you've first declared the has_many
# application_form.rb
class ApplicationForm < ActiveRecord::Base
has_many :form_questions
has_many :questions, :through => :form_questions
end
# question.rb
class Question < ActiveRecord::Base
belongs_to :section
has_many :form_questions
has_many :application_forms, :through => :form_questions
end
# form_question.rb
class FormQuestion < ActiveRecord::Base
belongs_to :question
belongs_to :application_form
belongs_to :question_type
has_many :form_question_answers
has_many :answers, :through => :form_question_answers
end
It looks like your schema might be a bit wonky, but the point is you always need to add the has_many for the join table first, then add the through.

Resources