I'm new to Rails and trying to understand associating entities.
I have three entities right now: Users, Companies, and Productlines.
company.rb:
class Company < ActiveRecord::Base
has_many :users
has_many :productlines
end
user.rb:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :company
end
productline.rb:
class Productline < ActiveRecord::Base
belongs_to :company
end
I've done the migration scrips to associate them, however when I click into a Company on Rails Admin, I'm getting this:
SQLite3::SQLException: no such column: productlines.company_id: SELECT "productlines".* FROM "productlines" WHERE "productlines"."company_id" = ?
Extracted source (around line #91):
#
def prepare sql
stmt = SQLite3::Statement.new( self, sql )
return stmt unless block_given?
begin
Edit: Here is my migration:
class AddProductlineIdToCompanies < ActiveRecord::Migration
def change
add_column :companies, :productline_id, :integer
add_index :companies, :productline_id
end
end
You should add the company_id to productlines and not product_line_id to companies...
class AddCompanyIdToProductlines < ActiveRecord::Migration
def change
add_column :productlines, :company_id, :integer
end
end
Related
I got a problem with my rails app. Here is my code in my Model:
class User < ApplicationRecord
has_many :assistants, class_name: User, foreign_key: :manager_id
belongs_to :manager, class_name: User
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
#validation
validates :first_name, :middle_name, :last_name, :birth_date, presence: true
end
Here is my Migration:
class AddReferenceToUserTable < ActiveRecord::Migration[5.0]
def change
add_column :users, :manager_id, :integer
end
end
BUT here is the error in my VIEW:
Sign up
1 error prohibited this user from being saved:
Manager must exist
May I know what wrong with my code?
Thanks,
Randz
If this is a rails 5 application belongs to is by default required. If a user will not always have a manager then you want
belongs_to :manager, class_name: User, required: false
I'm new to ruby on rails. Ihe error I have is
NameError in ReviewsController#create
uninitialized constant User::Review
Extracted source:
#review = current_user.reviews.build(review_params)
I read on other stack overflow questions that usually the error for wrong names or forgetting belongs_to or has_many but I believe I've set the relations correctly. I am using the gem devise to handle the user and sign in/sign up etc
Reviews.rb
class Reviews < ActiveRecord::Base
belongs_to :user
belongs_to :renters
end
User.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :reviews
end
Reviews_Controller.rb
class ReviewsController < ApplicationController
before_action :set_renter
before_action :authenticate_user!
def new
#review = Reviews.new(renters: #renter)
end
def create
#review = current_user.reviews.build(review_params)
#review.renter = #renter
#review.save
redirect_to #renter
end
private
def set_renter
#renter = Renters.find(params[:renter_id])
end
def review_params
params.require(:reviews).permit(:comment, :rating)
end
end
The Renters model is working fine and similar code I have to make a new Renter is working so I am not sure what is wrong.
ActiveRecord::Base classes are usually named in singular.
That means your class should be named Review and it should be stored in a file named models/review.rb (but still store its entries in a reviews database table).
If you do not want to follow this convention than you have to explicitly tell Rails that the class is named differently in the definition of the belongs_to and has_many association.
your model class for your reviews table should be Review in the file: app/models/review.rb
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :renters
end
and your User model representing users table should be in the file: app/models/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :reviews
end
NOTE: for this association to work, your reviews table must have a column user_id as the foreign key for performing activerecord operations on associated models (for example: User.find(1).reviews to get all records of reviews table whose user_id is 1)
This occours by convention of Rails. You can force with function class_name the class Reviews
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :reviews, class_name: "Reviews"
end
I'm trying to do a simple user.destroy but running into the following error:
ERROR: update or delete on table "users" violates foreign key constraint "fk_rails_5373344100" on table "identities"
DETAIL: Key (id)=(2) is still referenced from table "identities".
Here is my migration for Identities
class CreateIdentities < ActiveRecord::Migration
def change
create_table :identities do |t|
t.references :user, index: true, foreign_key: true
t.string :provider
t.string :uid
t.timestamps null: false
end
end
end
Here is my user and identity model:
class Identity < ActiveRecord::Base
belongs_to :user
validates_presence_of :uid, :provider
validates_uniqueness_of :uid, :scope => :provider
def self.find_for_oauth(auth)
find_or_create_by(uid: auth.uid, provider: auth.provider)
end
end
and user:
class User < ActiveRecord::Base
TEMP_EMAIL_PREFIX = 'ricky#writeit.com'
TEMP_EMAIL_REGEX = /\ricky#writeit.com/
# Include default devise modules. Others available are:
# :lockable, :timeoutable
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
validates_format_of :email, :without => TEMP_EMAIL_REGEX, on: :update
...
end
I'm new to foreign keys and references, so I'm not sure at all how to fix this.
You would need to remove the Identity that references the user first. Then you can delete the user.. By default the foreign key is doing a restrict so you cannot delete the user if anything references to it.
if you would like use Rails to handle destroying the identity you can do
class User < ActiveRecord::Base
has_many :identities, dependent: :destroy
......
end
Which would cause Rails to destroy all the dependent records.
But as you are using Foreign keys, you can adjust your migration to set cascade deletes
add_foreign_key :identities, :users, on_delete: :cascade
Assuming rails 4.2 which has native support
An easy solution is to simply cascade-delete the records in the associated table, which can be done through active record, like so:
user.rb
class User < ActiveRecord::Base
has_many :identities, dependent: :destroy
# rest of user class
end
Check out the documentation pertaining to has_many for more info.
Rails 4.1
Ruby 2.0
Credential.rb
class Credential < ActiveRecord::Base
belongs_to :category
has_many :user
validates :name, :login, :password, presence: true
attr_accessor :encryption_key
attr_encrypted :login, key: :encryption_key
attr_encrypted :password, key: :encryption_key
end
User.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :credentials
def you
"You are <b>#{email}</b>"
end
end
CredentialsController.rb
class CredentialsController < ApplicationController
before_filter :authenticate_user!
def create
#credential = current_user.credentials.new
#credential.encryption_key = session[:master_key]
#credential.update(credential_params)
if #credential.save
redirect_to credential_path(#credential), notice: "Password entry created successfully."
else
render "new"
end
end
The line:
#credential.update(credential_params)
throws an exception
undefined method 'each' for #<User:0x4de4f58>
You need to edit your associations. You have credentials that has_many :user and users that has_many :credentials. The one with the foreign key should be a belongs_to not has_many. If you're attempting to make a many-to-many relationship, then either use has_many_and_belongs_to or a join table. Further, it should be has_many :users and not has_many :user. That should resolve your error.
I have three models: User, Micropost, and Comment. I'm trying to set foreign keys as follows:
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.text :content
t.timestamps
end
add_index :comments, :micropost_id, :user_id
end
end
But I get this error:
An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: near "user_id": syntax error: CREATE user_id
INDEX "index_comments_on_micropost_id" ON "comments" ("micropost_id")
I understand that Rails insert foreign keys based on belongs_to and has_many declarations in the models. But I have everything set:
comment.rb:
class Comment < ActiveRecord::Base
belongs_to :micropost
belongs_to :user
end
micropost.rb:
class Micropost < ActiveRecord::Base
attr_accessible :title, :content
belongs_to :user
has_many :comments
end
user.rb:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
has_many :microposts
has_many :comments
end
Any suggestions to fix this?
If you want to create an index on 2 columns, the syntax is add_index table_name, [column1_name, column2_name], options. You also need to define the columns in the table (ActiveRecord does not add them automatically when you add belongs_to in the model class). So your migration should be
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.text :content
t.integer :micropost_id
t.integer :user_id
t.timestamps
end
add_index :comments, [:micropost_id, :user_id]
end
end