Как вставлять строки при использовании отношения «многие ко многим»

Учитывая следующее, как я могу вставлять строки в свою базу данных? (Или что мне исправить в моей схеме?)

Модели:

class Item < ActiveRecord::Base
    has_many                            :tran_items
    has_many :transactions, :through => :tran_items
end
class TranItem < ActiveRecord::Base
    belongs_to :item
    belongs_to :transaction
end
class Transaction < ActiveRecord::Base #answer: rename Transaction
    has_many                            :tran_items
    has_many :items, :through =>        :tran_items
end

Схема:

create_table :items do |t|
  t.references :tran_items #answer: remove this line
  t.string     :name
end
create_table :tran_items do |t|
  t.belongs_to :items,  :transactions,  :null => false #answer: unpluralize
  t.integer    :quantity
end
create_table :transactions do |t|
  t.references :tran_items #answer: remove this line
  t.decimal    :profit
end

Я потерял несколько часов, пытаясь вставить записи, используя консоль rails для проверки.


person Daniel Jomphe    schedule 12.11.2008    source источник
comment
Взгляните на этот пост « title = «как сохранить в базу данных с помощью ассоциаций в рельсах, защищающих массовое присвоение»> stackoverflow.com/questions/11665389/   -  person juliangonzalez    schedule 27.07.2012


Ответы (3)


(изменить: название модели «Транзакция» может вызвать некоторые проблемы из-за ActiveRecord::Transactions. Есть билет на маяк.)

Ваша схема настроена неправильно. «references» — это псевдоним «belongs_to». Предмет и Транзакция не принадлежат транс_элементам, каждый из них имеет_много транс_элементов (в соответствии с вашими моделями)

create_table :items do |t|
  t.string     :name
end
create_table :tran_items do |t|
  t.belongs_to :item, :transaction, :null    => false
  t.integer    :quantity
end
create_table :transactions do |t|
  t.decimal    :profit,  :default => 0
end

(редактировать: сделай «принадлежит_в единственном числе»)

Вы удалили базу данных и повторно запустили миграцию, чтобы построить новую схему?

rake db:drop && rake db:create && rake db:migrate

Вот что я получаю в консоли:

>> i = Item.create(:name => 'My Item')    
=> #<Item id: 2, name: "My Item">
>> t = Transaction.create(:profit => 100)
=> #<Transaction id: 2, profit: #<BigDecimal:2411d2c,'0.1E3',4(8)>>
>> t.tran_items.create(:item => i)
=> #<TranItem id: nil, item_id: 2, transaction_id: 2, quantity: nil>
person Mike Breen    schedule 13.11.2008
comment
Спасибо! Теперь я могу вставлять элементы и транзакции по отдельности (без какой-либо связи между ними), что, очевидно, неправильно, но хорошее начало. Однако мне еще предстоит найти, как заставить что-то подобное работать: item.transactions ‹‹ Transaction.create(...) - person Daniel Jomphe; 13.11.2008
comment
После этого я выполнял обратную миграцию и переходил на последнюю версию; Я попробовал удалить-создать-мигрировать, а затем запустил именно то, что вы запускаете, и все равно получаю ту же самую ошибку о том, что item= не определено. Невероятно... Думаю, я попробую переименовать Transaction, как вы сказали. - person Daniel Jomphe; 13.11.2008
comment
Хорошо, я заметил, что в своих последних тестах я добавил во множественное число некоторые хэши, которых не должно быть, в надежде, что это решит проблемы множественного числа; удаление базы данных и исправление оставшихся проблем с множественным числом решили все. (И я тоже переименовал Transaction.) Я думаю, что в будущем я отключу множественное число! - person Daniel Jomphe; 14.11.2008
comment
Еще раз спасибо за помощь, Майк. Я также обнаружил, что могу сделать i.transactions ‹‹ Transaction.create(...), что кажется мне очень элегантным. - person Daniel Jomphe; 14.11.2008
comment
Спасибо, бро помогло. - person Astik Anand; 26.02.2018

Если я правильно понял.

item = Item.new(:name => "item")
item.transactions.build(:name => "transaction")
item.save!
person tamersalama    schedule 12.11.2008
comment
Я заменил ваш второй :name => "transaction" на :profit => 10 и получил это при сохранении: transactions.tran_items_id may not be NULL - person Daniel Jomphe; 13.11.2008

Эта схема должна дать вам результаты, которые вы ищете:

   create_table :items do |t|
      t.string     :name
    end
    create_table :purchase_items do |t|
      t.belongs_to :item, :purchase, :null    => false
      t.integer    :quantity
    end
    create_table :purchases do |t|
      t.decimal    :profit,                :default => 0
    end

Вот модели:

class Purchase < ActiveRecord::Base
    has_many                            :purchase_items
    has_many :items, :through =>        :purchase_items
end   

class Item < ActiveRecord::Base
    has_many                            :purchase_items
    has_many :purchases, :through => :purchase_items
end

class PurchaseItem < ActiveRecord::Base
    belongs_to :item
    belongs_to :purchase
end

Теперь с помощью консоли:

>> i = Item.create(:name => 'Item One')
=> #<Item id: 1, name: "Item One">
>> p = Purchase.create(:profit => 100)
=> #<Purchase id: 1, profit: #<BigDecimal:2458cf4,'0.1E3',4(8)>>
>> p.purchase_items.create(:item => i)
=> #<PurchaseItem id: 1, item_id: 1, purchase_id: 1, quantity: nil>
person Mike Breen    schedule 13.11.2008