Rails: auto update reference table when update foreign_key - ruby-on-rails

When i try to update foreign_key for table BusinessCard. It auto update the Company table without needed.
My Console Image
Can someone help me with this. Thanks
Edit---
My Controller
def update
#bc = BusinessCard.find_by(business_card_id: params[:id], deleted: false)
raise "名刺情報は存在しておりません。" unless #bc
raise "同じ名刺情報が存在しております。" if (#bc.name != params[:name] or #bc.email != params[:email] or #bc.company.name != params[:c_name]) and BusinessCard.joins(:company).where(name: params[:name], email: params[:email], deleted: 0, 'companies.name' => params[:c_name]).exists?
ActiveRecord::Base.transaction do
##bc.name = params[:name]
##bc.email = params[:email]
##bc.tel = params[:tel]
##bc.furigana = params[:furigana]
##bc.recieve_date = params[:recieve_date]
##bc.update_by = #current_user.user_id
#Company
#bc.company_id = bz_company if params[:c_name] and params[:c_post_code]
#department
##bc.department_id = bz_department if params[:d_name]
raise #bc.errors unless #bc.save
#images
#bz_omt if params[:i_omt]
#bz_ura if params[:i_ura]
end
render_json(#bc, :ok)
end
def bz_company
#company = Company.find_by(name: params[:c_name], post_code: params[:c_post_code])
#company = Company.new(name: params[:c_name], post_code: params[:c_post_code], create_by: #current_user.user_id) unless #company
#company.address = params[:c_address]
#company.email = params[:c_email]
#company.tel = params[:c_tel]
#company.fax = params[:c_fax]
#company.url = params[:c_url]
#company.deleted = 0
#company.update_by = #current_user.user_id
raise #company.errors unless #company.save
#company.company_id
end
BusinessCard Model
class BusinessCard < ApplicationRecord
#Association
#With Tag
has_many :map_tags, primary_key: 'business_card_id', foreign_key: 'business_card_id'
has_many :tags, :through => :map_tags
#with Comment
has_many :map_comments, primary_key: 'business_card_id', foreign_key: 'business_card_id'
has_many :comments, :through => :map_comments
#with Company
has_one :company, primary_key: 'company_id', foreign_key: 'company_id'
#with department
has_one :department, primary_key: 'department_id', foreign_key: 'department_id'
#with file_locations
has_many :file_locations, primary_key: 'business_card_id', foreign_key: 'business_card_id'
end
Company Model
class Company < ApplicationRecord
#Association
has_many :business_cards, primary_key: 'company_id', foreign_key: 'company_id'
end
Company Migration
class CreateCompanies < ActiveRecord::Migration[5.0]
def change
create_table :companies, id: false do |t|
t.column :company_id, 'INTEGER PRIMARY KEY AUTOINCREMENT'
t.string :name, limit: 150, null: false
t.text :address, limit: 1000, null: false
t.string :email, limit: 129
t.string :tel, limit: 20
t.string :fax, limit: 20
t.string :url, limit: 150
t.boolean :deleted, default: false
t.integer :create_by
t.integer :update_by
t.timestamps
end
end
end
BusinessCard Migration
class CreateBusinessCards < ActiveRecord::Migration[5.0]
def change
create_table :business_cards, id: false do |t|
t.column :business_card_id, 'INTEGER PRIMARY KEY AUTOINCREMENT'
t.string :name, limit: 50, null: false
t.string :furigana, limit: 50
t.string :email, limit: 129, null: false
t.string :tel, limit: 20, null: false
t.integer :owner_id
t.datetime :recieve_date
t.integer :company_id, null: false
t.integer :department_id, null: false
t.boolean :deleted, default: false
t.integer :create_by
t.integer :update_by
t.timestamps
end
add_index :business_cards, :business_card_id, :unique => true
end
end

Try this:
instead this in BusinnesCard Model
has_one :company, primary_key: 'company_id', foreign_key: 'company_id'
put this
belongs_to :company, primary_key: 'company_id', foreign_key: 'company_id'
PS Your code is little diry, i recommend you to replace primary_keys. For example, instead company_id, use id

You are using primary key column names that do not follow Rails' conventions. Therefore you have to tell Rails the names with primary_key= in your models:
# in app/models/company.rb
self.primary_key = 'company_id'
# in app/models/business_card.rb
self.primary_key = 'business_card_id'

Related

How do I write a finder when I have a belongs_to relationship but no underlying database column? [duplicate]

I'm working with a legacy database that gives the following schema for the tables product and familia_producto (rake db:schema:dump)
create_table "producto", primary_key: "barcode", force: true do |t|
t.string "codigo_corto", limit: 16, null: false
t.string "marca", limit: 35
t.string "descripcion", limit: 50
t.string "contenido", limit: 10
t.string "unidad", limit: 10
t.float "stock", default: 0.0
t.float "precio"
t.float "precio_neto"
t.float "costo_promedio"
t.float "fifo"
t.float "vendidos"
t.boolean "aplica_iva"
t.integer "otros_impuestos", limit: 2
t.integer "familia", limit: 2, default: 1, null: false
t.integer "id_tipo_producto", limit: 2, null: false
t.boolean "es_perecible"
t.float "dias_stock", default: 1.0
t.float "margen_promedio", default: 0.0
t.boolean "es_venta_fraccionada"
t.float "stock_pro", default: 0.0
t.float "tasa_canje", default: 1.0
t.float "precio_mayor"
t.float "cantidad_mayor"
t.boolean "es_mayorista"
t.boolean "estado"
t.boolean "precio_editable"
end
create_table "familia_producto", force: true do |t|
t.string "nombre", limit: 32, null: false
end
In the models I've this
class FamiliaProducto < ActiveRecord::Base
self.table_name = 'familia_producto'
has_many :productos, :class_name => 'Producto', :primary_key => 'barcode', :foreign_key => 'familia'
end
class Producto < ActiveRecord::Base
self.table_name = 'producto'
belongs_to :familia_producto, :class_name => 'FamiliaProducto'
end
But when I call the .familia the producto object throws me a number, not the FamiliaProducto object.
2.1.0 :012 > p = Producto.all[0]
Producto Load (1.7ms) SELECT "producto".* FROM "producto"
=> #<Product......
2.1.0 :013 > p.familia
=> 2
That 2 should be the FamiliaProducto object.
You must use the name of the association, also need to add the foreign key to the belongs_to
class Producto < ApplicationRecord
belongs_to :familia_producto, class_name: 'FamiliaProducto', foreign_key: 'familia'
end
class FamiliaProducto < ApplicationRecord
has_many :productos, class_name: 'Producto', foreign_key: 'familia'
end
p = Producto.first
# Returns a FamiliaProducto object
p.familia_producto
# Returns an integer
p.familia

Why is my controller not saving my object in the database?

I am saving an entry object for CalendarEntry which is my model, but in the view when I click "Done" for some reason the object doesn't save.
In my point of view my controller is fine, but maybe the issue is there:
Controller
def create
#entry = CalendarEntry.new(entries_params)
binding.pry
if #entry.save
render 'admins/calendar_entries/index'
else
render 'admins/calendar_entries/new'
end
end
def entries_params
conversions
params.require(:calendar_entry).permit(:entry_type, :entry_level, :visible, :title, :publication_date, :expiration_date, :content, :phonenumber, :website, :state, :city, :address)
end
def conversions
params[:calendar_entry][:entry_type] = params[:calendar_entry][:entry_type].to_i
params[:calendar_entry][:entry_level] = params[:calendar_entry][:entry_level].to_i
end
Console
As you see in the console is asking me for two values "calendar_categories" and "calendar_entry_categories", but how it's supposed to ask it because my "CalendarEntry" only ask for the values in there,
P.D. The id, created_at and updated_at is generated automatically.
Update July/17 - 11:12pm
Schema defined here:
create_table "calendar_categories", 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 "calendar_entries", force: :cascade do |t|
t.integer "entry_type"
t.integer "entry_level"
t.boolean "visible"
t.string "title"
t.datetime "publication_date"
t.datetime "expiration_date"
t.text "content"
t.string "phonenumber"
t.string "website"
t.string "state"
t.string "city"
t.string "address"
t.string "profile_picture"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "calendar_entry_categories", force: :cascade do |t|
t.bigint "calendar_entry_id"
t.bigint "calendar_category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["calendar_category_id"], name: "index_calendar_entry_categories_on_calendar_category_id"
t.index ["calendar_entry_id"], name: "index_calendar_entry_categories_on_calendar_entry_id"
end
Model defined here:
class CalendarEntry < ApplicationRecord
scope :visible, -> { where(visible: true) }
scope :invisible, -> { where(visible: false) }
scope :expired, -> { where('expiration_date < ?', Time.zone.now) }
scope :active, -> { where('expiration_date >= ?', Time.zone.now) }
has_many :calendar_entry_categories, dependent: :destroy
has_many :calendar_categories, through: :calendar_entry_categories
enum entry_type: %i[event program]
enum entry_level: %i[municipal statal federal injuve]
mount_uploader :profile_picture, CalendarEntryProfilePictureUploader
validates :entry_type, :entry_level, :visible, :title,
:expiration_date, :content, :phonenumber, :website, :state, :city,
:address, :calendar_categories,
:calendar_entry_categories, presence: true
validates :publication_date, presence: true, on: :update
validates :title, uniqueness: true
validates :phonenumber, numericality: { only_integer: true }
validates :phonenumber, length: { is: 10 }
validates_inclusion_of :entry_type, in: CalendarEntry.entry_types
validates_inclusion_of :entry_level, in: CalendarEntry.entry_levels
validate :expiration_date_range
before_validation :init, on: :create
private
def init
self.publication_date ||= Time.zone.now
end
def expiration_date_range
return if !expiration_date.nil? && expiration_date > publication_date
errors.add(:expiration_date, :past_expiration_date)
end
end
It looks like you're trying to validate the presence of calendar_categories and calendar_entry_categories in your model validations.
You won't be able to validate their presence, considering a CalendarEntryCategory cannot exist until a CalendarEntry exists, and a CalendarCategory might not always exist when a CalendarEntry is created.
Therefore, to get this to work, all you should have to do is remove
:calendar_categories, :calendar_entry_categories from the presence: true validations in your CalendarEntry model.

Rails create record fails

Here is my table structure
class CreateStudentAssignments < ActiveRecord::Migration[5.1]
def change
create_table :student_assignments do |t|
t.string :title
t.string :subject
t.text :description
t.float :amount, default: 0
t.date :start_date
t.date :due_date
t.integer :word_count
t.time :approximate_estimated_duration
t.boolean :active, default: true
t.float :overall_rating
t.integer :view_count, default: 0
t.boolean :assignment_approved, default: false
t.references :assignment_status, foreign_key: true
t.references :student, foreign_key: { to_table: :users }
t.references :difficulty_level, foreign_key: true
t.references :writer, foreign_key: { to_table: :users } # Assignment accepted writer
t.timestamps
end
end
end
While try to create a record
p = {title: "title", subject: "subject", description: "des", amount: 5.00, start_date: Date.today + 1, due_date: Date.today + 5, word_count: 100, approximate_estimated_duration: 1000, overall_rating: 4, view_count:4, assignment_status: AssignmentStatus.last, difficulty_level_id: 4, student: User.last}
StudentAssignment.create(p).errors
ActiveModel::MissingAttributeError: can't write unknown attribute `student_id`
from (irb):56
How to pass that user?
Thanks in advance

problems with a scope in habtm

I have a habtm relationship between Dish and DailyMenu. Here is a scope
scope :menu_available, -> (type_id, daily_menu_id){ where('dish_type_id = ?', type_id) & where(joins(:daily_menus).where.not('daily_menu_id = ?', daily_menu_id)) }
It intends to find dishes of some type but that are not currently included in menu. Sadly it does not work correctly. Need some help please
A DishType model
class DishType < ActiveRecord::Base
include DishTypeSetter
enum meal:[:main_course, :second_course, :drink]
end
Dish model
class Dish < ActiveRecord::Base
has_and_belongs_to_many :daily_menus
has_many :orders
has_many :users, through: :orders
belongs_to :dish_type
scope :main_meals, -> { joins(:dish_type).where('meal = ?', 0) }
scope :second_meals, -> { joins(:dish_type).where('meal = ?', 1) }
scope :drinks, -> { joins(:dish_type).where('meal = ?', 2) }
#scope :menu_available, -> (type_id, daily_menu_id){ where('dish_type_id = ?', type_id) & where(joins(:daily_menus).where.not('daily_menu_id = ?', daily_menu_id)) }
scope :menu_available, lambda { |type_id, daily_menu_id|
where(joins(:daily_menus).where('daily_menu_id != ? AND dish_type_id = ?', daily_menu_id, type_id))
}
validates :dish_type, :name, presence: true
validates :name, uniqueness: { scope: :dish_type_id }
end
Menu model
class DailyMenu < ActiveRecord::Base
has_and_belongs_to_many :dishes
has_many :orders
has_many :users, through: :orders
end
Also about DishType model - it only has has_many dishes association(I moved this to a concern)/ But it does not have has_many daily_menus/
create_table "daily_menus", force: :cascade do |t|
t.string "day"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.date "date"
end
add_index "daily_menus", ["day"], name: "index_daily_menus_on_day", unique: true, using: :btree
create_table "daily_menus_dishes", force: :cascade do |t|
t.integer "daily_menu_id"
t.integer "dish_id"
end
create_table "dish_types", force: :cascade do |t|
t.integer "meal"
end
create_table "dishes", force: :cascade do |t|
t.string "name"
t.integer "type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "dish_type_id"
end
add_index "dishes", ["dish_type_id", "name"], name: "index_dishes_on_dish_type_id_and_name", unique: true, using: :btree
scope :menu_available, lambda { |type_id, daily_menu_id|
joins(:daily_menus)
.where('dishes.dish_type_id = ? AND daily_menus.id != ?', type_id, daily_menu_id)
}

FactoryGirl::InvalidFactoryError (factory_girl-4.4.0/lib/factory_girl.rb:73:in `lint')

I can't understand why this factory is invalid (FactoryGirl::InvalidFactoryError (factory_girl-4.4.0/lib/factory_girl.rb:73:in `lint').
Here it is:
FactoryGirl.define do
factory :building do
sequence(:map_index) { |n| "#{n}" }
static_building_id 1
finished_at Time.now + 1.hour #This row is the problem!
user
end
end
Here is the user factory:
FactoryGirl.define do
factory :user do
sequence(:email) { |n| "test_mail#{n}##gmail.com" }
sequence(:password) { |n| "password-#{n}" }
sequence(:username) { |n| "username-#{n}" }
end
end
And this is my schema.rb:
ActiveRecord::Schema.define(version: 20140726162156) do
create_table "buildings", force: true do |t|
t.integer "user_id"
t.integer "static_building_id"
t.integer "level"
t.datetime "time_creation"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "map_index"
t.datetime "finished_at"
end
Here is my model:
class Building < ActiveRecord::Base
belongs_to :user
validates :map_index, length: { in: 0..10}
validates :static_building_id, length: { in: 0..10}
validates :map_index, :static_building_id, presence: true
before_create :initialize_building
private
def initialize_building
self.level = 1
end
end
Note that without the column finished_at (both in the db and in the factory) everything works well... Any idea?

Resources