References in Rails using custom Name? - ruby-on-rails

So I am developing a rails app that will have two kinds of Users, student/tutor. but I only have one User model (using cancan for auth), so when I try to set up the meeting model (which has one tutor and one student) how do I do this? This is the model:
class Meeting < ActiveRecord::Base
belongs_to :student
belongs_to :tutor
attr_accessible :price, :subject, :time
end
and here's the relevant part of the schema:
create_table "meetings", :force => true do |t|
t.string "subject"
t.integer "student_id"
t.integer "tutor_id"
t.datetime "time"
t.integer "price"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "meetings", ["student_id"], :name => "index_meetings_on_student_id"
add_index "meetings", ["tutor_id"], :name => "index_meetings_on_tutor_id"
Without having to have two extra models containing student and tutor can I use those labels?

one way to do it..
class Meeting < ActiveRecord::Base
belongs to :student, class_name: 'User'
belongs to :tutor, class_name: 'User'
class User < ActiveRecord::Base
has_many :meet_with_students, class_name: 'Meeting', foreign_key: :tutor_id
has_many :students, through: :meet_with_students, source: :student
has_many :meet_with_tutors, class_name: 'Meeting', foreign_key: :student_id
has_many :tutors, through: :meet_with_tutors:, source: :tutor

I think you're looking for class_name:
class Meeting < ActiveRecord::Base
belongs_to :student, class_name: "User"
belongs_to :tutor, class_name: "User"
end

Related

How to implement multiple associations between models?

I have 4 models.
UserModel
SkillModel
UserSkillModel
PreferenceSkillModel
Association I used:
UserModel
has_many :skills, through: :user_skills
has_many :user_skills
has_many :skills, :through: :preference_skills
has_many :preference_skills
SkillModel
has_many :users, through: :user_skills
has_many :users_skills
has_many :users, :through: :preference_skills
has_many :preference_skills
UserSkillModel
belongs_to :user
belongs_to :skill
PreferenceSkillModel
belongs_to :user
belongs_to :skill
Schema:
create_table "preference_skills", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
t.integer "user_id", default: 0
t.integer "skill_id", default: 0
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "user_skills", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
t.integer "user_id"
t.integer "skill_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "skills", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
t.string "name", default: ""
t.integer "skill_count", default: 0
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
How can I implement this association in a correct way?
How can I implement this association in a correct way?
What is correct may depend on what you are trying to do. The following is correct, by naming separate associations for users-skills and users-preference_skills.
class User
has_many :user_skills
has_many :my_skills, through: :user_skills, class_name: 'Skill'
has_many :preference_skills
has_many :my_preference_skills, :through: :preference_skills, class_name: 'Skill'
...
end
class SkillModel
has_many :users_skills
has_many :direct_users, through: :user_skills, class_name: 'User'
has_many :preference_skills
has_many :preference_users, :through: :preference_skills, class_name: 'User'
...
end
If you want one collection with all the skills you need to use STI or polymorphism. Read the Rails Guides for more information.
I don't think there's a need for separate user_skills & preference_skills models.
You can use STI here like -
skill.rb
Skill < ApplicationRecord
end
user_skill.rb
UserSkill < Skill
end
preference_skill.rb
PreferenceSkill < Skill
end
Note: The Skill model that I've used is different from what you are assuming.
You might want to rename your current Skills model to more explainatory name like SkillDetail.
After this you can have your associations like -
class User < AR
has_many :skills
has_many :skill_details, through: :skills
end
class Skill < AR
belongs_to :user
belongs_to :skill_detail
end
class SkillDetail < AR
has_many :skills
has_many :users, through: :skills
end
P.S. Do some research on Single Table Inheritance (STI)
Hope this helps.
Also note that you got a downvote because this is a very vague question & you are directly asking to implement a business logic.

Rails model association for a soccer match. Match has two Country

Any suggestions on how to set up this relationship? A Match has two Country on each side, right?
However, Rails Admin is complaining that this is not the right way.
create_table "countries", force: true do |t|
t.string "name"
t.string "flag"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "matches", force: true do |t|
t.integer "country_a"
t.integer "country_b"
t.integer "score_country_a"
t.integer "score_country_b"
end
class Country < ActiveRecord::Base
belongs_to :matches
end
class Match < ActiveRecord::Base
belongs_to :country_side_a, foreign_key: :country_a
belongs_to :country_side_b, foreign_key: :country_b
end
How can I configure these relationships properly?
Here's how I ultimately set up the relations:
class Country < ActiveRecord::Base
has_many :matches_a, foreign_key: :country_a, class_name: "Match"
has_many :matches_b, foreign_key: :country_b, class_name: "Match"
end
class Match < ActiveRecord::Base
belongs_to :country_side_a, foreign_key: :country_a, class_name: "Country"
belongs_to :country_side_b, foreign_key: :country_b, class_name: "Country"
end
Country needs to have a has_one :matches, if you want a one to one mapping, or has_many :matches if you want a many to many relationship.
Have a read about how to set up a one to one/many relationship here:
http://guides.rubyonrails.org/association_basics.html#the-belongs-to-association

How do I specify foreign_key and class when using has_many :through?

