Rails: Association was not found; perhaps you misspelled it? - ruby-on-rails

I have a User model with a has_many :through relationship to the Publication model. The Publication model in turn has a has_many :through relationship to Author:
class User < ActiveRecord::Base
has_many :library_publications, :dependent => :destroy, :class_name => "Library::Publication"
has_many :publications, :through => :library_publications
end
class Library::Publication < ActiveRecord::Base
belongs_to :publication
belongs_to :user
end
class Publication < PublicationBase
has_many :library_publications, :dependent => :destroy, :class_name => "Library::Publication"
has_many :users, :through => :library_publications
has_many :publication_contributions, :dependent => :destroy, :class_name => "Publication::Contribution"
has_many :authors, :through => :publication_contributions
end
class Author < AuthorBase
has_many :publication_contributions, :dependent => :destroy, :class_name => "Publication::Contribution"
has_many :publications, :through => :publication_contributions
end
class Publication::Contribution < Publication::ContributionBase
belongs_to :publication, :class_name => "Publication"
belongs_to :author, :class_name => "Author"
end
As far as I can tell, all the associations are written correctly. However, when I try to eagerload authors from a user:
#user.library_publications.includes(:publication => [:authors])
I get this error:
Association named 'authors' was not found; perhaps you misspelled it?
What might be the cause of this?

After experimenting a little, I discovered that all of publication's associations were broken. This led to me to looking for larger problems, and eventually I discovered that this issue was caused by one of the join-table being namespaced, Library::Publication. When I de-namespaced it, publication's associations began working again.
I'm not sure why this happened, though. If anyone has an explanation, please share.

Related

Rails has_many through, issues with foreign key and source

A User has many subscribers and many publishers, both of which are users:
class User < ActiveRecord::Base
has_many :relationships, :foreign_key => "subscriber_id"
has_many :subscribers, :through => :relationships, :source => :subscriber
has_many :inverse_relationships, :class_name => "Relationship", :foreign_key => "publisher_id"
has_many :publishers, :through => :inverse_relationships, :source => :publisher
def subscribe_to(publisher)
self.relationships.create!(publisher_id: publisher.id, subscriber_id: id)
end
end
class Relationship < ActiveRecord::Base
belongs_to :subscriber, :class_name => "User"
belongs_to :publisher, :class_name => "User"
end
A user's publishers is who the user is subscribed to.
However, if I do john.subscribe_to(a_publisher), and then attempt to puts john.publishers, I get back an empty array.
I'm going back and forth randomly changing the foreign key and the source, hoping that it will eventually work, but something is off. What should the sources and foreign keys be here?
Update
Here's what I did to make it work:
class User < ActiveRecord::Base
has_many :relationships, :foreign_key => "publisher_id"
has_many :subscribers, :through => :relationships, :source => :subscriber
has_many :inverse_relationships, :foreign_key => "subscriber_id", :class_name => "Relationship"
has_many :publishers, :through => :inverse_relationships, :source => :publisher
def subscribe_to(publisher)
publisher.relationships.create!(subscriber_id: id)
end
end
First, I switched the foreign keys for both. Second, and this is the part I don't understand, I changed
self.relationships.create!(publisher_id: publisher.id)
to
publisher.relationships.create!(subscriber_id: id)
and it worked. For some reason, it doesn't work the other way around. Can anyone explain why?
Your association seems strange. You should try like this:
has_many :subscribers, :through => :relationships, :class_name => 'User'
And call :
john.subscribers.create(a_publisher)
Nowhere you're saying that subscriber is a User. I think your problem comes from here.
Maybe you can try with: :source => :user

Finding the repliers to a comment from a polymorphic comments model

I have this polymorphic association where a user can have many comments, a school can have many comments, and a comment can have many comments (or in my naming case replies):
class Comment < ActiveRecord::Base
attr_accessible :content
has_many :replies, :as => :commentable, :class_name => "Comment" # replies to comments
belongs_to :commentable, :polymorphic => true
belongs_to :commentor, :class_name => "User", :foreign_key => "user_id"
end
class User < ActiveRecord::Base
has_many :comments, :as => :commentable
has_many :commentors, # all users who commented on a user
:through => :comments,
:source => :commentor
end
class School < ActiveRecord::Base
has_many :comments, :as => :commentable
has_many :commentors, # all users who commented on a school
:through => :comments,
:source => :commentor
end
In the User, I can retrieve all who commented on a user using #user.commentors. Same goes for School, i.e. #school.commentors.
For the comments model, I would like to acheive the same thing for the Comments model where I can find all the commentors (or I guess repliers) to a comment; however, I have no idea what kind of association to create since a has_many :through association will not work like how it worked for the User and School model.
Use this:
has_many :reply_commentors, :through => :replies, :source => :commentor

Trouble on deleting "associated" model instances

