I'm getting the error unknown attribute: user_id durring execution of current_user.stories.build
class User < ActiveRecord::Base
has_many :stories, class_name: 'Story', foreign_key: 'user_id', dependent: :destroy
...
class Story < ActiveRecord::Base
belongs_to :user, class_name: 'User', foreign_key: 'user_id'
...
schema.rb
create_table "stories", :force => true do |t|
t.string "responsible"
t.string "descr"
t.string "state"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "users", :force => true do |t|
t.string "email"
t.string "password_digest"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "name"
end
It doesn't contain 'user_id' field. Any ideas?
Kulbir is correct that you need to define a user_id column in your stories table, but doesn't explain the way to do that.
The correct way to make that change is to create a new migration. By convention, it should be called add_user_id_to_stories and would be created as follows (assuming you're using Rails 3+):
rails generate migration add_user_id_to_stories
If you run that, it should actually generate a migration that already contains the change you need to make, which should be something like:
add_column :stories, :user_id, :integer
As an aside when you're following the Rails conventions concerning association naming, which you are, you can actually skip a lot of the extra specification. In the User model, you can specify just has_many :stories and in the Story model specify belongs_to :user. Rails will assume the same class names and foreign keys you've specified.
You should have a user_id field in your stories table like below to define the association in your models.
create_table "stories", :force => true do |t|
t.integer "user_id"
t.string "responsible"
t.string "descr"
t.string "state"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
...
end
Edit
Check Emily's answer for detailed explanation.
you should use the new syntax and pass the fieldtype as symbol
add_column :stories, :user_id, :integer
Related
I'm trying to return JSON API where a show action will
render json: user, include [:books, :friends, :comments]
Problem is, if I try to use the inverse_of in my User and Book model classes like this:
User Serializer
class UserSerializer < ActiveModel::Serializer
...
has_many :friends
has_many :books, inverse_of: :author
...
end
Book Serializer
class BookSerializer < ActiveModel::Serializer
...
belongs_to :author, class_name: "User", inverse_of: :books
...
end
I get an error:
ActiveRecord::StatementInvalid (SQLite3::SQLException: no such column: books.user_id: SELECT "books".* FROM "books" WHERE "books"."user_id" = ?):
If I remove the inverse_of and has_many from my User serializer, then I don't get any errors, but then the JSON being returned does not contain the included association.
Likewise, the same happens between Comment and User models.
Am I doing something wrong ?
My DB Schema for my two models are:
User Schema
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "username"
t.string "email"
t.string "password_digest"
t.boolean "banned"
t.integer "role_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "photo"
t.boolean "email_confirmed", default: false
t.string "confirm_token"
t.string "password_reset_token"
t.boolean "show_private_info", default: false
t.boolean "show_contact_info", default: false
t.index ["role_id"], name: "index_users_on_role_id"
end
Book Schema
create_table "books", force: :cascade do |t|
t.string "title"
t.boolean "adult_content"
t.integer "author_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "published"
t.string "cover"
t.text "blurb"
t.index ["author_id"], name: "index_books_on_author_id"
end
When I went to generate my Book model with:
rails generate model books ... author:references
It created this migration file:
class CreateBooks < ActiveRecord::Migration[5.0]
def change
create_table :books do |t|
t.string :title
t.boolean :adult_content
t.references :author, foreign_key: true
t.timestamps
end
end
end
I assume that includes the necessary foreign key setup...
Try to change this line in your User model(user.rb):
has_many :books, inverse_of: :author
to
has_many :books, inverse_of: :author, foreign_key: :author_id
You need to tell rails what foreign_key you used if it's not the default one.And the association should be declared in your models, not serializers. In serializer you are adding keys by "has_many", inverse_of does't works here.
Ruby 2.3.0, Rails 4.2.4, PostgreSQL 9.5
UPDATE: added activerecord-import code below.
Does anyone know how to make these associations hold, so that a model's table attributes can be referenced in another view? Similar to another Q&A (Rails has_many through aliasing with source and source_type for multiple types), where I have investors, companies, and transactions.
I've tried associations like the below (has_many ... through ...), but I'm failing to get ActiveRecord to recognize the connection among the 3 models & tables. Seeding the db:
The way data gets into these tables is via a csv file having 3 columns. I use roo-xls to extract each into an array of arrays.
My activerecord-import gem-based code (each *_val is an array of 1000s of arrays):
icol = [:name]
ccol = [:name]
tcol = [:investor_name, :company_name, :percent_owned]
investor_val = [["i1"],["i2"]] # just showing 2 arrays for brevity
company_val = [["c1"],["c2"]] # ""
transaction_val = [["i1","c1","pct1"],["i2","c2","pct2"]] # ""
Investor.import icol, investor_val, :validate => false
Company.import ccol, company_val, :validate => false
Transaction.import tcol, transaction_val, :validate => false
Import works, but when I check the transactions table, both company_id and investor_id are nil after executing the activerecord-import .import. I of course would like them to contain the foreign keys for the company and investor model records.
My models are below.
Class Company < ActiveRecord::Base
has_many :investors,
:through => :transactions
has_many :transactions
end
Class Investor < ActiveRecord::Base
has_many :companies,
:through => :transactions
has_many :transactions
end
Class Transaction < ActiveRecord::Base
belongs_to :company
belongs_to :investor
end
Transactions migration (others left out for brevity)
class CreatePositions < ActiveRecord::Migration
def change
create_table :positions do |t|
t.string :investor_name
t.string :company_name
t.string :percent_owned
t.belongs_to :company, index: true
t.belongs_to :manager, index: true
t.timestamps null: false
end
end
end
My schema, where I've added references to the belongs_to (transactions) table.
ActiveRecord::Schema.define(version: 20160128224843) do
create_table "companies", force: :cascade do |t|
t.string "name"
t.string "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "investors", force: :cascade do |t|
t.string "name"
t.string "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "transactions", force: :cascade do |t|
t.string "investor_name"
t.string "company_name"
t.float "percent_owned"
t.integer "investor_id"
t.integer "company_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "transactions", ["investor_id"], name: "index_transactions_on_investor_id", using: :btree
add_index "transactions", ["company_id"], name: "index_transactions_on_company_id", using: :btree
Im' using rails_admin to save a project that has a category within. I didn't define project_id and category_id because I thought they should be created by rails. The problem I got were using the method def category_id=(id) defined in project model (see below). The error is:
can't write unknown attribute `project_id`
My models are:
Category
class Category < ActiveRecord::Base
belongs_to :project, :inverse_of => :category
end
Project
class Project < ActiveRecord::Base
has_one :category, :dependent => :destroy, :inverse_of => :project
def category_id
self.category.try :id
end
def category_id=(id)
self.category = Category.find_by_id(id)
end
end
My schema:
create_table "categories", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "projects", force: :cascade do |t|
t.string "title"
t.text "text"
t.string "url"
t.string "key_feature"
t.string "image_1"
t.string "image_2"
t.string "image_3"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
How do you connect Projects to Categories?
Base on your schema Projects table has no category_id.
Neither you Category table has project_id
I would add category_id to Projects table.
rails g migration add_category_id_to_projects category_id:integer
rake db:migrate
The solution at the end was to manually add the project_id to categories table.
rails g migration add_project_id_to_categories project_id:integer
Thanks #Misha for you suggestion.
I have a rails app where users have children. So I had two models: :users and :children.
I used to have a one-to-many relationship (has_many / belongs_to), but I wanted to open it up to a many-to-many relationship where I could store variables about the relationship. So I changed the relationship to a "has_many through" relationship. I created a table called :relationships. A small caveat: I want the foreign_key for user to be :parent_id. Here is how I have them set up:
Schema:
create_table "relationships", :force => true do |t|
t.integer "child_id"
t.integer "parent_id"
t.datetime "created_at"
.
.
.
create_table "users", :force => true do |t|
t.string "email", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "first_name"
t.string "last_name"
.
.
.
create_table "children", :force => true do |t|
t.string "name", :null => false
t.integer "parent_id", :null => false
t.datetime "created_at", :null => false
.
.
.
Class Definitions:
user.rb:
has_many :relationships, foreign_key: "parent_id"
has_many :children, :through => :relationships, foreign_key: "parent_id"
child.rb:
has_many :relationships, foreign_key: "child_id"
has_many :parents, :through => :relationships
relationship.rb:
belongs_to :parent, class_name: "User", :foreign_key => :parent_id
belongs_to :child, class_name: "Child", :foreign_key => :child_id
Now when I choose a specific user and try to get user.children, I get [] in response. If I try to add new children, it doesn't work either. I can define the parent and the child, but when it tries to save, It cannot associate the two. It doesn't see the parent, so I get the error:
*ActiveRecord::StatementInvalid (PG::Error: ERROR: null value in column "parent_id" violates not-null constraint*
If I switch the Class definitions back to a one-to-many setup, it accesses the children just fine. I don't understand what the problem is. Any help would be very appreciated.
Thanks
How are you building the relationship? #user.children works for me with the given example when I create the relationship as follows:
#user.relationships.build(child_id: ...)
in children table parent_id should be allowed to take null if you want create children as nested attributes.
Change
create_table "children", :force => true do |t|
t.string "name", :null => false
t.integer "parent_id", :null => false
t.datetime "created_at", :null => false
end
To
create_table "children", :force => true do |t|
t.string "name", :null => false
t.integer "parent_id"
t.datetime "created_at", :null => false
end
I am creating a forum software. I want admins and mods to be able to close certain topics.
Codes are sanitized to show only relevant info.
Models
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :bio
has_many :topics, dependent: :destroy
end
class Topic < ActiveRecord::Base
belongs_to :user
attr_accessible :name, :last_post_id, :content
end
Schema for user: admin and mod columns determine admins and mods.
create_table "users", :force => true do |t|
t.string "name"
t.string "email"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "password_digest"
t.string "remember_token"
t.boolean "admin", :default => false
t.text "bio"
t.boolean "mod", :default => false
end
Schema for topic: closed column determines topic's closed status.
create_table "topics", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "forum_id"
t.string "name"
t.integer "last_post_id"
t.integer "views"
t.integer "user_id"
t.boolean "closed", :default => false
t.text "content"
end
I am reluctant to user attr_accessible :closed for TOPIC model because it will be vulnerable to malicious PUT request (correct me if I am wrong).
Is there some way for Rails app to be able to access and modify value of closed column of TOPIC without using attr_accessible, so that only mods and admins can edit them?
I searched on google and found this ascii cast.
Basically, you are looking for dynamic attr_accessible.
If you currently have
class Article < ActiveRecord::Base
attr_accessible :name, :content, :closed
end
You ca use dynamic attr_accessible like this :
class Article < ActiveRecord::Base
attr_accessible :name, :content
private
def mass_assignment_authorizer
super + [:closed]
end
end
I hope I is what you are looking for.
Be sure to check the link I gave you for complete reference.