Rake
のsh
メソッドを使用して、rails
シェルコマンドを呼び出すことができます。
sh "rails g migration AddPay#{initials}ToShoppingLists pay#{initials}:decimal"
sh "rails g migration AddPay#{initials}ToPayments pay#{initials}:decimal"
とは対照的に、sh
を使ってRubyの組み込みのシェルコマンドのバッククォートの区切り文字、コマンドは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はネーミングの衝突を起こさせないので、チェックは必要ないかもしれません。最終的には、移行と列の名前付けの方法を考えれば、この問題に直面するように思えます。 2人のユーザーのイニシャルが同じ場合はどうなりますか?
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キーのようなイニシャルではありません)。私はあなたの第2の提案で亀裂があり、あなたが必要とするスピードを保つかどうかを確認します。 – Darkstarone
助けてくれてうれしい!これらの関連付けを行い、作成するためのAPIの一番下にいくつかの例を追加しました。あなたが何をする必要があるかによって、この設定はより多くのdbクエリを意味するかもしれませんが、データとリレーションシップを柔軟にし、使いやすくすると思います –