您可以使用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的底部添加了一些示例来处理和构建这些关联。根据你需要做什么,这个设置可能意味着更多的数据库查询,但我认为它使得数据和关系灵活且非常容易处理 –