您可以使用Rake
的sh
方法,只需調用rails
shell命令。
sh "rails g migration AddPay#{initials}ToShoppingLists pay#{initials}:decimal"
sh "rails g migration AddPay#{initials}ToPayments pay#{initials}:decimal"
當使用sh
而不是紅寶石的內置反引號分隔符的shell命令,如果命令具有比其他0
退出狀態,將引發異常並中止任務。
要查看您的遷移是否已創建,您只需檢查是否存在與命名模式匹配的遷移文件。
files = Dir.glob Rails.root.join('db/migrate/*')
migration_patterns = {
/add_pay_#{initials.downcase}_to_shopping_lists/ => "rails g migration AddPay#{initials}ToShoppingLists pay#{initials}:decimal",
/add_pay_#{initials.downcase}_to_payments/ => "rails g migration AddPay#{initials}ToPayments pay#{initials}:decimal"
}
migration_patterns.each do |file_pattern, migration_command|
if files.none? { |file| file.match? file_pattern }
sh migration_command
end
end
Rake::Task['db:migrate'].invoke
這假定您不會有任何遷移命名衝突,導致none?
中出現誤報。但Rails不會讓你遷移命名衝突,所以檢查可能沒有必要。看起來你肯定會遇到這個問題,最終會考慮到你命名遷移和列的方式。如果兩個用戶具有相同的首字母縮寫呢?
可能有一種方法可以通過使用額外的數據庫表(可能是多態連接表?)而不是爲每個user
添加列來完成所需的操作?沿着這些線的東西可以工作:
class CreateDisbursements < ActiveRecord::Migration[5.1]
def change
create_table :disbursements do |t|
t.decimal :amount
t.integer :payable_id
t.string :payable_type
t.integer :receivable_id
t.string :receivable_type
t.timestamps
end
add_index :disbursements, [:payable_type, :payable_id]
add_index :disbursements, [:receivable_id, :receivable_type]
end
end
class Disbursement < ApplicationRecord
belongs_to :payable, polymorphic: true
belongs_to :receivable, polymorphic: true
end
class ShoppingList < ApplicationRecord
has_many :disbursements, as: :payable
has_many :users, through: :disbursements, source: :receivable, source_type: 'User'
end
class Payment < ApplicationRecord
has_many :disbursements, as: :payable
has_many :users, through: :disbursements, source: :receivable, source_type: 'User'
end
class User < ApplicationRecord
has_many :disbursements, as: :receivable
has_many :payments, through: :disbursements, source: :payable, source_type: 'Payment'
has_many :shopping_lists, through: :disbursements, source: :payable, source_type: 'ShoppingList'
end
user = User.find params[:user_id]
payment = Payment.find params[:payment_id]
amount = params[:amount]
payment.disbursements.create(amount: amount, receivable: user)
user.disbursements.create(amount: amount, payable: payment)
Disbursement.create(amount: amount, payable: payment, receivable: user)
user.payments
payment.users
謝謝,這是完美的 - 用戶將不會有初始衝突,因爲它被設置爲唯一。 (他們不是真正的名字更像id鍵)。我會對你的第二個建議有所瞭解,看看我是否保持了我所需要的速度。 – Darkstarone
很高興幫助!我在一些API的底部添加了一些示例來處理和構建這些關聯。根據你需要做什麼,這個設置可能意味着更多的數據庫查詢,但我認爲它使得數據和關係靈活且非常容易處理 –