2017-08-24 77 views
8

我有以下型號保存它們指向對方的ActiveRecord協會,在一次

class Cargo < ApplicationRecord 
    has_many :destinations 
    has_many :assignments 
    accepts_nested_attributes_for :destinations 
    accepts_nested_attributes_for :assignments 
end 

class Destination < ApplicationRecord 
    has_one :assignment_coming_to_me, class_name: 'Assignment', foreign_key: 'arrive_destination_id' 
    has_one :assignment_leaving_me, class_name: 'Assignment', foreign_key: 'start_destination_id' 
end 

class Assignment < ApplicationRecord 
    belongs_to :start_from, class_name: 'Destination', foreign_key: 'start_destination_id' 
    belongs_to :arrive_at, class_name: 'Destination', foreign_key: 'arrive_destination_id' 
end 

給人一種視覺形象,它是這樣的

   +-------------+ 
      +---| Destination | 
      | +-------------+---+ <= start_from 
      |      | +------------+ 
      |      +---| Assignment | 
      |      | +------------+ 
+-------+ | +-------------+---+ <= arrive_at 
| Cargo | --+---| Destination | 
+-------+ | +-------------+---+ <= start_from 
      |      | +------------+ 
      |      +---| Assignment | 
      |      | +------------+ 
      | +-------------+---+ <= arrive_at 
      +---| Destination | 
      | +-------------+---+ 
      |      | 
      .      . 
      .      . 

現在,是有辦法一次創建整個記錄,給定這樣的參數? (假設目標和任務是互相關聯,就像參數數組的順序)

{ 
    cargo: [ 
    destinations_attributes: [{place_id: ..}, {place_id: ...}, ...], 
    assignments_attributes: [{assignee_id: ..}, {assignee_id: ...}, ...], 
    ] 
} 

我知道先保存目的地,然後通過他們迭代設置分配的目標ID可以做的工作,但不知道是否有一個更聰明的方式。

+0

如果我理解你的模式,要通過它的目的地跟蹤的東西。我認爲有更好的方式來安排你的模型關聯。可以請將您的數據庫架構發佈到這三個表中。 –

+0

@佩德羅Assignmet有start_destination_id和goal_destination_id,目的地有cargo_id,這幾乎是要點 – Ryo

回答

1

那麼,不知道你的問題的細節我會回答我認爲這將是一個「輕鬆」的方式來解決。

通過使用相關聯的地方的has_many你會:

貨物必須通過分配多個目的地。

目的地有許多貨物通過分配。

分配保存貨物和目的地外鍵。

如果您需要有關目的地順序的信息,則可以根據作業的創建時間戳查詢記錄。

這裏有一個example-of-has-many-through-using-nested-attributes。我相信你可以通過這種方式來保存所有記錄「自動」。此外,您可以讓協會提供的查詢處理所有三個表的記錄!

讓我知道你在想什麼! 祝你好運!

鏈接guide rails has_many_through assoaciton

+0

感謝您的答案,但據我所知它不適用於我的情況。嵌套屬性將嘗試除非params爲指定的ID,以創造新的紀錄,所以它會共4個獨立的新的分配創造了兩座相鄰的目的地,而不是在它們中的哪一個作爲圖說明共享3個分配。 – Ryo

+0

你對嵌套屬性是正確的。如果您需要一起保存,則此關聯不起作用。抱歉! –

1

層次結構過於豐富的建築用途: 我能複製它所有的工作流程:

在我離開的意見

您可以運行代碼的結尾在終端的代碼只是將它複製到test.rb文件,並在終端

運行ruby test.rb而之前,在PostgreSQL中創建(或MySQL)數據庫

require "active_record" 

class Cargo < ActiveRecord::Base 
    establish_connection adapter: 'postgresql', database: 'test_destination' 

    connection.create_table table_name, force: true do |t| 
    t.string :name 
    end 

    has_many :delivery_places 

    accepts_nested_attributes_for :delivery_places 
end 

class DeliveryPlace < ActiveRecord::Base 
    establish_connection adapter: 'postgresql', database: 'test_destination' 

    connection.create_table table_name, force: true do |t| 
    t.string  :name 
    t.integer :order, default: 0 
    t.datetime :arrived_at 
    t.belongs_to :cargo 
    end 

    belongs_to :cargo 
    has_one :assigment 

    accepts_nested_attributes_for :assigment 
end 

class Assignee < ActiveRecord::Base 
    establish_connection adapter: 'postgresql', database: 'test_destination' 

    connection.create_table table_name, force: true do |t| 
    t.string :name 
    end 

    has_many :assigments 
    has_many :delivery_places, through: :assigments 
    has_many :cargos, through: :delivery_places 
end 

class Assigment < ActiveRecord::Base 
    establish_connection adapter: 'postgresql', database: 'test_destination' 

    connection.create_table table_name, force: true do |t| 
    t.belongs_to :delivery_place 
    t.belongs_to :assignee 
    end 

    belongs_to :delivery_place 
    belongs_to :assignee 
    accepts_nested_attributes_for :assignee 
end 

nikolay = Assignee.create! name: 'Nikolay' 
dec12 = DateTime.new(2017, 12, 12) 
dec13 = DateTime.new(2017, 12, 13) 
dec14 = DateTime.new(2017, 12, 14) 

Cargo.create! \ 
    name: 'candies', 
    delivery_places_attributes: [ 
    { 
     name: 'Moscow', 
     order: 0, 
     arrived_at: dec12, 
     assigment_attributes: { 
     assignee_id: nikolay.id 
     } 
    }, 
    { 
     name: 'Tokio', 
     order: 1, 
     arrived_at: dec13, 
     assigment_attributes: { 
     assignee_attributes: { 
      name: 'Ryo' 
     } 
     } 
    }, 
    { 
     name: 'Ny York', 
     order: 2, 
     arrived_at: dec14, 
     assigment_attributes: { 
     assignee_attributes: { 
      name: 'John' 
     } 
     } 
    } 
    ] 


# Let's find all my cargos 
puts nikolay.cargos 
# => [#<Cargo:0x007fae3e4475e8 id: 1, name: "candies">] 

# Do I have any cargos since 13 december till 14 december? 
puts nikolay.cargos.joins(:delivery_places).where(delivery_places: { arrived_at: dec13...dec14 }).distinct 
# [] 

# Do I have any cargos since 12 december till 14 december? 
puts nikolay.cargos.joins(:delivery_places).where(delivery_places: { arrived_at: dec12...dec14 }).distinct 
# => [#<Cargo:0x007fefac16a460 id: 1, name: "candies">] 

# Do I have cargo which I sent? 
nikolay.cargos.joins(:delivery_places).where(delivery_places: { order: 0 }).distinct 
# => [#<Cargo:0x007fefac16a460 id: 1, name: "candies">] 
+0

謝謝你的回答,但是它不是@Pedro的答案。 – Ryo