I have these 3 classes:
User:
class User < ActiveRecord::Base
end
UserStory:
class UserStory < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
belongs_to :assigned, class_name: 'User'
belongs_to :board
has_many :comments
has_many :watched_stories
has_many :watchers, through: :watched_stories, source: :user
end
WatchedStory:
class WatchedStory < ActiveRecord::Base
belongs_to :user
belongs_to :story, class_name: 'UserStory'
end
when I try to list all watchers via UserStory#watchers I see this error:
PG::UndefinedColumn: ERROR: column watched_stories.user_story_id does not exist
It seems like the relation has_many through is wrong, but I can see the error. What am I missing here?
My migration:
class CreateWatchedStories < ActiveRecord::Migration
def change
create_table :watched_stories do |t|
t.references :user, index: true
t.references :story, index: true, references: :user_story
t.timestamps
end
end
end
If WatchedStory and UserStory are connected through story_id you need to specify that, otherwise Rails will assume it's user_story_id:
class WatchedStory < ActiveRecord::Base
belongs_to :story, class_name: 'UserStory', foreign_key: :story_id
end
class UserStory < ActiveRecord::Base
has_many :watched_stories, foreign_key: :story_id
end
PG::UndefinedColumn: ERROR: column watched_stories.user_story_id does
not exist
Rails is looking for a column called user_story_id which didn't exist in your watched_stories table.
Reason
You have this line belongs_to :story, class_name: 'UserStory' in WatchedStory model,so with class_name specified as UserStory,Rails will look for user_story_id by default.
Fix
The error could be resolved by setting foreign_key option in your WatchedStory model
class WatchedStory < ActiveRecord::Base
belongs_to :user
belongs_to :story, class_name: 'UserStory',foreign_key: :story_id
end
Related
Hello I try to do a has_many through relation but it's not working as I expect.
Here are my models
def User < ApplicationRecord
has_many :user_roles, class_name: "UserRole"
has_many :roles, through: :user_roles
end
def Role < ApplicationRecord
has_many :user_roles, class_name: "UserRole"
has_many :users, through: :user_roles
end
def UserRole < ApplicationRecord
belongs_to :user
belongs_to :role
end
When I do this in rails console
User.roles
I've got the following error
ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR: relation "user_roles" does not exist)
I'm stuck with this error since 2 hours and no google result helped me ...
EDIT:
Here is my migration
class CreateUserRole < ActiveRecord::Migration
def change
create_table :user_role do |t|
t.belongs_to :user, type: :uuid
t.belongs_to :role, type: :uuid
end
end
end
I have a table Atribuition with 2 references from User table.
class Attribuition < ApplicationRecord
belongs_to :user, class_name: 'User', foreign_key: 'user_id'
belongs_to :not_rated, class_name: 'User', foreign_key: 'not_rated_id'
end
The User model:
class User < ApplicationRecord
has_many :attribuitions, dependent: :destroy
end
When i destroy an user marked in not_rated i want it to be destroyed, but it just happens when i destroied an user marked as user_id, then the attribute row is deleted. I wanna make dependent:: destroy to work for many references of same model. That is possible?
My migration is:
class CreateAttribuitions < ActiveRecord::Migration[5.2]
def change
create_table :attribuitions do |t|
t.references :user
t.references :not_rated, index: { unique: true }
t.timestamps
end
end
end
Edit:
First you do following change as rails use convention over configuration
class Attribuition < ApplicationRecord
- belongs_to :user, class_name: 'User', foreign_key: 'user_id'
+ belongs_to :user
end
Changes needed
When you mention has_many :attribuitions, dependent: :destroy by side of User model class_name will be Attribuition and foreign_key will be user_id stored in attributions table.
So if you need to destroy attribuitions related by foreign_key not_rated_id & user_id then you need following changes.
class User < ApplicationRecord
has_many :attribuitions, dependent: :destroy # default foreign_key is user_id
has_many :not_rated_attribuitions, foreign_key: 'not_rated_id', dependent: :destroy
end
In my Rails 5.2 application I want to reference another Model. I have the following setup in the application:
class SomeModule::AnotherModule::User < ApplicationRecord
has_many :phones
end
class Phone < ApplicationRecord
belongs_to :user, optional: true, class_name: '::SomeModule::AnotherModule::User'
end
The migration was done like so:
add_reference :phones, :user, foreign_key: true, index: true
Now, when I try to call upon the user from a phone I get this:
Phone.first.user
#=> NameError: uninitialized constant User::Phone
from /home/testuser/.rvm/gems/ruby-2.5.1/gems/activerecord-5.2.0/lib/active_record/inheritance.rb:196:in `compute_type'
Removing the class_name: attribute does not change anything.
What am I doing wrong?
class SomeModule::AnotherModule::User < ApplicationRecord
has_many :phones, class_name: 'Phone', foreign_key: 'user_id'
end
class Phone < ApplicationRecord
belongs_to :user, optional: true, class_name: 'SomeModule::AnotherModule::User', foreign_key: 'user_id'
end
i have two class User and Bug there are two foreign keys in bug which are referencing to user_id ..the problem is that how i store user_id in foreign key column while creating the record.like for example if user enter bug then his id store in buger_id colunm.
class Bug
belongs_to :buger, class_name: "User", foreign_key: "buger_id"
belongs_to :developer , class_name: "User", foreign_key: "developer_id"
class user
has_many :created_bugs, class_name:"bugs"
has_many :developed_bugs, class_name:"bugs"
You need to add the foreign_key to the has_many declaration!
class User < ActiveRecord::Base
has_many :created_bugs, class_name: 'Bug' , foreign_key: :buger_id
has_many :developed_bugs, class_name: 'Bug' , foreign_key: :developer_id
end
class Bug < ActiveRecord::Base
belongs_to :buger, class_name: 'User'
belongs_to :developer , class_name: 'User'
end
See also: http://guides.rubyonrails.org/association_basics.html
You can specify class and foreign key on the has_many line as well.
has_many :created_bugs, class_name:"Bug", foreign_key: 'buger_id'
has_many :developed_bugs, class_name:"Bug", foreign_key: 'developer_id'
In Rails 5.1 or greater you can do it like this:
Migration
class CreateBug < ActiveRecord::Migration
def change
ccreate_table(:bugs) do |t|
t.references :bugger, foreign_key: { to_table: 'users' }
t.references :developer, foreign_key: { to_table: 'users' }
end
end
end
This will create the fields bugger_id, and developer_id and make the database level references to the users table
Models
class Bug < ActiveRecord::Base
belongs_to :bugger, class_name: "User"
belongs_to :developer, class_name: "User"
end
class User < ActiveRecord::Base
has_many :created_bugs, class_name: "Bug", foreign_key: "bugger_id"
has_many :developed_bugs, class_name: "Bug", foreign_key: "developer_id"
end
FactoryBot
If you use FactoryBot then your factory might look something like this:
FactoryBot.define do
factory :bug do
association :bugger, factory: :user
association :developer, factory: :user
end
end
I'm trying to create an app where a user chooses volunteers to complete their task. The way that volunteers are considered participants is through the selected boolean attribute placed on the TaskVolunteer join table. Unfortunately when I try to find the participants of a particular class I get the following error:
task = Task.create
task.participants
SQLite3::SQLException: no such column: users.selected
Models
class User < ActiveRecord::Base
has_many :owned_tasks, class_name: "Task", foreign_key: :owner_id
has_many :task_volunteers, as: :volunteer
has_many :volunteered_tasks, through: :task_volunteers
end
class TaskVolunteer < ActiveRecord::Base
# task_id, volunteer_id, selected (boolean)
belongs_to :task
belongs_to :volunteer, class_name: "User", foreign_key: :volunteer_id
end
class Task < ActiveRecord::Base
# owner_id
has_many :task_volunteers
has_many :volunteers, through: :task_volunteers, source: :volunteer
has_many :participants, -> {where(selected: true)}, through: :task_volunteers, source: :volunteer
belongs_to :owner, class_name: "User"
end
The error is caused by a faulty foreign_key option in TaskVolunteer.
belongs_to :volunteer, class_name: "User", foreign_key: :volunteer_id
foreign_key here refers to the column on the users table not on tasks_volunteers. You can just remove the foreign key option.
class TaskVolunteer < ActiveRecord::Base
# task_id, volunteer_id, selected (boolean)
belongs_to :task
belongs_to :volunteer, class_name: "User"
end
Added
I have to say though by altering the naming a bit and using an enum to denote status you could cut the code and cognitive complexity quite dramatically.
class User < ActiveRecord::Base
has_many :participations, foreign_key: :participant_id
has_many :owned_tasks, class_name: "Task", as: :owner
end
class Task < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
has_many :participations
has_many :participants, through: :participations, source: :participant
# Dynamically generates relations such as 'selected_participants'
Participation.statuses.keys.each do |status|
has_many "#{status}_participants".to_sym,
-> { where(participations: { status: status.to_sym }) },
through: :participations,
source: :participant
end
end
class Participation < ActiveRecord::Base
belongs_to :task
belongs_to :participant, class_name: "User"
enum status: [:interested, :selected]
end
The enum macro gives you stuff like:
user.participations.selected
participation.selected?