Хорошо, я на самом деле создал для вас демонстрационный проект Rails 3.1 и разместил его на GitHub . Я включил вывод консоли в файл README
, чтобы доказать, что такие вызовы, как item.seller.name
и item.manufacturer.name
, работают, а также вызовы туда и обратно, такие как vendor.sold_items.first.manufacturer.name
, которые позволяют вам узнать имя производителя например, первый проданный товар для конкретного поставщика.
Я думаю, корень всего, как вы заметили, в том, что vendor
и manufacturer
для всех намерений и целей идентичны. По этой причине я просто объединил их в класс Vendor
и настроил отношения с внешним ключом таким образом, чтобы они работали так, как я думаю, вы хотите.
В частности, вам следует обратить внимание на файл README , в котором есть вывод сеанса консоли, который я запустил, чтобы показать, как он работает. Вы также захотите взглянуть на два класса моделей и на то, как определяются их ассоциации, а также на файл spec/factories.rb
о том, как он устанавливает ложные данные базы данных (я включил их ниже).
Перечитывая ваш вопрос сегодня утром, я не уверен, что вы делали неправильно, но вы, вероятно, можете объяснить это тонкой ошибкой в ваших ассоциациях где-то. Это, вероятно, тот случай, когда вы действительно близко, но не совсем там. : D
Вот некоторые фрагменты кода:
приложение / модели / item.rb
class Item < ActiveRecord::Base
belongs_to :seller, :class_name => "Vendor"
belongs_to :manufacturer, :class_name => "Vendor"
end
приложение / модели / vendor.rb
class Vendor < ActiveRecord::Base
has_many :sold_items, :class_name => "Item", :foreign_key => :seller_id
has_many :manufactured_items, :class_name => "Item", :foreign_key => :manufacturer_id
end
спецификация / factories.rb
require 'populator'
require 'faker'
FactoryGirl.define do
factory :vendor do |v|
v.name {Populator.words(1..3)}
v.website {Faker::Internet.domain_name}
v.abbr {(["ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VWX", "YZ1"])[rand(9)]}
end
factory :item do |i|
i.association :seller, :factory => :vendor
i.association :manufacturer, :factory => :vendor
i.name {Populator.words(3..5)}
end
end
Библиотека / задачи / populator.rake
namespace :db do
desc "Erase database"
task :erase => :environment do
puts "Erasing..."
[Vendor, Item].each(&:delete_all)
end
desc "Erase and fill database"
task :populate => [:environment, :erase] do
require 'populator'
require 'faker'
puts "Populating: enjoy this random pattern generator while you wait..."
50.times{Factory.create(:vendor)}
Vendor.all.each do |v|
# This line actually has a bug in it that makes all `seller_id` and `manufacturer_id`
# columns always contain a value in the range 0..50. That means
# `rake db:populate` will only actually work the first time, but
# I think you get the idea of how this should work.
10.times{Factory.create(:item, :seller_id => (rand(50) + 1), :manufacturer_id => (rand(50) + 1))}
print (['\\', '/', '_', '|'])[rand(4)]
end
puts ""
end
end