I am completely new to rails and I ran into a problem while I try to define an association between models. To be specific, I am trying to create a relationship between task and category but It ran into the error when I try to connect them category.tasks << task1.
The Error:
C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activemodel-7.0.4/lib/active_model/attribute.rb:211:in `with_value_from_database': can't write unknown attribute `category_id` (ActiveModel::MissingAttributeError)
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{name}`"
^^^^^
task1 attribute:
t.string :name
t.text :description
t.integer :position
t.boolean :completed
t.timestamps
category attribute:
t.string :name
t.timestamps
the pre-set the connection between task and catogory
class AddCategoryIdtoTask < ActiveRecord::Migration[7.0]
def change
add_column(:tasks, :category_id, :integer, index:true)
end
end
class Task < ApplicationRecord
belongs_to :category, optional: true
end
class Category < ApplicationRecord
has_many :tasks
end
When I appendix task1 into category.tasks , would it not update the category_id to match?
I hope some passerby could look into this error that I feel like I am obviously missing something
Related
Model:
class UserPosition < ApplicationRecord
belongs_to :user
belongs_to :job_title
end
UserPosition's schema:
t.integer :user_id
t.integer :company_id
t.integer :industry_id
t.integer :department_id
t.integer :job_title_id
t.string :job_title_custom
user_positions_controller.rb
def create
#user_position = UserPosition.find_or_create_by(user_id: current_user.id)
#user_position.update_attributes({
:industry_id => params[:industry_id],
:department_id => params[:department_id],
:job_title_id => params[:job_title_id],
:job_title_custom => params[:job_title_custom]
})
I need UserPosition to either create a record with:
user_id
job_title_custom
OR
t.integer :user_id
t.integer :company_id
t.integer :industry_id
t.integer :department_id
t.integer :job_title_id
Currently, if I try to create a UserPosition with just user_id & job_title_custom
It doesn't work, the logs show ROLLBACK the error message is:
#messages={:job_title=>["must exist"]}
What am I doing wrong here? I think it could be because job_title has a relationship defined in the model but the Rails Guide says that they are optional, so I'm not sure.
Turns out this is a new Rails 5 behavior.
"In Rails 5, whenever we define a belongs_to association, it is required to have the associated record present by default after this change.
It triggers validation error if associated record is not present."
"In Rails 4.x world To add validation on belongs_to association, we need to add option required: true ."
"Opting out of this default behavior in Rails 5. We can pass optional: true to the belongs_to association which would remove this validation check."
Full Answer: http://blog.bigbinary.com/2016/02/15/rails-5-makes-belong-to-association-required-by-default.html
I Have a model named employee. The following is my migration file.
class CreateEmployees < ActiveRecord::Migration
def change
create_table :employees, id: false do |t|
t.string :name
t.string :password
t.string :role
t.primary_key :name
end
end
end
Now, I want to create a model named "teamplayer" with the columns as 'name' which needs to refers 'name' column in employee model. And 'tl' column
which is independent to this model. The following is my "teamplayer" migration file.
class CreateTeamplayers < ActiveRecord::Migration
def change
create_table :teamplayers, :id false do |t|
t.string :tl
t.string :name
end
end
end
In the above file, how to reference 'name' column to the model employee? So how to achieve foreign key in rails.
I think you want to look into Active Record Associations (http://guides.rubyonrails.org/association_basics.html)
I know you've asked to create a foreign key on name but unless you plan to ensure that name is unique, then this is possibly not the best plan (depending on the actual relationship you are trying to model - one to many / one to one etc).
I would be tempted to set up the foreign key relationship on employees.id. To do this, you can use the has_many and belongs_to associations.
You could change your teamplayers migration as follows:
class CreateTeamplayers < ActiveRecord::Migration
def change
create_table :teamplayers, :id false do |t|
t.belongs_to :employee
t.string :tl
end
end
end
Then in your Employee model, you can add the has_many side of things:
class Employee < ActiveRecord::Base
has_many :teamplayers
end
You can still easily get the Employee name given a Team Player record with a simple join.
Edit - to get the Employee, you can do something like this, assuming #tis a teamplayer instance:
#t.employee.name
(the code is untested and from memory so....)
You can do it in the teamplayer model, you just need to add index in your migration
class CreateTeamplayers < ActiveRecord::Migration
def change
create_table :teamplayers, :id false do |t|
t.string :tl
t.string :name
end
add_index :teamplayers, :name
end
end
You can set name as Primary key inside the employee model like this
class Employee < ActiveRecord::Base
self.primary_key = "name"
has_many :teamplayers
end
Now inside the model Teamplayer you can set the foreign key
class Teamplayer < ActiveRecord::Base
belongs_to :employee, foreign_key: 'name'
end
This should reference 'name' to employee model
Here are my migrations:
class CreateTests < ActiveRecord::Migration
def change
create_table :tests do |t|
t.string :value
t.timestamps
end
end
end
class CreateQuestions < ActiveRecord::Migration
def change
create_table :questions do |t|
t.string :title
t.timestamps
end
end
end
class CreateQuestionsTests < ActiveRecord::Migration
def change
create_table :questions_tests do |t|
t.integer :test_id
t.integer :question_id
t.timestamps
end
end
end
Now in the rails console I created a test object and a question object
test = Test.create(value: "10")
question = Question.create(title: "blablabla")
If now I do test.questions.create(question_id: question.id) I get the following error:
ActiveRecord::UnknownAttributeError: unknown attribute: question_id
How is that?
If you are using has_and_belongs_to_many relationship, you must to have relation table without id and stamps
class CreateQuestionsTests < ActiveRecord::Migration
def change
create_table :questions_tests, :id => false do |t|
t.integer :test_id
t.integer :question_id
end
end
end
I guess that you want to do a Rich association here, if so you should declare relations in your models like this :
Test.rb
class Test < ActiveRecord::Base
has_many :questions_tests
has_many :questions, :through => :questions_tests # here you tell rails that your Test model has many questions if you go through questions_tests
end
Question.rb
class Question < ActiveRecord::Base
has_many :questions_tests
has_many :tests, :through => :questions_tests # here you tell rails that your Question model has many tests if you go through questions_tests
end
QuestionTest.rb
class QuestionTest < ActiveRecord::Base
belongs_to :test
belongs_to :question
end
with this you can traverse the associations table (questions_tests) directly like you want : test.questions.create(question_id: question.id), and you have also this possibility :
test = Test.create(value: "10")
question = Question.create(title: "blablabla")
test.questions_tests << question # or question.questions_tests << test
I'm a beginner in Rails, and I'm having trouble inserting rows into the database using Rails's migration.
class Actions < ActiveRecord::Migration
def up
create_table :actions do |t|
t.integer :channel_id
t.string :name
t.text :description
t.integer :weight
t.timestamps
end
add_index :actions, :channel_id
Actions.create :name => 'name', :description => '', :weight => 1, :channel_id => 1
end
Running this code results in:
== Actions: migrating ========================================================
-- create_table(:actions)
-> 0.0076s
-- add_index(:actions, :channel_id)
-> 0.0036s
-- create({:name=>"name", :description=>"", :weight=>1, :channel_id=>1})
rake aborted!
An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: unrecognized token: "{": {:name=>"name", :description=>"", :weight=>1, :channel_id=>1}
The Action model:
class Actions < ActiveRecord::Base
belongs_to :channels
attr_accessible :name, :description, :weight, :channel_id
end
I don't know where the curly brackets come from and why they cause an exception. Who can help me solving this problem?
Uh oh, it seems that your migration class name is the same as the name of the model you're trying to access (Actions). Because of this, instead of the model class, the create method will be called on the migration class, which probably tries to create a table using your hash, or something. That's why you're getting that error message.
Rename your migration class (and also its file for the sake of consistency) and it should run fine:
class CreateActions < ActiveRecord::Migration
I've been trying to setup a Single Table Inheritance model in Rails 3 in which the parent class also contains a has_many relationship. Unfortunately I can't get it to work. Here are three classes as an example:
class Article < ActiveRecord::Base
has_many :paragraphs, :dependent => :destroy, :autosave => true
end
class Paragraph < ActiveRecord::Base
belongs_to :article
end
class SportsArticle < Article
end
And here's the migration that would be used to set this up:
class AddTables < ActiveRecord::Migration
def self.up
create_table :articles do |t|
t.string :type, :null => false # for STI
t.string :title, :null => false
t.timestamps
end
create_table :paragraphs do |t|
t.references :article, :null => false
t.timestamps
end
end
def self.down
drop_table :articles
drop_table :paragraphs
end
end
When I set it up this way and I try to create a new SportsArticle, say by doing the following:
SportsArticle.create(:title => "Go Giants")
I always get the following error:
"TypeError: can't convert String into Integer"
I have no idea how to fix this issue and have tried finding a solution online to no avail. Does anybody who has experience with STI models see anything wrong? Here's the link to the documentation on the create method if it will help in diagnosing the problem:
http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-c-create
Try renaming :type to something else, like :article_type
eg:
t.string :article_type, :null => false # for STI
The error was being caused due to a naming collision. I was using a name for one of my models called "attributes" which was causing the problem. The hint that eventually diagnosed the problem came from the Rails Association Documentation.