I want to access the table "Words" from the "linked_to" column, and not from "id" column.
The INNER JOIN query created by Rails always search for the id column in the Words table.
This is what I want to do :
From the Class Point,
Do an inner join to "linked_to" column (I already specify the :foreign_key)
"Linked_to" is not unique in the "Words" table, because there is one line per translation
Filter (Select) in the Words table, the value corresponding to my current language (let's assume dictionnary = 1)
My current Model
class Word < ActiveRecord::Base
has_and_belongs_to_many :points, :foreign_key => "linked_to"
belongs_to :dictionnary
attr_accessible :lang, :value, :dictionnary_id, :language_id, :linked_to
end
class Point < ActiveRecord::Base
has_and_belongs_to_many :words, :association_foreign_key => "linked_to"
belongs_to :priority
attr_accessible :edited_by
end
It's called convention. :) You have created the wrong associations, beginning with your design.
The has_and_belongs_to_many creates a relation between two models, thus using their primary key. Rethink your models: the dictionary_id field does not belong to Words, but is a additional field for the intermediate table. When you 'qualify' the intermediate table, you cannot use HASB anymore. Use a normal intermediate table
WordPointsForDictionary:
belongs_to :word
belongs_to :point
belongs_to :dictionary
Word:
has_many :points, :through => :WordPointsForDictionary
has_many :wordpointsfordictionary
Point:
has_many :words, :through => :WordPointsForDictionary
has_many :wordpointsfordictionary
This way you have removed the repetition and ugly relationships from you models. Clean primary key relationships and that will help you on the long way very much.
Related
So basically I like to know what association i need to link my routes table with employees table. I have a routes table with an employees column (array type) which holds employee id's. I also have an employee table that has (first_name, last_name, phone_number).
A has_many :employees, foreign_key: :employees, class_name: :Employee does not work and gives an error. Any ideas?
This error is given
ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column employees.employees does not exist)
LINE 1: SELECT "employees".* FROM "employees" WHERE "employees"."emp...
Using an array column here is a just bad idea:
Violates first normal form.
Doesn't let you use foreign keys to maintain referential integrity.
Doesn't work with ActiveRecord assocations that expect you to model your data in a sane way.
You will need to write queries by hand.
Instead you most likely want is a self-referential assocation:
class AddManagerToEmployees < ActiveRecord::Migration[6.1]
def change
add_reference :employees, :manager,
null: true,
foreign_key: { to_table: :employees }
end
end
class Employee < ApplicationRecord
belongs_to :manager,
class_name: 'Employee'
has_many :subordinates,
class_name: 'Employee',
foreign_key: :manager_id
end
If the manager-employee relation should be many to many instead of one to many use a join table.
Let us consider the below model.
User{ id:number(primary_key), column1:string, column2:string)
Now, the column1 can be any string, but column2 can be either null, or have values from column1. However column1 and column2 can't be same. I.E. column2 will be the foreign key and it will reference column1.
How will i create a has_one relationship with these constraints.
Something like,
has_one :master_agreement, :class_name => 'User', :foreign_key => 'column2', :primary_key => 'column1'
but the above mentioned doesn't work for me.
To setup a self-joining relationship in rails you want to use belongs_to not has_one as the key difference is that belongs_to places the foreign key column on the model's table - while has_one places it on the other end.
class User < ActiveRecord::Base
belongs_to :company # references users.company_id
has_one :company # references companies.user_id
end
Lets consider a system where you have a hierarchy of categories:
class Category < ActiveRecord::Base
belongs_to :parent, class_name: 'Category'
has_many :subcategories, class_name: 'Category', foreign_key: 'parent_id'
end
This creates a self joining relationship with the categories.parent_id foreign key column which references categories.id.
While you could potentially use something different than categories.id as the reference you are just making things harder on yourself as the id column already is an indexed primary key column.
I have a has many through relationship in a model that is self referencing. In the join table I also have an extra column that defines the source of the relationship. When adding a new object to that relationship I'd like to avoid duplicates in the join table based on the user_id, friend_id, and source_id
User Model
class User < ActiveRecord::Base
has_many :friendships
has_many :friends, :class_name => "User", :through => :friendships
end
Join Model
class Friendship < ActiveRecord::Base
attr_accessible :friend_id, :user_id, :source_id, :alert, :hide
# Relationships
belongs_to :user
belongs_to :friend, :class_name => "User"
has_one :source
end
I understand that I can do this
unless user.friends.include?(newFriend)
user.friendships.build(:friend_id => friendUser.id, :source_id => source.id)
end
But that seems like it will check to see if the new user exists in the current user's friends. I need to check on the join model level and make sure that the connection doesn't exist with the given source id.
I know there are several ways to accomplish this, but I'm pretty new to ruby on rails and am looking for the "rails way" to do it.
You can validate based on multiple columns in your intermediate table like this:
validates_uniqueness_of :user_id, :scope => [:friend_id, :source_id]
I have two tables with has_and_belongs_to_many relationship: categories and raw_categories
Should the table be called categories_raw_categories?
Yes, the join table is named after the two tables to be joined listed in alphabetical order. Since categories is higher in the alphabet than raw_categories, the join table is called categories_raw_categories. Note that if you are doing migrations, you need to create a separate migration for this join table.
See here for more details on HABTM relationships and the join tables required for them: http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_and_belongs_to_many
Also note that you can set a custom name for the join table if you want. Example (if you want to call the join table category_associations):
# Category model
has_and_belongs_to_many :raw_categories, :join_table => 'category_associations'
# RawCategory model
has_and_belongs_to_many :categories, :join_table => 'category_associations'
You can also always explicitly make the join table a first-class model by using has_many :though on the models to be joined. Following the example above, you could make CategoryAssociation an actual model and join it to the other two like this:
# CateogoryAssociation model
belongs_to :category
belongs_to :raw_category
# Category model
has_many :category_associations
has_many :raw_categories, :through => :category_associations
# RawCategory model
has_many :category_associations
has_many :categories, :through => :category_associations
Alright, so here's the deal. I have two tables and a join table since it's a many-to-many relationship. I have an order and an order can have many products. Obviously it goes the other way since products can be on many orders. I've got the following classes:
class Order < ActiveRecord::Base
has_many :orders_products
has_many :products, :through => :orders_products
end
class OrderProduct < ActiveRecord::Base
belongs_to :order
belongs_to :product
end
class Product < ActiveRecord::Base
has_many :orders_products
has_many :orders, :through => :orders_products
end
I'm getting a page to display and I'm able to enter stuff and when I go to interact with the products on the saved order via #order.products I'm getting the following error:
SQLite3::SQLException: no such table: order_products: SELECT "products".* FROM "products" INNER JOIN "order_products" ON "products".id = "order_products".product_id WHERE (("order_products".order_id = 1))
My join table is named orders_products, but as you can see it's trying to join through order_products. My limited knowledge of Rails naming conventions tells me that orders_products is the correct way to name it, and then name my model as OrderProduct. I'm really pounding my head against a wall on this one.
EDIT: I see that even though it saved my order it and I selected multiple checkboxes it did not save any values in the orders_products table, presumably for the same reason as it is erroring now.
orders_products is not the correct naming convention for a has_many :through relationship--it is correct for a has_and_belongs_to_many relationship. In a has_many :through, the "join" model is not just for joining--it is also its own model that has its own data, that also happens to join two other models together.
If your OrderProduct model doesn't have any of it's own data, logic, or constraints, then you could use a has_and_belongs_to_many relationship instead, remove the model completely, and then your join table is named right. Otherwise, it is named according to regular model naming conventions, namely order_products.