How do I tell a has_many :through association which foreign_key and/or classto use?
I've tried every permutation of the above and usually receive: NoMethodError: undefined method 'relation_delegate_class' for "User":String
ActiveRecord::Schema.define(version: 20141031013511) do
create_table "messages", force: true do |t|
t.string "content"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "creator_id"
end
create_table "messages_views", force: true do |t|
t.integer "message_viewed"
t.integer "message_viewer"
end
create_table "shows_viewers", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true do |t|
t.string "username"
t.datetime "created_at"
t.datetime "updated_at"
end
end
class MessagesView < ActiveRecord::Base
belongs_to :message_viewed
belongs_to :message_viewer
end
class Message < ActiveRecord::Base
belongs_to :creator, class_name: 'User'
has_many :messages_views
has_many :message_viewers, through: :messages_views, class: 'User', foreign_key: 'message_viewer'
end
class User < ActiveRecord::Base
has_many :messages, foreign_key: 'creator_id'
has_many :messages_views
has_many :message_vieweds, through: :messages_views, class: 'Message', foreign_key: 'message_viewed'
end
This is the current state of the app.
I think the problem with the association table and your code should be like that :
class MessagesView < ActiveRecord::Base
belongs_to :message_viewed, class_name: 'Message'
belongs_to :message_viewer, class_name: 'User'
end
class Message < ActiveRecord::Base
belongs_to :creator, class_name: 'User'
has_many :messages_views, foreign_key: 'message_viewed', class_name: "messages_view"
has_many :message_viewers, through: :messages_views, class_name: 'User', foreign_key: 'message_viewer'
end
class User < ActiveRecord::Base
has_many :messages, foreign_key: 'creator_id'
has_many :messages_views, foreign_key: 'message_viewer', class_name: "messages_view"
has_many :message_vieweds, through: :messages_views, class_name: 'Message', foreign_key: 'message_viewed'
end

Can't create alias name for has_many :through

This is my Migration code:
1.User
create_table :users do |t|
t.string :name
t.string :password
t.string :department
t.timestamps
end
2.Ploy
create_table :ploys do |t|
t.string :name
t.string :state
t.string :description
t.string :location
t.float :spend
t.references :creator, index: true, class_name: "User"
t.timestamps
end
3.participants
def change
create_table :participants do |t|
t.belongs_to :ploy
t.belongs_to :user
t.timestamps
end
This is my Model code:
class User < ActiveRecord::Base
has_one :create_ploys, class_name: "Ploy"
has_many :participants
has_many :ploys, through: :participants, source: :join_ploys
end
class Ploy < ActiveRecord::Base
belongs_to :creator, class_name: "User"
has_many :participants
has_many :users, through: :participants, source: "joiners"
end
class Participant < ActiveRecord::Base
belongs_to :user
belongs_to :ploy
end
When i call user.join_ploys, but give me a error: NoMethodError: undefined method `join_ploys'
So i think maybe something is wrong about :source, But i don't know how to do.
so where are you defining a model or association for joiners and join_ploys? You can't just create a :source without defining what it is. Check out this SO: Need help to understand :source option of has_one/has_many through of Rails

Migration for Users Following Posts

In my application, I have models for Users and Projects.
I want users to have the ability to follow many projects. So users has_many projects, and projects belongs_to users that not only created them but users that follow them too.
So I generated a migration called ProjectRelationship and tried to make it flow below, but it doesn't seem to work. Can somebody help me fix my associations?
Thanks for the help!
project_relationship.rb
class ProjectRelationship < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
project.rb
belongs_to :user
has_many :project_relationships
has_many :followers, through: :project_relationships, source: :user
user.rb
has_many :projects
has_many :project_relationships
has_many :projects_followed, through: :project_relationships, source: :project
schema.rb
create_table "project_relationships", :force => true do |t|
t.integer "follower_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "projectuser_id"
end
add_index "project_relationships", ["follower_id"], :name => "index_project_relationships_on_follower_id", :unique => true
add_index "project_relationships", ["projectuser_id"], :name => "index_project_relationships_on_projectuser_id"
projects/show.html.erb
<%= #project.followers.count %>
You need to specify the foreign keys. The ProjectRelationship model will be expecting the corresponding table to have a "user_id" and "project_id" columns. However, you used different names. So either specify the foreign keys:
class ProjectRelationship < ActiveRecord::Base
belongs_to :user, foreign_key: "follower_id"
belongs_to :project, foreign_key: "projectuser_id"
end
or change the column names in your migration:
create_table :project_relationships do |t|
t.integer :user_id
t.integer :project_id
...
end
You will also need to specify the foreign key in your other models:
class Project < ActiveRecord::Base
belongs_to :user
has_many :project_relationships, foreign_key: "projectuser_id"
has_many :followers, through: :project_relationships, source: :user
end
class User < ActiveRecord::Base
has_many :projects
has_many :project_relationships, foreign_key: "follower_id"
has_many :projects_followed, through: :project_relationships, source: :project
end
#roma149 - Thanks for your response. I updated the controllers, routes, and what you said. No errors generate, but when I click the button follow in _follow.html.erb, it does not seem to follow the project or update the count "#project.followers.count"
Moved details to here: Why doesn't my user follow/unfollow button work?

Resources