In console I get this error:
peegin.user
NameError: undefined local variable or method `peegin' for main:Object
Did you mean? #peegin
Also when i try to access Peegin in console it doesn't display user_id:
Peegin
=> Peegin(id: integer, title: string, meaning: string, example: string, created_at: datetime, updated_at: datetime, permalink: string)
2.3.0 :039 >
User Class
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 :peegins
end
Peegin Class
class Peegin < ActiveRecord::Base
belongs_to :user
before_create :generate_permalink
def to_param
permalink
end
private
def generate_permalink
pattern=self.title.parameterize
duplicates = Peegin.where(permalink: pattern)
if duplicates.present?
self.permalink = "#{pattern}-#{duplicates.count+1}"
else
self.permalink = self.title.parameterize
end
end
end
Schema
ActiveRecord::Schema.define(version: 20160804115242) do
create_table "peegins", force: :cascade do |t|
t.string "title"
t.string "meaning"
t.string "example"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "permalink"
t.integer "user_id"
end
add_index "peegins", ["user_id"], name: "index_peegins_on_user_id", unique: true
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
Make sure your database is up to date.
$ bin/rake db:migrate
Then.. you have to create a Peegin object and then you can access the user:
peegin = Peegin.create(title: "something")
peegin.user # => nil
peegin.user = User.first # Or take any user you want.
peegin.save # => user_id is updated in the database
In your rails console please try this:
#peegin = Peegin.find(1) //IF one doesn't work make sure if database has a record with this id and try with id that exists.
then use
#peegin.user
Instead of
peegin.user
Related
I've just linked my Rails app to a mysql database which has the table names and columns in Spanish. Now I solved the Spanish table names problem by setting self.table_name = "table_name" inside the model.rb. Now the next problem occurs when I want to call a data through joining tables. In this case I'm trying to call all the ads that belong the first category. When I try this as you see in the screenshot below, I get this error. It sees the ad table now anuncio which is the Spanish name. I'm a bit confused, because I thought that by doing self.table_name = "table_name" in every model Rails knows which table I mean. Does someone know what's going on here and how to solve it? See below all my code regarding the models and tables.
Ad model:
class Ad < ApplicationRecord
self.table_name = "anuncios"
has_many :ad_copies
has_many :ad_addresses
has_many :relationships
has_many :magazines
has_many :categories, through: :relationships
belongs_to :user
end
Relationship model:
class Relationship < ApplicationRecord
self.table_name = "rel_anuncio"
self.primary_key = "id_anuncio"
belongs_to :ad, class_name: "anuncio", foreign_key: "id_anuncio", optional: true
belongs_to :category, class_name: "categoria", foreign_key: "id_categoria", optional: true
belongs_to :subcategory, class_name: "subcategoria", foreign_key: "id_subcategoria", optional: true
end
Category model:
class Category < ApplicationRecord
self.table_name = "categorias"
has_many :subcategories
has_many :relationships
has_many :ads, through: :relationships
belongs_to :user
end
Subcategory model:
class Subcategory < ApplicationRecord
self.table_name = "subcategorias"
has_many :relationships
has_many :ads, through: :relationships
belongs_to :category
end
You can see in the models above that I've been trying to get the relationship model to connect to the ad model with respectively the category and subcategory model, because these models have n:n relationship with each other. Before, when I was using an English database as practice, the #categories.first.ads.count worked, but changing to a Spanish database it suddenly stopped working. In the relationship table I'm also explicitly setting the foreign-key for each of the models.
Ads table (anuncios) schema:
create_table "anuncios", id: :integer, force: :cascade, options: "ENGINE=MyISAM DEFAULT CHARSET=utf8" do |t|
t.string "empresa", null: false
t.string "tel", null: false
t.string "fax_principal", null: false
t.string "movil_principal", null: false
t.string "email_principal", null: false
t.string "web", null: false
t.string "facebook", null: false
t.string "horario_v_principal", null: false
t.string "horario_i_principal", null: false
t.string "direccion_principal", null: false
t.string "poblacion_principal", null: false
t.string "activo", limit: 2, null: false
t.string "tam_anuncio", null: false
t.string "twitter", null: false
t.string "link", limit: 2, null: false
t.string "general", limit: 2, null: false
t.string "isla", limit: 10, null: false
t.string "subtitulo", null: false
t.string "comentario", null: false
t.datetime "modificacion", null: false
t.integer "promo1", default: 0, null: false
t.integer "promo2", default: 0, null: false
t.string "instagram", null: false
t.string "tel2", null: false
t.string "tel3", null: false
t.string "tel4", null: false
t.string "movil2", null: false
t.string "movil3", null: false
t.string "movil4", null: false
end
Relationship table (rel_anuncios) schema:
create_table "rel_anuncio", primary_key: ["id_anuncio", "id_categoria", "id_subcategoria"], force: :cascade, options: "ENGINE=MyISAM DEFAULT CHARSET=utf8" do |t|
t.integer "id_anuncio", null: false
t.integer "id_categoria", null: false
t.integer "id_subcategoria", null: false
t.integer "orden", null: false
end
Categories table (categorias) schema:
create_table "categorias", id: :integer, force: :cascade, options: "ENGINE=MyISAM DEFAULT CHARSET=utf8" do |t|
t.string "nombre", null: false
t.string "color", null: false
t.string "activo", limit: 2, null: false
t.string "bdd", limit: 7, null: false
t.integer "orden", null: false
t.integer "promoI", limit: 1, default: 0, null: false
t.integer "promoF", limit: 1, default: 0, null: false
t.integer "islas", limit: 1, default: 3, null: false
end
Subcategories table (subcategorias) schema:
create_table "subcategorias", id: :integer, force: :cascade, options: "ENGINE=MyISAM DEFAULT CHARSET=utf8" do |t|
t.integer "id_categoria", null: false
t.string "nombre", null: false
t.string "color", null: false
t.string "activo", limit: 2, default: "si", null: false
t.integer "orden", null: false
t.integer "promoI", limit: 1, default: 0, null: false
t.integer "promoF", limit: 1, default: 0, null: false
t.integer "islas", limit: 1, default: 3, null: false
end
UPDATE:
In response to #Jagdeep Singh comment I've changed my relationship.rb to look like this:
class Relationship < ApplicationRecord
self.table_name = "rel_anuncio"
self.primary_key = "id_anuncio"
belongs_to :ad, foreign_key: "id_anuncio", optional: true
belongs_to :category, foreign_key: "id_categoria", optional: true
belongs_to :subcategory, foreign_key: "id_subcategoria", optional: true
end
*I've taken away the class names.
After this change I get the following error:
Mysql2::Error: Unknown column 'rel_anuncio.category_id' in 'where clause': SELECT COUNT(*) FROM `anuncios` INNER JOIN `rel_anuncio` ON `anuncios`.`id` = `rel_anuncio`.`id_anuncio` WHERE `rel_anuncio`.`category_id` = 1
Here I can see that ActiveRecord is using in its sql statement category_id which should be id_categoria (see schema relationship table above). I have no idea how to make ActiveRecord use the right name for the foreign_key.
You class names should be the actual model names (and not their table names) when defining associations. And as your association names follow the rails conventions e.g. model for belongs_to :ad is Ad, and so on, you can omit specifying class_name:
class Relationship < ApplicationRecord
belongs_to :ad, foreign_key: "id_anuncio", optional: true
belongs_to :category, foreign_key: "id_categoria", optional: true
belongs_to :subcategory, foreign_key: "id_subcategoria", optional: true
end
Update
More changes in association definitions after the recent error posted in comments:
class Category < ApplicationRecord
has_many :subcategories, foreign_key: 'id_categoria'
has_many :relationships, foreign_key: 'id_categoria'
has_many :ads, through: :relationships
belongs_to :user
end
class Subcategory < ApplicationRecord
has_many :relationships, foreign_key: 'id_subcategoria'
has_many :ads, through: :relationships
belongs_to :category, foreign_key: 'id_categoria'
end
I'm pretty new at Ruby on Rails and i'm not sure what is the best approach to modelling the application.
My app has an User model and a Restaurant model. Both of them has only one address.
Restaurants table
create_table "restaurants", force: :cascade do |t|
t.string "name"
t.text "description"
t.string "email"
t.string "phone"
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
User table
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "surname"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The restaurants addresses must have two columns more than the users addresses ( lat and long)
FIRST APPROACH - Create two tables, one to the restaurant addresses and another to the user addressses.
User addresses table
create_table "user_addresses", force: :cascade do |t|
t.string "street"
t.string "city"
t.string "zip_code"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_addresses_on_user_id"
end
restaurant addresses table
create_table "restaurant_addresses", force: :cascade do |t|
t.string "street"
t.string "city"
t.string "zip_code"
t.decimal "longitude"
t.decimal "latitude"
t.integer "restaurant_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["restaurant_id"], name: "index_addresses_on_restaurant_id"
end
SECOND APPROACH -
Create a Polymorphic association for the User model and Restaurant model.
Create a separated table with the coordinates (associated just with the restaurant Model).
Polymorphic Association
class User
has_one :address, as: :addressable
end
class Restaurant
has_one :address, as: :addressable
has_one:coordinate
end
class Address
belongs_to :addressable, polymorphic: true
end
Any one of this approachs are good enough or is it a better way to do that?
My app consists of 3 models:
FashionModel
Measurement
ModelProfile
class FashionModel < ActiveRecord::Base
has_secure_password
has_one :model_profile
has_one :measurement
accepts_nested_attributes_for :model_profile
accepts_nested_attributes_for :measurement
end
class ModelProfile < ActiveRecord::Base
belongs_to :fashion_model
end
class Measurement < ActiveRecord::Base
belongs_to :fashion_model
end
The schema is roughly as follows:
create_table "fashion_models", force: :cascade do |t|
t.string "first_name", limit: 25
t.string "last_name", limit: 25
t.string "email", limit: 255, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest", limit: 255
t.string "password_reset_token", limit: 255
t.datetime "password_reset_sent_at"
end
create_table "measurements", force: :cascade do |t|
t.integer "fashion_model_id", limit: 4
t.decimal "feet", precision: 10
t.decimal "inches", precision: 10
t.decimal "bust", precision: 10, default: 36
t.decimal "waist", precision: 10, default: 28
t.decimal "hips", precision: 10, default: 36
t.decimal "shoes", precision: 10
t.integer "dress", limit: 4
t.string "eyes", limit: 255
t.string "hair", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "model_profiles", force: :cascade do |t|
t.integer "fashion_model_id", limit: 4
t.string "phone_number", limit: 255
t.date "birthdate"
t.text "bio", limit: 65535
t.string "location", limit: 255, default: "Venice"
t.string "gender", limit: 255
t.decimal "rate", precision: 10, default: 100
t.string "profile_picture", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "model_profiles", ["fashion_model_id"], name: "index_model_profiles_on_fashion_model_id", using: :btree
add_foreign_key "bookings", "fashion_models"
add_foreign_key "fashion_model_photos", "fashion_models"
end
I am trying to filter out data based on the input. For example someone searches for a model with height 5'8", with black eyes, and brown hair, I should display only those models by querying the database.
Therefore, I am trying to use named scopes in the model. I am not sure how do I scope the attributes of the measurement table by writing a scope in the FashionModel model.
I read a few resources online and from what I understood, I wrote something like
scope :eye_color, includes(:measurement).where(measurement: { eyes: "Amber" })
Though I don't want to hardcode Amber into the eyes field, I get an error in my console when trying to access this scope. I do something like
a = FashionModel.all
a.eye_color
This gives me an and ArgumentError: wrong number of arguments (given 0, expected 1).
I also tried doing this
scope :eye_color, -> (eye_color) { where eyes: eye_color }
and then calling it by a.eye_color("Amber"), which in turn gave me a NoMethodError: undefined method 'measurement' for Class.
So basically I want to scope into the child models from the parent model.
Any help is much appreciated! Thanks
Define your scope as:
scope :eye_color, ->(eye_color) {
includes(:measurements).where(measurements: {eyes: eye_color})
}
And then query with a param like:
FashionModel.eye_color("Amber")
Error that need to be solved:
ActiveRecord::StatementInvalid: Mysql2::Error: Cannot delete or update
a parent row: a foreign key constraint fails
(slap_chat_development.chatrooms, CONSTRAINT fk_rails_496733c195
FOREIGN KEY (group_id) REFERENCES groups (id)): DELETE FROM
groups WHERE groups.id = 1
QUESTION IS:
can someone guide me where from should this error be fixed.
As I see problem persists in relation between groups and chatrooms tables.
Further details:
schema.rb
ActiveRecord::Schema.define(version: 20160606100750) do
create_table "chatrooms", force: :cascade do |t|
t.integer "group_id", limit: 4
t.string "name", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "chatrooms", ["group_id"], name: "index_chatrooms_on_group_id", using: :btree
create_table "chatrooms_users", force: :cascade do |t|
t.integer "chatroom_id", limit: 4
t.integer "user_id", limit: 4
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "chatrooms_users", ["chatroom_id"], name: "index_chatrooms_users_on_chatroom_id", using: :btree
add_index "chatrooms_users", ["user_id"], name: "index_chatrooms_users_on_user_id", using: :btree
create_table "groups", force: :cascade do |t|
t.string "name", limit: 255
t.integer "user_id", limit: 4
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "groups", ["user_id"], name: "index_groups_on_user_id", using: :btree
create_table "groups_users", force: :cascade do |t|
t.integer "group_id", limit: 4
t.integer "user_id", limit: 4
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "groups_users", ["group_id"], name: "index_groups_users_on_group_id", using: :btree
add_index "groups_users", ["user_id"], name: "index_groups_users_on_user_id", using: :btree
create_table "posts", force: :cascade do |t|
t.integer "user_id", limit: 4
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "content", limit: 255
end
add_index "posts", ["user_id"], name: "index_posts_on_user_id", using: :btree
create_table "users", force: :cascade do |t|
t.string "email", limit: 255, default: "", null: false
t.string "encrypted_password", limit: 255, default: "", null: false
t.string "reset_password_token", limit: 255
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", limit: 4, default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip", limit: 255
t.string "last_sign_in_ip", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "first_name", limit: 255
t.string "nick_name", limit: 255
t.string "last_name", limit: 255
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_foreign_key "chatrooms", "groups"
add_foreign_key "chatrooms_users", "chatrooms"
add_foreign_key "chatrooms_users", "users"
add_foreign_key "groups", "users"
add_foreign_key "groups_users", "groups"
add_foreign_key "groups_users", "users"
add_foreign_key "posts", "users"
end
Group model:
class Group < ActiveRecord::Base
has_many :chatrooms
belongs_to :group_admin, class_name: "User", foreign_key: :user_id
has_and_belongs_to_many :members, class_name: "User", association_foreign_key: :user_id
validates :user_id, presence: true
validates :name, presence: true, length: { minimum: 3 }
before_create { self.name = self.name.capitalize }
after_create :assign_creator
around_destroy :destroy_all_associates
def general_room
self.chatrooms.where("name = ?", "general").take
end
def except_general_room
self.chatrooms.select { |room| room != self.general_room }
end
def assign_creator
member = self.group_admin
self.members << member
self.general_room.members << member
end
def destroy_all_associates
rooms = self.chatrooms
yield
rooms.each do |room|
room.destroy
end
end
end
Chatroom model:
class Chatroom < ActiveRecord::Base
belongs_to :group
has_and_belongs_to_many :members, class_name: "User", association_foreign_key: :user_id
validates :name, presence: true, length: { minimum: 3 }
before_save { self.name = self.name.downcase }
around_create :ensure_group_presence
around_destroy :destroy_all_associates
def feed
ids = Array.new
self.members.each do |member|
ids += member.post_ids
end
Post.where("id IN (?)", ids)
end
def ensure_group_presence
yield
self.group_id.present?
end
def destroy_all_associates
feed = self.feed
yield
feed.destroy_all
end
end
You can try using this in your group model.
class Group < ActiveRecord::Base
has_many :chatrooms , dependent: :destroy
end
Now when you execute, Group.last.destroy, it should delete the dependent associated chatrooms before and no hanging data would be left
It seems like you are trying to delete a group that has one or many chatrooms.
But because you added a foreign key constraint (add_foreign_key "chatrooms", "groups"), it is not allowed to delete a group when there is still a chatroom assigned.
To solve this issue you have to destroy all associated chatrooms before destroying the group itself.
I think it depends on whether you need to delete the associated table.
If you need to delete the associated table, you should
has_many :chatrooms , dependent: :destroy
However, if you do not want to delete the associated table, you should
has_many :chatrooms , dependent: :nullify
There are detailed descriptions in the rails API
:dependent
Controls what happens to the associated objects when their owner is
destroyed. Note that these are implemented as callbacks, and Rails
executes callbacks in order. Therefore, other similar callbacks may
affect the :dependent behavior, and the :dependent behavior may
affect other callbacks.
:destroy causes all the associated objects to also be destroyed.
:delete_all causes all the associated objects to be deleted directly
from the database (so callbacks will not be executed).
:nullify causes the foreign keys to be set to NULL. Callbacks are not executed.
:restrict_with_exception causes an exception to be raised if there are any associated records.
:restrict_with_error causes an error to be added to the owner if there are any associated objects.
If using with the :through option, the association on the join model must be a belongs_to, and the records which get deleted are the join records, rather than the associated records.
If using dependent: :destroy on a scoped association, only the scoped objects are destroyed. For example, if a Post model defines has_many
:comments, -> { where published: true }, dependent: :destroy and destroy is called on a post, only published comments are destroyed.
This means that any unpublished comments in the database would still contain a foreign key pointing to the now deleted post.
RailsApi
Error: Mysql2::Error: Cannot delete or update a parent row: a foreign key constraint fails
Solution:
I think you have used .delete or delete_all,
Instead of .delete or delete_all use .destroy
.destroy will delete all associated values with that model
Now It will work !
In development rake db:migrate works fine, generating a .sqlite3 file. In production where rake db:migrate adds tables to an actualy MySQL db I get the error.
-- create_table(:category_item_values)
rake aborted!
StandardError: An error has occurred, all later migrations canceled:
Index name 'index_category_item_values_on_category_item_key_id' on table 'category_item_values'
already exists/site/db/migrate/20151218040123_create_category_i
tem_values.rb:3:in `change'
Tasks: TOP => db:migrate
So clearly the index name index_category_item_values_on_category_item_key_id already exists but I dont know what to change to fix the problem or how the naming convention works in this case.
here is 20151218040123_create_category_item_values.rb
class CreateCategoryItemValues < ActiveRecord::Migration
def change
create_table :category_item_values do |t|
t.string :key
t.integer :key_type
t.integer :guide_id
t.integer :category_id
t.text :value
t.belongs_to :category_item_key, index: true
t.belongs_to :category_item, index: true
t.timestamps null: false
end
add_foreign_key :category_item_values, :category_items
add_index :category_item_values, :guide_id
add_index :category_item_values, :category_id
add_index :category_item_values, :key_type
add_index :category_item_values, :key
end
end
and
20160430043022_add_foreign_key_cat_keys_to_category_item_values.rb
class AddForeignKeyCatKeysToCategoryItemValues < ActiveRecord::Migration
def change
add_foreign_key :category_item_values, :category_item_keys
end
end
plus 20160111231051_create_category_item_keys.rb just incase the duplicate is in there
class CreateCategoryItemKeys < ActiveRecord::Migration
def change
create_table :category_item_keys do |t|
t.string :name
t.integer :key_type
t.integer :submitted_by
t.integer :approved_by
t.integer :guide_id
t.belongs_to :category, index: true
t.timestamps null: false
end
add_foreign_key :category_item_keys, :categories
add_index :category_item_keys, :name, unique: true
add_index :category_item_keys, :key_type
end
end
here is category_item_values table in the schema file
create_table "category_item_values", force: :cascade do |t|
t.string "key"
t.integer "key_type"
t.integer "guide_id"
t.integer "category_id"
t.text "value"
t.integer "category_item_key_id"
t.integer "category_item_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
end
add_index "category_item_values", ["category_id"], name: "index_category_item_values_on_category_id"
add_index "category_item_values", ["category_item_id"], name: "index_category_item_values_on_category_item_id"
add_index "category_item_values", ["category_item_key_id"], name: "index_category_item_values_on_category_item_key_id"
add_index "category_item_values", ["guide_id"], name: "index_category_item_values_on_guide_id"
add_index "category_item_values", ["key"], name: "index_category_item_values_on_key"
add_index "category_item_values", ["key_type"], name: "index_category_item_values_on_key_type"
add_index "category_item_values", ["slug"], name: "index_category_item_values_on_slug"
Whats clashing to cause this error?