I have those two Models, in a HABTM Relationship:
The Project is using Rails 4, so no attr_accessible tags
wine.rb
class Wine < ActiveRecord::Base
has_and_belongs_to_many :pairings, class_name: 'Food', join_table: 'foods_wines', association_foreign_key: 'food_id'
has_many :images, as: :attachable, class_name: 'Asset', dependent: :delete_all
end
food.rb
class Food < ActiveRecord::Base
has_and_belongs_to_many :wines, class_name: "Wine", join_table: "foods_wines", foreign_key: "food_id"
end
I created the Join Table with this migration:
create_table(:foods_wines, :id => false) do |t|
t.integer :food_id
t.integer :wine_id
end
add_index :foods_wines, [:food_id, :wine_id]
When I try to create the new Relation in the Rails Console, it does not seem to be saving the HABTM Relationship.
#wine.pairings.create(:name => "Seafood")
it does not seem to be saving the HABTM Relation -> When I restart the console, the relation is gone - I also checked inside the DB, where I get an empty table for the foods_wines table.
Am I missing something crucial here?
I think, you have to replace :
has_and_belongs_to_many :pairings, class_name: 'Food', join_table: 'foods_wines', association_foreign_key: 'food_id'
with :
has_and_belongs_to_many :pairings, class_name: 'Food', join_table: 'foods_wines', foreign_key: 'wine_id'
in wine.rb, because you have to specify the foreign key of this class (Wine).
Related
class QuestionSet
has_and_belongs_to_many :questions,
class_name: 'Exam',
join_table: 'question_question_sets',
foreign_key: 'question_set_id',
association_foreign_key: 'question_id'
end
class Question
has_and_belongs_to_many :question_sets,
class_name: 'Exam',
join_table: 'question_question_sets',
foreign_key: 'question_id',
association_foreign_key: 'question_set_id'
end
The above models are inherited from the base model Exam(using rails STI) and the join table contains two fields: question_id and question_set_id. Now I need to convert this association into has_many through.
I have tried as follows:
class QuestionQuestionSet
has_many :questions
has_many :question_sets
end
class Question
has_many :question_question_sets, foreign_key: :question_id
has_many :question_sets, through: :question_question_sets
end
class QuestionSet
has_many :question_question_sets, foreign_key: :question_set_id
has_many :questions, through: :question_question_sets
end
Even after editing your models, it's necessary to create a new join table since the previous one (created by habtm) doesn't have and "id" column.
As a reference you can follow the steps indicated in http://www.chrisrolle.com/en/blog/migration-path-from-habtm-to-has_many-through
I am having problems creating this association: Consider a model "Entry". I want entries to have many entries as parents and I want entries to have many entries as children. I want to realize this relation via a model I called "Association", so here is what I tried:
Migration:
class CreateAssociations < ActiveRecord::Migration[5.0]
def change
create_table :associations do |t|
t.integer :parent_id
t.integer :child_id
end
end
end
Association model:
class Association < ApplicationRecord
belongs_to :parent, class_name: 'Entry'
belongs_to :child, class_name: 'Entry'
end
so far it works. But now how do I use this to create two many-to-many relations on a model to itself?
class Entry < ApplicationRecord
# has many parent entries of type entry via table associations and child_id
# has many child entries of type entry via table associations and parent_id
end
This should work:
class Entry < ApplicationRecord
has_and_belongs_to_many :parents, class_name: 'Entry', join_table: :associations, foreign_key: :child_id, association_foreign_key: :parent_id
has_and_belongs_to_many :children, class_name: 'Entry', join_table: :associations, foreign_key: :parent_id, association_foreign_key: :child_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 have a problem related with this association. A pasted code is better than any title:
table.rb
class Table < ActiveRecord::Base
has_and_belongs_to_many :clients, class_name: 'User'
has_and_belongs_to_many :managers, class_name: 'User'
end
user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :tables
end
migration - join table
class UsersToTable < ActiveRecord::Migration
def change
create_table :tables_users, id: false do |t|
t.references :user, as: :client
t.references :user, as: :manager
t.references :table
end
end
end
Problem
tab = Table.new
tab.save
tab.clients.create
tab.clients.create
tab.clients.create
tab.managers.create
tab.managers.size # == 4
tab.clients.size # == 4
When I creating associated Objects(Users) they all are linked to both clients and managers.
I want to be able to create them separately - When creating a client - only number of clients rise, when creating manager, only number of managers rise.
In other words I want this:
tab.managers.size # == 1
tab.clients.size # == 3
Could you please help?
has_and_belongs_to_many :stuff, class_name: 'StuffClass' is just DSL for:
has_many "<inferred_join_table_name>"
has_many :stuff, through: "<inferred_join_table_name>"
It seems that since clients and managers are names for Users, the inferred join table get's to be "TablesUsers", and that is not right.
Try specifyng the join table for both and using different join tables for each relationship:
class Table
has_many :tables_clients
has_many :clients, through: :tables_clients
has_many :tables_managers
has_many :clients, through: :tables_managers
end
class TablesClients
belongs_to :client, class_name: 'User'
belongs_to :table
end
create_table :tables_clients, id: false do |t|
t.references :client, index: true
t.references :table, index: true
end
# and the same for tables_managers
Then the user belongs to Tables in too different ways:
class User
has_many :client_tables_users, class_name: 'TablesUsers', foreign_key: :client_id
has_many :tables_as_client, through: :client_tables_users, source: :table
has_many :managed_tables_users, class_name: 'TablesUsers', foreign_key: :manager_id
has_many :managed_tables, through: :managed_tables_users, source: :table
end
I'm looking to set up a self-referencing has_and_belongs_to_many relationship using rails 4, with a postgres db.
Basically I've got a Single Inheritance Table set up called Resource, which holds People, Places, and Things in it. (This works beautifully.)
create_table :resources do |t|
t.string :name
t.string :type
t.text :description
end
I'm trying to create a 'has_and_belongs_to_many' relationship so that each Resource can have a series of 'owners', which will be an Relation of People. Each Person, in turn, will have a series of 'possessions'. Since it's a single table, I'll need to join the Resource table to itself.
My migration for the join table looks like this:
create_table :owners_possessions, id: false do |t|
t.integer :owner_id # the id of a person
t.integer :possession_id # the id of a place/thing owned by that person
end
Person.rb:
class Person < Resource
has_and_belongs_to_many :possessions, class_name: :resources,
join_table: :owners_possessions,
foreign_key: :owner_id,
association_foreign_key: :possession_id
end
Resource.rb:
class Resource < ActiveRecord::Base
has_and_belongs_to_many :owners, class_name: :people,
join_table: :owners_possessions,
association_foreign_key: :possession_id,
foreign_key: :owner_id
end
However, when running Resource.find(x).owners in the console, I get the following error message:
ActiveRecord::StatementInvalid: Could not find table 'resources_resources'
Which is perturbing because everything I've searched so far has pointed toward the join_table option as a way to get it looking at the right table.
Furthermore, running `Person.find(x).possessions' yields
NameError: uninitialized constant Person::Possession
What might I be missing here?
I can't reproduce the errors you posted, I suppose you altered your code somewhat.
Anyway, the class_name option in your associations should be the exact name of the other model. So 'Person' in singular form rather than :people:
class Person < Resource
has_and_belongs_to_many :possessions,
class_name: 'Resource',
join_table: :owners_possessions,
foreign_key: :possession_id,
association_foreign_key: :owner_id
end
class Resource < ActiveRecord::Base
has_and_belongs_to_many :owners,
class_name: 'Person',
join_table: :owners_possessions,
association_foreign_key: :possession_id,
foreign_key: :owner_id
end
Notice I also swapped the :foreign_key and :association_foreign_key values so they return the appropriate records.