I have such db schema:
Tables:
COUNTRY_DESIGNATIONS
DES_TEXTS
MANUFACTURERS
MODELS
And such relationships:
COUNTRY_DESIGNATIONS has_many MODELS
DES_TEXTS has_many COUNTRY_DESIGNATIONS
MANUFACTURERS has_many MODELS
In rails model all relations and other "things" are written.
And when i select manufactures, I get all it's models. But now I want in these models to select data from COUNTRY_DESIGNATIONS (sure all table relations id's must be equal), and then when select data from COUNTRY_DESIGNATIONS i want to fetch data from DES_TEXTS and display it.
How can i do this? what change in controllers, views? (I were using standart scaffolds)
now i have such view to view models from manufacturer:
- #manufacturer.models.each do |model|
%tr
%p
mod_id
%td= model.MOD_ID
%p
MOD_PCON_START
%td= model.MOD_PCON_START
%p
MOD_PCON_END
%td= model.MOD_PCON_END
= link_to 'Show model', model
and i want to add something like this:
- #manufacturer.models.each do |model|
%tr
%p
...
%td= model.country_des.des_text.FIELD - something like this)
= link_to 'Show model', model
models files:
class CountryDesignation < ActiveRecord::Base
set_table_name "COUNTRY_DESIGNATIONS"
set_primary_key :CDS_ID
belongs_to :des_text
belongs_to :language
has_many :models
end
class DesText < ActiveRecord::Base
set_table_name "DES_TEXTS"
set_primary_key :TEX_ID
has_many :country_designation
has_many :designation
end
class Model < ActiveRecord::Base
set_table_name "MODELS"
set_primary_key :MOD_ID
belongs_to :manufacturer
belongs_to :country_designation
has_many :types
end
dump:
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20120418164608) do
create_table "COUNTRY_DESIGNATIONS", :primary_key => "CDS_ID", :force => true do |t|
t.binary "CDS_CTM"
t.integer "CDS_LNG_ID"
t.integer "CDS_TEX_ID"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "DESIGNATIONS", :primary_key => "DES_ID", :force => true do |t|
t.integer "DES_LNG_ID"
t.integer "DES_TEX_ID"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "DES_TEXTS", :primary_key => "TEX_ID", :force => true do |t|
t.text "TEX_TEXT"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "LANGUAGES", :primary_key => "LNG_ID", :force => true do |t|
t.integer "LNG_DES_ID"
t.string "LNG_ISO2"
t.string "LNG_CODEPAGE"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "MANUFACTURERS", :primary_key => "MFA_ID", :force => true do |t|
t.integer "MFA_PC_MFC"
t.integer "MFA_CV_MFC"
t.integer "MFA_AXL_MFC"
t.integer "MFA_ENG_MFC"
t.integer "MFA_ENG_TYP"
t.string "MFA_MFC_CODE"
t.string "MFA_BRAND"
t.integer "MFA_MF_NR"
t.binary "MFA_PC_CTM"
t.binary "MFA_CV_CTM"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "MODELS", :primary_key => "MOD_ID", :force => true do |t|
t.integer "MOD_MFA_ID"
t.integer "MOD_CDS_ID"
t.integer "MOD_PCON_START"
t.integer "MOD_PCON_END"
t.integer "MOD_PC"
t.integer "MOD_CV"
t.integer "MOD_AXL"
t.binary "MOD_PC_CTM"
t.binary "MOD_CV_CTM"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "TYPES", :primary_key => "TYP_ID", :force => true do |t|
t.integer "TYP_CDS_ID"
t.integer "TYP_MMT_CDS_ID"
t.integer "TYP_MOD_ID"
t.binary "TYP_CTM"
t.binary "TYP_LA_CTM"
t.integer "TYP_SORT"
t.integer "TYP_PCON_START"
t.integer "TYP_PCON_END"
t.integer "TYP_KW_FROM"
t.integer "TYP_KW_UPTO"
t.integer "TYP_HP_FROM"
t.integer "TYP_HP_UPTO"
t.integer "TYP_CCM"
t.integer "TYP_CYLINDERS"
t.integer "TYP_DOORS"
t.integer "TYP_TANK"
t.integer "TYP_KV_VOLTAGE_DES_ID"
t.integer "TYP_KV_ABS_DES_ID"
t.integer "TYP_KV_ASR_DES_ID"
t.integer "TYP_KV_ENGINE_DES_ID"
t.integer "TYP_KV_BRAKE_TYPE_DES_ID"
t.integer "TYP_KV_BRAKE_SYST_DES_ID"
t.integer "TYP_KV_FUEL_DES_ID"
t.integer "TYP_KV_CATALYST_DES_ID"
t.integer "TYP_KV_BODY_DES_ID"
t.integer "TYP_KV_STEERING_DES_ID"
t.integer "TYP_KV_STEERING_SIDE_DES_ID"
t.float "TYP_MAX_WEIGHT"
t.integer "TYP_KV_MODEL_DES_ID"
t.integer "TYP_KV_AXLE_DES_ID"
t.integer "TYP_CCM_TAX"
t.float "TYP_LITRES"
t.integer "TYP_KV_DRIVE_DES_ID"
t.integer "TYP_KV_TRANS_DES_ID"
t.integer "TYP_KV_FUEL_SUPPLY_DES_ID"
t.integer "TYP_VALVES"
t.integer "TYP_RT_EXISTS"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "carts", :force => true do |t|
t.integer "customer_id"
t.integer "item_id"
t.integer "amount"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "credit_cards", :force => true do |t|
t.integer "customer_id"
t.string "number"
t.string "nameOfCard"
t.date "expiryDate"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "currencies", :force => true do |t|
t.float "currencyvalue"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "customer_sessions", :force => true do |t|
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "customers", :force => true do |t|
t.string "username"
t.string "crypted_password"
t.string "password_salt"
t.string "persistence_token"
t.string "email"
t.string "skype"
t.integer "ICQ"
t.string "firstname"
t.string "lastname"
t.string "country"
t.string "state"
t.string "city"
t.string "street"
t.string "building"
t.integer "room"
t.string "addressNote"
t.string "dateOfReg"
t.integer "custGroup_id"
t.float "totalBuy"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "order_statuses", :force => true do |t|
t.string "statusname"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "orders", :force => true do |t|
t.integer "basket_id"
t.integer "customer_id"
t.integer "shipping_id"
t.integer "paymentmethod_id"
t.integer "orderstatus_id"
t.datetime "dateoforder"
t.float "totalcost"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "payment_methods", :force => true do |t|
t.string "methodname"
t.boolean "allowed"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "sellers", :force => true do |t|
t.string "username"
t.string "crypted_password"
t.string "password_salt"
t.string "persistence_token"
t.string "email"
t.string "skype"
t.integer "ICQ"
t.string "firstname"
t.string "lastname"
t.string "dateOfReg"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "shippings", :force => true do |t|
t.string "shippingname"
t.float "shippingcost"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "telephone_operators", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "telephones", :force => true do |t|
t.integer "customer_id"
t.integer "operator"
t.integer "number"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "virtual_pay_systems", :force => true do |t|
t.string "name"
t.boolean "active"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "virtual_pays", :force => true do |t|
t.integer "customer_id"
t.string "number"
t.integer "virtualpaysystem_id"
t.datetime "created_at"
t.datetime "updated_at"
end
end
The code you have written should mostly work, but there is a subtle error in it:
The belongs_to association uses the singular (as in belongs_to :manufacturer), but for the associationhas_many, you have to use the plural:
class DesText < ActiveRecord::Base
set_table_name "DES_TEXTS"
set_primary_key :TEX_ID
has_many :country_designations
has_many :designations
end
Please ensure that the relevant keys are set in your tables. Here are the rules for you:
Every has_many association (see Rails Guides) needs that the many part has a reference to the one part. In your example: Model needs a reference to CountryDesignation. Rails thinks that your model table includes a column country_designation_id (which it will not find).
Similar for DES_TEXTS and COUNTRY_DESIGNATIONS.
After having corrected that, you should be able to use the following code (only the changed one with the deep access over some objects):
- #manufacturer.models.each do |model|
%tr
%p
...
%td= model.country_designation.des_text.FIELD
= link_to 'Show model', model
This will show inside a loop for each model of the manufacturer the des_text of its country_designation.
But be careful: This is only an example and will only work, if every model has a country designation and every country designation has a des_text.
It is unfortunate that you use an existing db scheme, it makes a lot of things more difficult. I would give you the following advice here:
Migrate to a clean state with names rails suspects.
Test after each migration, if your model conforms to the rules by using the console of Rails. You can start then rails c and type there in commands you think should work.
Your application is a the moment to big and complicated, so I don't think there is a chance to debug it further here ... (sorry, but this is the fourth time I add to my answer, and it looks more like a Rails tutorial now)
Related
I am making a Band application where a Venue has many Events and Bands through Events.
I realized that in my form for creating an event can only hold one band_id
but I want to have many bands because it only makes sense to do so.
This is my Schema
ActiveRecord::Schema.define(version: 20170817180728) do
create_table "bands", force: :cascade do |t|
t.string "name"
t.string "genre"
t.string "image"
t.boolean "explicit_lyrics"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "events", force: :cascade do |t|
t.string "name"
t.text "date"
t.boolean "alcohol_served"
t.string "image"
t.integer "venue_id"
t.integer "band_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "venues", force: :cascade do |t|
t.string "name"
t.string "city"
t.string "state"
t.boolean "family_friendly"
t.string "image"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
These are my models
class Venue < ApplicationRecord
has_many :events
has_many :bands, through: :events
end
class Event < ApplicationRecord
belongs_to :venue
belongs_to :band
end
class Band < ApplicationRecord
has_many :events
end
I am fairly new to rails this is a practice web app. I want to be able to be able to show multiple band_ids to my event.
Would I just keep repeating t.band_id in my form??
You'll want to specify a foreign key relationship in your migration that reflects the Active Record associations you've set up in your models using belongs_to instead of a data type. This way, you'll get a references from one table to another, or in your case, from one table to two others, which is how one table with two one-to-many relationships is set up.
class CreateEvents < ActiveRecord::Migration
def change
create_table :venues do |t|
t.string :name
t.string :city
t.string :state
t.boolean :family_friendly
t.string :image
t.timestamps
end
create_table :bands do |t|
t.string :name
t.string :genre
t.string :image
t.boolean :explicit_lyrics
t.timestamps
end
create_table :events do |t|
t.belongs_to :venue, index: true # Look here!
t.belongs_to :band, index: true # and here!
t.string :name
t.text :date
t.boolean :alcohol_served
t.string :image
t.timestamps
end
end
end
I'm trying to make an e-commerce website type thing using Rails. So I've made my models for it. My problem is how to make a particular element a primary key?
create_table "bookmarks", :primary_key => bk_id force: :cascade do |t|
t.string "bk_name"
t.string "size"
t.string "brand"
t.string "product_id"
t.integer "mrp"
t.text "colour"
t.integer "stock"
t.integer "discount"
t.text "bk_description"
t.integer "bk_id", primary:true
t.integer "cart_unit"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
This is a portion of the schema.rb file. Is the way I've marked bookmark id as the primary key correct? Also, after making these changes, I ran rails db:migrate command and the primary key portion disappears and it becomes like this-
create_table "bookmarks",force: :cascade do |t|
t.string "bk_name"
t.string "size"
t.string "brand"
t.string "product_id"
t.integer "mrp"
t.text "colour"
t.integer "stock"
t.integer "discount"
t.text "bk_description"
t.integer "bk_id"
t.integer "cart_unit"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
I don't understand why this happened and why those changes I made (I did save the file after editing) just disappeared. Can someone explain this to me? Also, I'd like to mention that I'm learning Ruby on Rails so...please be gentle with me. :P
In your migration file:
create_table :bookmarks, :primary_key => :bk_id do |t|
...
t.integer :bk_id
...
end
Do not forget to indicate it in your Model too:
class Bookmarks < ActiveRecord::Base
self.primary_key = 'bk_id'
end
Assuming it’s Rails4+, you might do:
create_table :bookmarks, force: :cascade do |t|
...
t.integer :bk_id, primary_key: true
...
end
In Rails3 you just put an additional statement after:
create_table "bookmarks", force: :cascade do |t|
...
t.integer "bk_id"
...
end
execute "ALTER TABLE bookmarks ADD PRIMARY KEY (bk_id);"
Don't change content of schema.rb file. This content will be auto generated from your migrate files. Try find your create bookmarks migrate file and add :primary_key => bk_id to it.
File: db/migrate/xxxxxxxxxx_create_bookmarks.rb
(xxxxxxxxx is a timestamp)
Help it helps.
I have this problem, but don't know why.
I create models with generator:
bin/rails generate model Book name:string author:string description:text cover:string
bin/rails generate model Episode name:string description:text art:string
ant other...
book.rb
class Book < ApplicationRecord
has_many :episodes
end
episode.rb
class Episode < ApplicationRecord
belongs_to :book
has_many :scenes
end
When in console i try to: book.episodes << episode i had an error: ActiveModel::MissingAttributeError: can't write unknown attribute "book_id"
My schema.rb
ActiveRecord::Schema.define(version: 20170320111956) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "answers", force: :cascade do |t|
t.text "text"
t.string "next_scene"
t.string "next_episode"
t.string "voiceover"
t.integer "end"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "books", force: :cascade do |t|
t.string "name"
t.string "author"
t.text "description"
t.string "cover"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "episodes", force: :cascade do |t|
t.string "name"
t.text "description"
t.string "art"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "scenes", force: :cascade do |t|
t.string "name"
t.text "text"
t.integer "choise"
t.string "next_scene"
t.string "next_episode"
t.string "art"
t.string "music"
t.string "sound_fx"
t.string "voiceover"
t.integer "end"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
In schema i haven't id_book, but why? I also do db:migrate and have error again.
By default, Rails uses the convention of naming the primary as the autogenerated column id. If you wish to specify a different primary key, such as book_id, you could do the following:
class Book < ApplicationRecord
self.primary_key = "book_id"
end
I'm rails begginer.
how to load database that has following condition.
I want show lecture list that has order by comment.created_at DESC
schema.rb
create_table "comments", force: :cascade do |t|
t.text "content"
t.integer "user_id"
t.integer "lecture_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "likedcount", default: 0
end
create_table "lectures", force: :cascade do |t|
t.string "subject"
t.string "professor"
t.string "major"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "uptachi", default: 0
t.integer "hatachi", default: 0
end
lecture.rb
has_many :comments
comment.rb
belongs_to: lectures
You need to write it as:
has_many :comments, -> { order("comments.created_at DESC") }
As per the OP's comment, it seems, what he want is a named scope. Like,
scope :order_by_comments, -> { joins(:comments).order("comments.created_at DESC") }
The more i read about foreign keys in rails i am getting more and more confused. In a post i read that its sufficient to add belongs_to and has_many/has_one in respective model file to getting things done. But again in another post I read that the index should be added to reference another table. Suppose There is writers table and book table in dbms while creating Books table we have to add
FOREIGN KEY (writers_Id) REFERENCES Writers(Id)
but in rails we in writer model we add has_many :book an in book model we add belongs_to :writer is both are equivalent ?
If both are equivalent then why we add index such as
add_index :books, :writer_id
I have project on which I am working on it has users has one personal information, academic information, application and rank. Also there is subject_streams which have streams and streams have cutoffs. Finally there is category which is independent. I dont know if i modeled data correctly but in the schema.rb am I doing correctly what i have said ?
ActiveRecord::Schema.define(version: 20140713133617) do
create_table "academics", force: true do |t|
t.integer "user_id"
t.integer "tenth_roll", default: 0
t.integer "tenth_year_pass", default: 2000
t.decimal "tenth_marks_percent", precision: 10, scale: 2, default: 40.0
t.string "tenth_board"
t.integer "hs_roll", default: 0
t.integer "hs_year_pass", default: 2002
t.decimal "hs_marks_percent", precision: 10, scale: 2, default: 40.0
t.string "hs_board"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "calculated_marks"
t.string "sub1"
t.integer "sub1_marks"
t.string "sub2"
t.integer "sub2_marks"
t.string "sub3"
t.integer "sub3_marks"
t.string "sub4"
t.integer "sub4_marks"
t.string "sub5"
t.integer "sub5_marks"
t.string "sub6"
t.integer "sub6_marks"
t.string "sub7"
t.integer "sub7_marks"
t.string "sub8"
t.integer "sub8_marks"
t.string "sub9"
t.integer "sub9_marks"
t.string "sub10"
t.integer "sub10_marks"
t.integer "subject_streams_id"
end
add_index "academics", ["user_id"], name: "index_academics_on_user_id", unique: true, using: :btree
create_table "applications", force: true do |t|
t.integer "user_id"
t.integer "stream_id"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "verified", default: false
end
add_index "applications", ["user_id"], name: "index_applications_on_user_id", unique: true, using: :btree
create_table "categories", force: true do |t|
t.string "category"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "cutoffs", force: true do |t|
t.integer "stream_id"
t.integer "category_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "cutoff_marks"
end
add_index "cutoffs", ["stream_id"], name: "index_cutoffs_on_stream_id", using: :btree
create_table "personals", force: true do |t|
t.integer "user_id"
t.date "date_of_birth"
t.string "gender"
t.string "blood_group"
t.string "fathers_name"
t.string "mothers_name"
t.text "address_present"
t.datetime "created_at"
t.datetime "updated_at"
t.string "first_name"
t.string "middle_name"
t.string "last_name"
t.integer "category_id"
t.string "image"
t.string "avatar"
end
add_index "personals", ["user_id"], name: "index_personals_on_user_id", unique: true, using: :btree
create_table "ranks", force: true do |t|
t.integer "user_id"
t.integer "rank"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "ranks", ["user_id"], name: "index_ranks_on_user_id", unique: true, using: :btree
create_table "registers", force: true do |t|
t.boolean "active"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "simple_captcha_data", force: true do |t|
t.string "key", limit: 40
t.string "value", limit: 6
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "simple_captcha_data", ["key"], name: "idx_key", using: :btree
create_table "streams", force: true do |t|
t.string "stream"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "seats"
t.integer "subject_stream_id"
end
add_index "streams", ["subject_stream_id"], name: "index_streams_on_subject_stream_id", using: :btree
create_table "subject_streams", force: true do |t|
t.string "subject_stream"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true 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"
t.datetime "updated_at"
t.integer "level", default: 1
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
end
In Ruby on Rails, the code has_many :books and belongs_to :writer is like defining relationships in the code level. It doesnt achieve anything in the database level. For example, if we write belongs_to :writer in the Book model, it just means that if there is a column writer_id in the books table, we can code something like this:
b = Book.first
b_writer = b.writer
#### equivalent to
# b_writer = Writer.find(b.writer_id)
# b_writer = Writer.where(:id => b.writer_id).first
# or b_writer = Writer.find_by_sql("SELECT writers.* from writers where writers.id = #{b.writer_id}")
It assumes that the foreign key is writer_id in books table by convention. If we need to change the foreign key for the queries generated by association, we need to specify it separately:
belongs_to :writer, :foreign_key => 'writerID'
So, in general declaring associations in models, gives us some utility methods to query those associations from database, instead of creating the queries manually. So, all the database related changes needs to be done in the migrations, like adding the column writer_id, adding index for column writer_id, setting writer_id with forieign key constraint etc. Rails does not support foreign_key constraint in migrations by default, as different databases handle foreign_key differently. For PostGre and MySQL database, you can use foreigner gem for adding foreign_key constraint.
Please read more about Rails associations