I'm using rails_admin gem. It works fine when I open the admin panel from localhost but then I get this error whenever i tried to show the user inside rails admin panel.
ActiveRecord::StatementInvalid in RailsAdmin::Main#show
PG::UndefinedColumn: ERROR: column relationships.user_id does not exist
LINE 1: ...LECT "relationships".* FROM "relationships" WHERE "relations...
^
: SELECT "relationships".* FROM "relationships" WHERE "relationships"."user_id" = $1
I realised this error might come from my User model
class User < ActiveRecord::Base
has_many :relationships
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
end
relationship.rb
class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
end
I don't have any idea at all why at fist the error said the relationship.user_id does not exist. How can I fix this? Thanks in advance.
This is telling you that the relationships table underneath the Relationship model does not have a user_id column.
When you use the has_many association in the User model, then you need to have a user_id column in the relationships table per: http://guides.rubyonrails.org/association_basics.html#the-has-many-association
Examine the relationships table in the database to see the structure of the table. It would seem you need a migration to add the user_id column to that table.
Related
I have a data model - SeasonTeams with the following relation:
has_many :linked_team_constraints, class_name: 'LinkedTeamConstraints', dependent: :destroy
Then I have the LinkedTeamConstraints model as follows:
belongs_to :season_team, primary_key: :_id
Now when I call destroy on the SeasonTeam - thereby destroying the LinkedTeamConstraint - I get error column linked_team_constraints.season_team_id does not exist. I do have two OTHER columns labeled season_team_id_1 and season_team_id_2. How can I establish a has_many relationship such that linked_team_constraints.season_team_id_1 or ..._id_2 is queried instead of ...season_team_id.
Would it be something like:
has_many :linked_team_constraints... {where("_id == ?", linked_team_constraints.season_team_id_1 || linked_team_constraints.season_team_id_2)}?
You need to specify foreign_key for your relations and have separate relation for each key. Like:
has_many :linked_team_1_constraints, class_name: 'LinkedTeamConstraints', foreign_key: :season_team_id_1, dependent: :destroy
has_many :linked_team_2_constraints, class_name: 'LinkedTeamConstraints', foreign_key: :season_team_id_2, dependent: :destroy
I'm quite stuck in in Ruby on Rails relations and I really appreciate you help.
Have model User
class User < ActiveRecord::Base
has_many :followers, :through => :follows, foreign_key: "followee_id"
has_many :followees, :through => :follows, foreign_key: "follower_id"
end
and model Follow
class Follow < ActiveRecord::Base
belongs_to :followee, class_name: "User"
belongs_to :follower, class_name: "User"
end
but if want to create new follower like:
user.followers << User.first
the result is SystemStackError
Thank you for every help!
You have to try something like this:
class User < ActiveRecord::Base
has_many :follower_follows, foreign_key: :followee_id, class_name: "Follow"
has_many :followers, through: :follower_follows, source: :follower
has_many :followee_follows, foreign_key: :follower_id, class_name: "Follow"
has_many :followees, through: :followee_follows, source: :followee
end
Here follower_follows and followee_follows are join tables and source: :follower matches with the belong_to :follower identification in the Follow model and source: :followee matches with the belong_to :followee identification in the Follow model
I think this would work in your case
So in chapter 12 or Hartl's Railstutorial, we're building the ability for users to follow one another's "twitter" feeds. This is modeled as users forming relationships and we create a relationship model with a table that has a follower_id and a followed_id. Also in the model, we associate it with the user model as follows:
class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
end
We also associate the user model with the relationship model as follows:
class User < ActiveRecord::Base
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
I'm confused as to why we need to have has_many :following in the user model. It says in the tutorial that following someone is an active relationship, so why do we need to say users have many active relationships, and users are also following many (which is an active relationship). What exactly is has_many :following doing that has_many :active_relationships cannot do?
Also my second question is why the belongs_to is split into follower and followed, instead of just user. What do we gain by using two belongs_to instead of just one on the user?
It is a way to access the Users that are either following or being followed by a particular user instead of the relationships.
If you just had #user.active_relationships that would return back the relationships in the join table. But with #user.following you get an association array of User objects.
And as for your second question, a relationship between two users takes 2 objects not one, and would be pointless to have just a single belongs_to :user.
Ruby on Rails Guides - Associations | Has many :through
I don't get something in the last chapter of the Rails tutorial.
So the aim of this chapter to make friendships with other users, and that makes it a self referential association. (users have a relationship with other users)
So with the User model, there is the Friendship model, that acts as a through table.
And in the code, class User
class User < ActiveRecord::Base
has_many :microposts, dependent: :destroy
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
.
.
.
end
But I don't get this part:
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
We have to specify in the has_many :through association the table that we are going through (Relationship table). But in the above code there isn't an
:active_relationships or :passive_relationships table ,there's only a Relationship class.
The Relationship table:
class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
validates :follower_id, presence: true
validates :followed_id, presence: true
end
So, my question is, how does that work?
Tnx Tom
You are right you have just Relationship class.
In rails by default there will be has_namy :relationships then you don't have to specify the class name.
If you don't follow the rails default rules, then when you will try to with different association name , you have to specify the class name.
In your example
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
Here you specified to find active relationships from Relationship class.
The has_many :through refers to an association.
has_many :following, through: :active_relationships, source: :followed
The has_many :through refers to an association, not a table. The :source is a relationship in the class that that association refers to.
In this case
has_many :followers, through: :passive_relationships, source: :follower
refers to this relationship
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
And in the relationship class, there is a :follower that is the actual source for this object.
I want to select all Notices that belong to the Character via the has_one association that have a nil supernotice. How do I code this?
notice.rb:
belongs_to :character
has_one :active_comment_relationship, class_name: "Commentrelationship",
foreign_key: "commenter_id",
dependent: :destroy
has_one :supernotice, through: :active_comment_relationship,
class_name: "Notice",
source: :commentee
accepts_nested_attributes_for :active_comment_relationship
has_many :passive_comment_relationships, class_name: "Commentrelationship",
foreign_key: "commentee_id",
dependent: :destroy
has_many :comments, through: :passive_comment_relationships,
class_name: "Notice",
source: :commenter
character.rb:
has_many :notices
def topNotices
self.notices.where(supernotice: nil) # doesn't work
end
Logs:
: SELECT "notices".* FROM "notices" WHERE "notices"."character_id" = $1 AND "notices"."commentee_id" IS NULL ORDER BY "notices"."created_at" DESC
Completed 500 Internal Server Error in 316ms (ActiveRecord: 12.0ms)
ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column notices.commentee_id does not exist
LINE 1: ..."notices" WHERE "notices"."character_id" = $1 AND "notices"....
The logs show the error notices.commentee_id does not exist, but I've clearly stated in notice.rb that a notice has_one :supernotice through: :active_comment_relationship. Where am I going wrong?
You need to add:
has_many :notices
In your character model.
You have a problem in your association in the first place.
When you define associations between two models, you have to set up properly in both of the models.
In your notice.rb Model, you have belongs_to :character association, so you have to define the counterpart of this association in your character.rb Model as well. You have to define a has_many or has_one association in your Character model which in your case is has_many notices.
So, in your character.rb Model, you need to define this association:
has_many :notices
When you setup the associations in both the models properly, then you can expect to get the correct result using:
self.notices.where(supernotice: nil)
because now it knows how your Character model is associated with your Notice model.
I highly recommend you to read the Active Record Associations Guide