Im trying to set up a has one relationship in RoR. An agreement has one contact. In the agreement table there is a column called contact_id.
When i try to call an agreenment's contact like so: <%= agreement.contact.name %> (contact table has a column name) I get the error Unknown column 'contacts.agreement_id' Where it should be looking for agreement.contact_id
Any suggestions?
Michael's answer is right; the foreign key must always be in the table for the model that 'belongs_to' another model.
However, the best answer for you may be to invert the relationship: that is, are you sure an agreement doesn't belong to a contact, instead of having one contact? If you switch the relationship, then rails will correctly know to look for the foreign key in the agreements table, and not the contact table.
This Rails Guide has a more thorough discussion regarding the choice between has_one and belongs_to.
Your contacts table needs the foreign key migration added, i.e. you need to create a column agreement_id as integer. Make sure you do rake db:migrate and this should work.
Remember, the FK is on the 'belongs_to' table side of the relationship. So, an agreement has_one contact and contact belongs_to agreement.
Related
Let's say I have two tables: NormalClass Table and SpecialClass Table.
Each table contains classes for students.
I want to join tables so that I can access the normal classes of each student in that has a special class for students.
Both tables share the student_id key.
Trying to do this:
NormalClass.includes(:specialClasses)..
results in:
ActiveRecord::ConfigurationError: Association named 'specialClasses' was not found on NormalClass.includes; perhaps you misspelled it?
Should I be doing something else?
Gerbil,
Basically, you need to first set your associations properly.
Look at section 2.4 The has_many :through Association in Rails guides
Once you set it, you can pull up the data you want by pulling the student_id key
i'm starting now on Rails, i looked in the forum, but i didn't find anything that could solve my problem.
Here it goes, I have a Category table, and it has only name for a column (there is no repetition in categories) so i would like name to be the primary key, then i have a Product table that has name, main_photo, description and i would like to say that a product only has a category, do i need to add a column named category as a foreign key in products?
A Category is suposed to have many products.
Then in category models how do i say that name is the primary Key, and how can i do the correspondence between the suposed primary key name in categories and category in products?
Foreign key constraints in Active Record aren't used very often as the ideology behind Active Record says that this kind of logic should belong in the model and not in the database - the database is just a dumb store: http://guides.rubyonrails.org/migrations.html#active-record-and-referential-integrity.
The Rails way is to have an ID column on all tables including your Categories table, and in your Products table, have a column called Category_ID. Notice that the table names are plurals.
Then in your model you define the relationships between the entities Product and Category. Read the article A Guide to Active Record Associations and it will answer all your questions, especially sections 2.1, 2.2 and 3.3.
There are many valid reasons to have foreign keys in your database. See Does Rails need database-level constraints?
I recommend Foreigner if you want to easily add foreign keys to your Rails app.
I currently have a Product model and a Question model.
I have originally developed an application and in this application I had this relationship between them:
Product has_many :questions Question
belongs_to :product
However, I know now that a Question doesn't always have to belong to a Product.
What kind of relationship or solution should I be doing for something like this?
Note: I am using Rails 2.3.8
Unless I misunderstood your question, I don't see any problem with what you have. The Question records that do not belong to a Product will simply have a product_id column set to null.
There could be an issue if you have a validation in your Question model that checks the presence of a product_id but if that's the case, simply remove the validation on product_id.
You may also want to check that there is no constraint at the database level that prevents the product_id foreign key from being null.
In the Rails ActiveRecord Associations guide, I'm confused over why the tables for has_one and has_many are identical:
Example tables for has_many:
customers(id,name)
orders(id,customer_id,order_date)
Example tables for has_one:
these tables will, at the database level, also allow a supplier to have many accounts, but we just want one account per supplier
suppliers(id,name)
accounts(id,supplier_id,account_number) #Foreign Key to supplier here??
Shouldn't the tables for has_one be like this instead:
suppliers(id,name,account_id) #Foreign Key to account here
accounts(id,account_number)
Now because the account_id is in the suppliers table, a supplier can never have more than one account.
Is the example in the Rails Guide incorrect?
Or, does Rails use the has_many kind of approach but restricts the many part from happening?
If you think about this way -- they are all the same:
1 customer can have many orders, so each order record points back to customer.
1 supplier can have one account, and it is a special case of "has many", so it equally works with account pointing back to supplier.
and it is the same case with many-to-many, with junction table pointing back to the individual records... (if a student can take many classes, and one class can have many students, then the enrollment table points back to the student and class records).
as to why account points back to supplier vs account points to supplier, that one I am not entirely sure whether we can have it either way, or one form is better than the other.
I believe it has to do with the constraints. With has_one rails will try to enforce that there is only one account per supplier. However, with a has_many, there will be no constraint enforced, so a supplier with has_many would be allowed to exist with multiple accounts.
It does take some getting used to when thinking about the relationships and their creation in rails. If you want to enforce foreign keys on the database side (since rails doesn't do this outside of the application layer), take a look at Mathew Higgins' foreigner
If I understand your question correctly, you believe there is a 1:1 relationship bi-directionally in a has_one/belongs_to relationship. That's not exactly true. You could have:
Class Account
belongs_to :supplier
belongs_to :wholesaler
belongs_to :shipper
# ...
end
account = supplier.account # Get supplier's account
wholesaler = Wholesaler.new
wholesaler.accounts << account # Tell wholesaler this is one of their suppliers
wholesaler.save
I'm not saying your app actually behaves this way, but you can see how a table -- no, let's say a model -- that "belongs to" another model is not precluded from belonging to any number of models. Right? So the relationship is really infinity:1.
I should add that has_one is really a degenerate case of has_many and just adds syntactic sugar of singularizing the association and a few other nits. Otherwise, it's pretty much the same thing and it's pretty much why they look alike.
How do the relationships magically function when only the models are altered?
If I want a "has__and___belongs___to__many" relationship, what should I name the table (so Rails can use it) that contains the two foreign keys?
Short answer: You can't just tell the models that they're related; there have to be columns in the database for it too.
When you set up related models, Rails assumes you've followed a convention which allows it to find the things you wrote. Here's what happens:
You set up the tables.
Following conventions in Rails, you name the table in a particular, predictable way (a plural noun, e.g. people). In this table, when you have a relationship to another table, you have to create that column and name it in another predictable way (e.g. bank_account_id, if you're relating to the bank_accounts table).
You write a model class inheriting from ActiveRecord::Base
class Person < ActiveRecord::Base
When you instantiate one of these models, the ActiveRecord::Base constructor looks at the name of the class, converts it to lowercase and pluralizes it. Here, by reading Person, it yields people, the name of the table we created earlier. Now ActiveRecord knows where to get all the information about a person, and it can read the SQL output to figure out what the columns are.
You add relationships to the model: has_many, belongs_to or has_one.
When you type something like, has_many :bank_accounts, it assumes a few things:
The name of the model that you relate to is BankAccount (from camel-casing :bank_accounts).
The name of the column in the people table which refers to a bank account is bank_account_id (from singularizing :bank_accounts).
Since the relationship is has_many, ActiveRecord knows to give you methods like john.bank_accounts, using plural names for things.
Putting all of that together, ActiveRecord knows how to make SQL queries that will give you a person's bank accounts. It knows where to find everything, because you followed a naming convention that it understands when you created the table and its colums.
One of the neat things about Ruby is that you can run methods on a whole class, and those methods can add other methods to a class. That's exactly what has_many and friends are doing.
This works because you are following "Convention over Configuration".
If you state that a customer model has many orders then rails expects there to be a customer_id field on the orders table.
If you have followed these conventions then rails will use them and will be able to build the necessary SQL to find all the orders for a given customer.
If you look at the development.log file when you are developing your application you will be able to see the necessary SQL being built to select all orders for a given customer.
Rails does not create tables without you asking it to. The creation of tables is achieved by generating a migration which will create/alter tables for you. The fact that you create a customer model and then state within it that it has_many :orders will not create you an orders table. You will need to do that for yourself within a migration to create an orders table. Within that migration you will need to either add a customer_id column or use the belongs_to: customer statement to get the customer_id field added to the orders table.
The rails guide for this is pretty useful