I am using Ruby on Rails 3.1.0 and I would like to know why database records in the following example are not deleted on destroying an "associated" model instance.
In my application I have these classes:
class User < ActiveRecord::Base
has_one :account,
:autosave => true,
:dependent => :destroy
has_many :article_relationships,
:class_name => 'ArticleUserRelationship',
:foreign_key => 'user_id',
:autosave => true,
:dependent => :destroy
has_many :articles,
:through => :article_relationships,
:source => :article,
:dependent => :destroy
...
end
class ArticleRelationship < ActiveRecord::Base
belongs_to :user
...
end
class Account < ActiveRecord::Base
belongs_to :user,
:autosave => true,
:dependent => :destroy
end
If I run #article.user.destroy or #article.user.account.destroy methods (note: article is kind of Article) those will delete from the database the user, the account and article relationship records but will not delete users related articles, even if I state has_many :articles ... :dependent => :destroy.
Anyway I read the official RoR guide about the "has_many Association Reference" and at the 4.3.2.6 :dependent chapter it says:
This option (:dependent) is ignored when you use the :through option on the association.
So, what could/should I make in order to delete all user articles? That is, what method could/should I run? How?

Trying to design a controller to display courses (Rails)

Below are the models that are relevant to my problem. I am attempting to design a way to display CourseEnrollments along with their steps to a given patient. Here is what I have come up with so far.
INDEX ACTION - /course_enrollments/ --> Display courses user is enrolled in as well as the most recent course overview. This can redirect to most recent course.
SHOW ACTION - /course_enrollments/:id --> Display courses user is enrolled in as well as the most recent course overview
The part I am struggling to figure out is how to display an individual step for a course. Should this be done in the course_steps controller (which is nested inside the courses resource)?
class Course < ActiveRecord::Base
belongs_to :course_category
belongs_to :client
belongs_to :user_created, :foreign_key => :user_created_by, :class_name => "User"
belongs_to :user_updated, :foreign_key => :user_last_updated_by, :class_name => "User"
has_many :course_steps, :dependent => :destroy
has_many :steps, :through => :course_steps
has_many :course_requests, :dependent => :destroy
has_many :course_enrollments, :dependent => :destroy
has_many :patients, :through =>:course_enrollments
end
class CourseStep < ActiveRecord::Base
belongs_to :step
belongs_to :course
validates_uniqueness_of :step_id, :scope => :course_id
end
class Step < ActiveRecord::Base
belongs_to :step_type
belongs_to :client
has_one :step_quiz, :dependent => :destroy
has_one :step_survey, :dependent => :destroy
has_one :step_text, :dependent => :destroy
has_one :step_download, :dependent => :destroy
has_one :step_video, :dependent => :destroy
has_one :step_presentation, :dependent => :destroy
has_many :course_steps, :dependent => :destroy
has_many :courses, :through => :course_steps
end
class CourseEnrollment < ActiveRecord::Base
belongs_to :patient
belongs_to :course
end
class Patient < ActiveRecord::Base
belongs_to :user, :dependent => :destroy
has_many :enrollments, :dependent => :destroy
has_many :clients, :through => :enrollments
has_many :course_requests, :dependent => :destroy
has_many :course_enrollments, :dependent => :destroy
has_many :courses, :through => :course_enrollments
end
The usual approach is to nest these and have a compound sort of path, but how you route these things is often dependent on the level of context involved. For instance, is the display of a course driven by a user to the degree that the path should have the user in it, or is it a case of simply personalizing the course page?
Typically you see things like this:
resources :courses do |course|
course.resources :enrollments
course.resources :steps
end
There's usually a correlation between your has_many relationships and declaring an equivalent resources but not always.
Have a look at the generated routes using rake routes to see what the parameters will be called when passed to your controller, as well as what the expected controller name will be. You can customize the name of the controller by passing in a :controller option to the route.
Typically the last record in the path is passed in as :id whereas the prior ones are named, such as :course_id. This is a somewhat annoying inconsistency, so do be careful to check you're loading using the correct parameters.
If you need to display an individual step for a course, you definitely need to use the course_steps controller, logic being, each CourseStep object is a combo of one-course and one-step.

Rails, has_many polymorphic association to one model

I would like to have one model (event) that has multiple polymorphic HABTM associations to the same user model.
It should work something like this:
Event < ActiveRecord::Base
has_many :admin_users, :through => :event_users, :source => :userable, :source_type => 'User'
has_many :participating_users, :through => :event_users, :source => :userable, :source_type => 'User'
has_many :paid_users, :through => :event_users, :source => :userable, :source_type => 'User'
has_many :done_users, :through => :event_users, :source => :userable, :source_type => 'User'end
class EventUser < ActiveRecord::Base
belongs_to :userable, :polymorphic => true
belongs_to :event
end
User < ActiveRecord::Bas
has_many :event_users, :as => :userable
has_many :events, :through => :event_users
end
This almost works!! The problem is though that userable_type gets the type "User" for all diffrent associations. Is it possible to solve this?
I'm afraid your associations look totally wrong. First of all, if you have a 'has_many' on one side of a association, you have to have a 'belongs_to' on the other side. Secondly, I'm guessing done_user, admin_user etc inherit from User. Am i correct ?
And how different are participating_user, admin_user etc different from each other? Do you really need classes for each of these, can you make do with named scopes?
I would suggest you simplify your data model.
Right now your modeling looks fuzzy. Please do elaborate.
EDIT
Honestly, I think your modeling is over complicated. If I were you, given your descriptions of *_users, I would just have named scopes to retrieve that type of an user. So in effect
class Event < ActiveRecord::Base
has_many :event_users
has_many :users, :through => :event_users
end
class User < ActiveRecord::Base
has_many :event_users
has_many :events, :through => :event_users
end
So now, write named scopes in your User model to retrieve *_user.
Here's an excellent screencast on named_scopes.

Resources