From 3f08c2a9b0efb91aa768664cb66af3b077d4e690 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 27 Jun 2012 11:55:10 +1000 Subject: [PATCH] Convert distributors_products join table into ProductDistribution explicit join model --- app/models/spree/distributor.rb | 4 +++- app/models/spree/product_decorator.rb | 8 ++++--- app/models/spree/product_distribution.rb | 9 +++++++ ...utors_products_to_product_distributions.rb | 24 +++++++++++++++++++ db/schema.rb | 11 +++++---- spec/factories.rb | 11 ++++++++- spec/models/distributors_spec.rb | 2 +- spec/models/product_spec.rb | 12 +++------- 8 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 app/models/spree/product_distribution.rb create mode 100644 db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb diff --git a/app/models/spree/distributor.rb b/app/models/spree/distributor.rb index 70e5b12923..3a40d6a607 100644 --- a/app/models/spree/distributor.rb +++ b/app/models/spree/distributor.rb @@ -2,9 +2,11 @@ module Spree class Distributor < ActiveRecord::Base self.table_name = 'distributors' belongs_to :pickup_address, :foreign_key => 'pickup_address_id', :class_name => 'Spree::Address' - has_and_belongs_to_many :products has_many :orders + has_many :product_distributions + has_many :products, :through => :product_distributions + accepts_nested_attributes_for :pickup_address validates_presence_of :name, :pickup_address diff --git a/app/models/spree/product_decorator.rb b/app/models/spree/product_decorator.rb index a47b92baa8..f60c36ad3e 100644 --- a/app/models/spree/product_decorator.rb +++ b/app/models/spree/product_decorator.rb @@ -1,11 +1,13 @@ Spree::Product.class_eval do belongs_to :supplier - has_and_belongs_to_many :distributors + + has_many :product_distributions + has_many :distributors, :through => :product_distributions attr_accessible :supplier_id, :distributor_ids - validates_presence_of :supplier, :distributors + validates_presence_of :supplier scope :in_supplier, lambda { |supplier| where(:supplier_id => supplier) } - scope :in_distributor, lambda { |distributor| joins(:distributors).where('distributors.id = ?', (distributor.respond_to?(:id) ? distributor.id : distributor.to_i)) } + scope :in_distributor, lambda { |distributor| joins(:product_distributions).where('product_distributions.distributor_id = ?', (distributor.respond_to?(:id) ? distributor.id : distributor.to_i)) } end diff --git a/app/models/spree/product_distribution.rb b/app/models/spree/product_distribution.rb new file mode 100644 index 0000000000..2a73d464ca --- /dev/null +++ b/app/models/spree/product_distribution.rb @@ -0,0 +1,9 @@ +module Spree + class ProductDistribution < ActiveRecord::Base + self.table_name = 'product_distributions' + + belongs_to :product + belongs_to :distributor + belongs_to :shipping_method + end +end diff --git a/db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb b/db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb new file mode 100644 index 0000000000..83f4eb26fe --- /dev/null +++ b/db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb @@ -0,0 +1,24 @@ +class RenameDistributorsProductsToProductDistributions < ActiveRecord::Migration + def up + # Convert m2m join table into explicit join model, and add a shipping method relation and timestamps + rename_table :distributors_products, :product_distributions + add_column :product_distributions, :id, :primary_key + change_table :product_distributions do |t| + t.references :shipping_method + t.timestamps + end + + # Set default shipping method on all product distributions + sm = Spree::ShippingMethod.first + Spree::ProductDistribution.update_all(:shipping_method_id => sm.id) if sm + end + + def down + change_table :product_distributions do |t| + t.remove :id + t.remove :shipping_method_id + t.remove :created_at, :updated_at + end + rename_table :product_distributions, :distributors_products + end +end diff --git a/db/schema.rb b/db/schema.rb index fb2bab56b4..c5fcc6a90e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120626013846) do +ActiveRecord::Schema.define(:version => 20120626233350) do create_table "distributors", :force => true do |t| t.string "name" @@ -28,9 +28,12 @@ ActiveRecord::Schema.define(:version => 20120626013846) do t.integer "pickup_address_id" end - create_table "distributors_products", :id => false, :force => true do |t| - t.integer "product_id" - t.integer "distributor_id" + create_table "product_distributions", :force => true do |t| + t.integer "product_id" + t.integer "distributor_id" + t.integer "shipping_method_id" + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_activators", :force => true do |t| diff --git a/spec/factories.rb b/spec/factories.rb index df9b9bdf72..804c5d5678 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -19,12 +19,21 @@ FactoryGirl.define do pickup_times "Whenever you're free" pickup_address { Spree::Address.first || FactoryGirl.create(:address) } end + + factory :product_distribution, :class => Spree::ProductDistribution do + product { |pd| Spree::Product.first || FactoryGirl.create(:product) } + distributor { |pd| Spree::Distributor.first || FactoryGirl.create(:distributor) } + shipping_method { |pd| Spree::ShippingMethod.first || FactoryGirl.create(:shipping_method) } + end end FactoryGirl.modify do factory :simple_product do supplier { Spree::Supplier.first || FactoryGirl.create(:supplier) } - distributors { [Spree::Distributor.first || FactoryGirl.create(:distributor)] } + + # before(:create) do |product, evaluator| + # product.product_distributions = [FactoryGirl.create(:product_distribution, :product => product)] + # end end end diff --git a/spec/models/distributors_spec.rb b/spec/models/distributors_spec.rb index 6541d2552b..f9db087d70 100644 --- a/spec/models/distributors_spec.rb +++ b/spec/models/distributors_spec.rb @@ -5,7 +5,7 @@ module Spree describe "associations" do it { should belong_to(:pickup_address) } - it { should have_and_belong_to_many(:products) } + it { should have_many(:product_distributions) } it { should have_many(:orders) } end diff --git a/spec/models/product_spec.rb b/spec/models/product_spec.rb index f8ecce0071..e0cfd05a8e 100644 --- a/spec/models/product_spec.rb +++ b/spec/models/product_spec.rb @@ -4,25 +4,19 @@ describe Spree::Product do describe "associations" do it { should belong_to(:supplier) } - it { should have_and_belong_to_many(:distributors) } + it { should have_many(:product_distributions) } end describe "validations" do it "is valid when created from factory" do - build(:product).should be_valid + create(:product).should be_valid end it "requires a supplier" do - product = build(:product) + product = create(:product) product.supplier = nil product.should_not be_valid end - - it "requires at least one distributor" do - product = build(:product) - product.distributors.clear - product.should_not be_valid - end end end