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
Related
I am new learner. I just started learning more about Backend with Ruby on Rails.
I have the following tables - User and User_Transaction.
So basically I want to have a transaction which holds information about the sender and the receiver. This personally sounds to me more like a has_and_belongs_to_many relation. However, I am really confused in how to approach this and how should I include the 2 foreign keys.
I am curious to learn more about this and I will be really happy if someone helps me :).
Migrations
User
class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
t.integer :username
t.integer :password
t.timestamps
end
end
end
Transaction
class CreateTransactions < ActiveRecord::Migration[6.0]
def change
create_table :transactions do |t|
t.string :sender
t.string:receiver
t.decimal :amount
t.timestamps
end
end
end
Models
Transaction
class ::Transaction < ApplicationRecord
#We have two users per transaction 'Sender' and 'Receiver'
has_and_belongs_to_many :users
# belongs_to :sender, :class_name => 'User'
# belongs_to :receiver, :class_name => 'User'
end
User
class User < ApplicationRecord
# has_many :accounts
# has_many :transactions
has_and_belongs_to_many :transactions
end
how about this:
migrations
class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
t.string :username
t.string :password
t.timestamps
end
end
end
class CreateTransactions < ActiveRecord::Migration[6.0]
def change
create_table :transactions do |t|
t.references :sender, index: true, null: false, foreign_key: {to_table: :users}
t.references :receiver, index: true, null: false, foreign_key: {to_table: :users}
t.decimal :amount
t.timestamps
end
end
end
models
class User < ApplicationRecord
has_many :send_transactions, class_name: "Transaction", foreign_key: :sender, inverse_of: :sender
has_many :receive_transactions, class_name: "Transaction", foreign_key: :receiver, inverse_of: :receiver
end
class Transaction < ApplicationRecord
belongs_to :sender, class_name: "User", inverse_of: :send_transactions
belongs_to :receiver, class_name: "User", inverse_of: :receive_transactions
end
I am trying to make a many-to-many association in an RoR program, but I can't get rid of the error I mentioned in the title, the command I am using in the Rails console is:
User.find(1).attended_events = [Event.find(1)]
I need to solve this problem and can't find anywhere, I appreciate any help.
My code:
Models
class User < ApplicationRecord
has_many :created_events,class_name:"Event"
has_many :hosts
has_many :attended_events, through: :hosts
end
class Host < ApplicationRecord
belongs_to :attended_event, class_name:"Event"
belongs_to :attendee, class_name:"User"
end
class Event < ApplicationRecord
belongs_to :creator, foreign_key: :user_id, class_name:'User'
has_many :hosts
has_many :attendees, through: :hosts
end
Migration Files
class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
class CreateHosts < ActiveRecord::Migration[6.0]
def change
create_table :hosts do |t|
t.references :attendee, null: false, foreign_key: true
t.references :attended_event, null: false, foreign_key: true
t.integer :user_id
t.integer :event_id
t.timestamps
end
end
end
class CreateEvents < ActiveRecord::Migration[6.0]
def change
create_table :events do |t|
t.string :date
t.text :description
t.references :user, null: false, foreign_key: true
t.timestamps
end
end
end
Read about the foreign_key option for has_many.
class Event < ApplicationRecord
belongs_to :creator, foreign_key: :user_id, class_name:'User'
has_many :hosts
has_many :attendees, through: :hosts
end
These model associations are wrong, the error is in the second line.
class Event < ApplicationRecord
belongs_to :creator, foreign_key: :user_id, class_name:'User'
has_many :hosts
has_many :attendees, through: :hosts
end
With these model associations, you need to specify the foreign_key for the has_many :hosts statement.
class Host < ApplicationRecord
belongs_to :attended_event, class_name:"Event"
belongs_to :attendee, class_name:"User"
end
Here are my suggestions:
User
class User < ApplicationRecord
has_many :created_events, foreign_key: 'user_id'
has_many :hosts, foreign_key: 'attendee_id'
has_many :attended_events, through: :hosts
end
Host
class Host < ApplicationRecord
belongs_to :attended_event, class_name: 'Event'
belongs_to :attendee, class_name: 'User'
end
Event
class Event < ApplicationRecord
belongs_to :creator, class_name: 'User'
has_many :hosts, foreign_key: 'attended_event_id'
has_many :attendees, through: :hosts
end
Your hosts migration
Better avoid passing the foreign_key here, it will look for an attendees table and a attended_events table in the database.
class CreateHosts < ActiveRecord::Migration[6.0]
def change
create_table :hosts do |t|
# t.references :attendee, null: false, foreign_key: true
t.references :attendee, null: false
# t.references :attended_event, null: false, foreign_key: true
t.references :attended_event, null: false
t.timestamps
end
end
end
Define source on through association
class User < ApplicationRecord
has_many :created_events, class_name:"Event"
has_many :hosts
has_many :attended_events, through: :hosts, source: :event
end
class Host < ApplicationRecord
belongs_to :event
belongs_to :user
end
class Event < ApplicationRecord
belongs_to :creator, foreign_key: :user_id, class_name:'User'
has_many :hosts
has_many :attendees, through: :hosts, source: :user
end
class CreateHosts < ActiveRecord::Migration[6.0]
def change
create_table :hosts do |t|
t.references :user, null: false, foreign_key: true
t.references :event, null: false, foreign_key: true
t.timestamps
end
end
end
Then you can do
User.find(1).attended_events << Event.find(1)
Team, looking for some help for a very specific (newbie) situation on a Rails 4 association.
We have 3 models:
class Brand < ActiveRecord::Base
has_many :lines, dependent: :destroy
has_many :products, through: :lines, dependent: :destroy
end
class Line < ActiveRecord::Base
belongs_to :brand
has_and_belongs_to_many :products
end
class Product < ActiveRecord::Base
has_and_belongs_to_many :lines
has_many :brands, through: :lines
end
This configuration works well when trying to check for Products under specific Brand (or Line) and viceversa: different Brands (or Lines) available for a specific Product. However, when it comes to delete/destroy there is an issue. We are getting this Rspec error:
ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection:
Cannot modify association 'Brand#products' because the source reflection
class 'Product' is associated to 'Line' via :has_and_belongs_to_many.
We have made research on this exception, checked for Rails API, with no luck, examples found are showing a different model configuration. What's missing on this approach?
Appreciate your help guys!
In my opinion, it should be something like this:
class Brand < ActiveRecord::Base
has_many :lines, dependent: :destroy
has_many :products, through: :lines, dependent: :destroy
end
class Line < ActiveRecord::Base
belongs_to :brand
has_and_belongs_to_many :products
end
class Product < ActiveRecord::Base
belongs_to :brand, through: :line
has_and_belongs_to_many :lines
end
And in migrations:
create_table :brands , force: true do |t|
t.string :name
...
t.timestamps null: false
end
create_table :lines , force: true do |t|
t.string :name
t.belongs_to :brand
...
t.timestamps null: false
end
create_table :products , force: true do |t|
t.string :name
...
t.timestamps null: false
end
create_table :line_products, force: true, id: false do |t|
t.belongs_to :line, index: true
t.belongs_to :product, index: true
end
I hope it will help.
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
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