From c46019d68c6f8d189c088f37fd1d6c95bcecdc88 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 18 Oct 2012 15:46:09 +1100 Subject: [PATCH] WIP: Move Supplier, Distributor, DistributorSet and ProductDistribution models out of Spree namespace --- app/controllers/application_controller.rb | 4 +-- .../spree/admin/distributors_controller.rb | 2 +- .../admin/reports_controller_decorator.rb | 4 +-- .../spree/orders_controller_decorator.rb | 2 +- app/models/distributor.rb | 31 ++++++++++++++++ app/models/distributor_set.rb | 34 ++++++++++++++++++ app/models/product_distribution.rb | 9 +++++ app/models/spree/distributor.rb | 34 ------------------ app/models/spree/distributor_set.rb | 36 ------------------- app/models/spree/product_decorator.rb | 2 +- app/models/spree/product_distribution.rb | 13 ------- app/models/spree/supplier.rb | 36 ------------------- app/models/supplier.rb | 33 +++++++++++++++++ .../admin/products/_supplier_form.html.haml | 4 +-- .../spree/products/_add_to_cart.html.haml | 2 +- ..._move_distributor_from_order_to_product.rb | 2 +- ...r_and_supplier_address_to_spree_address.rb | 16 ++++----- ...utors_products_to_product_distributions.rb | 2 +- db/seeds.rb | 14 ++++---- lib/spree/product_filters.rb | 6 ++-- spec/factories.rb | 12 +++---- spec/lib/spree/product_filters_spec.rb | 2 +- spec/models/product_distribution_spec.rb | 2 +- spec/requests/admin/distributors_spec.rb | 2 +- spec/support/spree/init.rb | 2 +- 25 files changed, 147 insertions(+), 159 deletions(-) create mode 100644 app/models/distributor.rb create mode 100644 app/models/distributor_set.rb create mode 100644 app/models/product_distribution.rb delete mode 100644 app/models/spree/distributor.rb delete mode 100644 app/models/spree/distributor_set.rb delete mode 100644 app/models/spree/product_distribution.rb delete mode 100644 app/models/spree/supplier.rb create mode 100644 app/models/supplier.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c2785bfb5a..73238eaef2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -11,8 +11,8 @@ class ApplicationController < ActionController::Base def load_data_for_sidebar - @suppliers = Spree::Supplier.all - @distributors = Spree::Distributor.with_active_products_on_hand.by_name + @suppliers = Supplier.all + @distributors = Distributor.with_active_products_on_hand.by_name end end diff --git a/app/controllers/spree/admin/distributors_controller.rb b/app/controllers/spree/admin/distributors_controller.rb index cfbc3dd22f..5a99ae99f8 100644 --- a/app/controllers/spree/admin/distributors_controller.rb +++ b/app/controllers/spree/admin/distributors_controller.rb @@ -15,7 +15,7 @@ module Spree private def load_distributor_set - @distributor_set = Spree::DistributorSet.new :distributors => collection + @distributor_set = DistributorSet.new :distributors => collection end def load_countries diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index 10c09b7bdb..b4d6585ec2 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -53,7 +53,7 @@ Spree::Admin::ReportsController.class_eval do @search = Spree::Order.complete.search(params[:q]) orders = @search.result - @distributors = Spree::Distributor.all + @distributors = Distributor.all @report = OpenFoodWeb::GroupBuyReport.new orders unless params[:csv] @@ -67,4 +67,4 @@ Spree::Admin::ReportsController.class_eval do end end -end \ No newline at end of file +end diff --git a/app/controllers/spree/orders_controller_decorator.rb b/app/controllers/spree/orders_controller_decorator.rb index 96f717e99f..6b9a708d1c 100644 --- a/app/controllers/spree/orders_controller_decorator.rb +++ b/app/controllers/spree/orders_controller_decorator.rb @@ -3,7 +3,7 @@ Spree::OrdersController.class_eval do after_filter :populate_variant_attributes, :only => :populate def populate_order_distributor - @distributor = params[:distributor_id].present? ? Spree::Distributor.find(params[:distributor_id]) : nil + @distributor = params[:distributor_id].present? ? Distributor.find(params[:distributor_id]) : nil if populate_valid? @distributor order = current_order(true) diff --git a/app/models/distributor.rb b/app/models/distributor.rb new file mode 100644 index 0000000000..1bc2d274c5 --- /dev/null +++ b/app/models/distributor.rb @@ -0,0 +1,31 @@ +class Distributor < ActiveRecord::Base + belongs_to :pickup_address, :foreign_key => 'pickup_address_id', :class_name => 'Spree::Address' + has_many :orders, :class_name => 'Spree::Order' + + has_many :product_distributions, :dependent => :destroy + has_many :products, :through => :product_distributions + + accepts_nested_attributes_for :pickup_address + + validates_presence_of :name, :pickup_address + validates_associated :pickup_address + + scope :by_name, order('name') + scope :with_active_products_on_hand, lambda { joins(:products).where('spree_products.deleted_at IS NULL AND spree_products.available_on <= ? AND spree_products.count_on_hand > 0', Time.now).select('distinct(distributors.*)') } + + after_initialize :initialize_country + before_validation :set_unused_address_fields + + def initialize_country + self.pickup_address ||= Spree::Address.new + self.pickup_address.country = Spree::Country.find_by_id(Spree::Config[:default_country_id]) if self.pickup_address.new_record? + end + + def set_unused_address_fields + pickup_address.firstname = pickup_address.lastname = pickup_address.phone = 'unused' if pickup_address.present? + end + + def to_param + "#{id}-#{name.parameterize}" + end +end diff --git a/app/models/distributor_set.rb b/app/models/distributor_set.rb new file mode 100644 index 0000000000..04fbd02db4 --- /dev/null +++ b/app/models/distributor_set.rb @@ -0,0 +1,34 @@ +# Tableless model to handle updating multiple distributors at once from a +# single form. Used to update next_collection_at field for all distributors in +# admin backend. +class DistributorSet + include ActiveModel::Conversion + extend ActiveModel::Naming + + attr_accessor :distributors + + def initialize(attributes={}) + @distributors = Distributor.all + + attributes.each do |name, value| + send("#{name}=", value) + end + end + + def distributors_attributes=(attributes) + attributes.each do |k, attributes| + # attributes == {:id => 123, :next_collection_at => '...'} + d = @distributors.detect { |d| d.id.to_s == attributes[:id].to_s } + d.assign_attributes(attributes.except(:id)) + end + end + + def save + distributors.all?(&:save) + end + + def persisted? + false + end + +end diff --git a/app/models/product_distribution.rb b/app/models/product_distribution.rb new file mode 100644 index 0000000000..19305c2685 --- /dev/null +++ b/app/models/product_distribution.rb @@ -0,0 +1,9 @@ +class ProductDistribution < ActiveRecord::Base + belongs_to :product, :class_name => 'Spree::Product' + belongs_to :distributor + belongs_to :shipping_method, :class_name => 'Spree::ShippingMethod' + + validates_presence_of :product_id, :on => :update + validates_presence_of :distributor_id, :shipping_method_id + validates_uniqueness_of :product_id, :scope => :distributor_id +end diff --git a/app/models/spree/distributor.rb b/app/models/spree/distributor.rb deleted file mode 100644 index ad6c5a0da8..0000000000 --- a/app/models/spree/distributor.rb +++ /dev/null @@ -1,34 +0,0 @@ -module Spree - class Distributor < ActiveRecord::Base - self.table_name = 'distributors' - belongs_to :pickup_address, :foreign_key => 'pickup_address_id', :class_name => 'Spree::Address' - has_many :orders - - has_many :product_distributions, :dependent => :destroy - has_many :products, :through => :product_distributions - - accepts_nested_attributes_for :pickup_address - - validates_presence_of :name, :pickup_address - validates_associated :pickup_address - - scope :by_name, order('name') - scope :with_active_products_on_hand, lambda { joins(:products).where('spree_products.deleted_at IS NULL AND spree_products.available_on <= ? AND spree_products.count_on_hand > 0', Time.now).select('distinct(distributors.*)') } - - after_initialize :initialize_country - before_validation :set_unused_address_fields - - def initialize_country - self.pickup_address ||= Address.new - self.pickup_address.country = Country.find_by_id(Spree::Config[:default_country_id]) if self.pickup_address.new_record? - end - - def set_unused_address_fields - pickup_address.firstname = pickup_address.lastname = pickup_address.phone = 'unused' if pickup_address.present? - end - - def to_param - "#{id}-#{name.parameterize}" - end - end -end diff --git a/app/models/spree/distributor_set.rb b/app/models/spree/distributor_set.rb deleted file mode 100644 index 4ef6ae5b27..0000000000 --- a/app/models/spree/distributor_set.rb +++ /dev/null @@ -1,36 +0,0 @@ -# Tableless model to handle updating multiple distributors at once from a -# single form. Used to update next_collection_at field for all distributors in -# admin backend. -module Spree - class DistributorSet - include ActiveModel::Conversion - extend ActiveModel::Naming - - attr_accessor :distributors - - def initialize(attributes={}) - @distributors = Spree::Distributor.all - - attributes.each do |name, value| - send("#{name}=", value) - end - end - - def distributors_attributes=(attributes) - attributes.each do |k, attributes| - # attributes == {:id => 123, :next_collection_at => '...'} - d = @distributors.detect { |d| d.id.to_s == attributes[:id].to_s } - d.assign_attributes(attributes.except(:id)) - end - end - - def save - distributors.all?(&:save) - end - - def persisted? - false - end - - end -end diff --git a/app/models/spree/product_decorator.rb b/app/models/spree/product_decorator.rb index e97b5f4662..91ed6e57ee 100644 --- a/app/models/spree/product_decorator.rb +++ b/app/models/spree/product_decorator.rb @@ -23,7 +23,7 @@ Spree::Product.class_eval do # Build a product distribution for each distributor def build_product_distributions - Spree::Distributor.all.each do |distributor| + Distributor.all.each do |distributor| unless self.product_distributions.find_by_distributor_id distributor.id self.product_distributions.build(:distributor => distributor) end diff --git a/app/models/spree/product_distribution.rb b/app/models/spree/product_distribution.rb deleted file mode 100644 index c64f8543c4..0000000000 --- a/app/models/spree/product_distribution.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Spree - class ProductDistribution < ActiveRecord::Base - self.table_name = 'product_distributions' - - belongs_to :product - belongs_to :distributor - belongs_to :shipping_method - - validates_presence_of :product_id, :on => :update - validates_presence_of :distributor_id, :shipping_method_id - validates_uniqueness_of :product_id, :scope => :distributor_id - end -end diff --git a/app/models/spree/supplier.rb b/app/models/spree/supplier.rb deleted file mode 100644 index 93cb9aa675..0000000000 --- a/app/models/spree/supplier.rb +++ /dev/null @@ -1,36 +0,0 @@ -module Spree - class Supplier < ActiveRecord::Base - self.table_name = 'suppliers' - has_many :products - belongs_to :address - - accepts_nested_attributes_for :address - - validates_presence_of :name, :address - validates_associated :address - - after_initialize :initialize_country - before_validation :set_unused_address_fields - - def has_products_on_hand? - self.products.where('count_on_hand > 0').present? - end - - def to_param - "#{id}-#{name.parameterize}" - end - - - private - - def initialize_country - self.address ||= Address.new - self.address.country = Country.find_by_id(Spree::Config[:default_country_id]) if self.address.new_record? - end - - def set_unused_address_fields - address.firstname = address.lastname = address.phone = 'unused' if address.present? - end - - end -end diff --git a/app/models/supplier.rb b/app/models/supplier.rb new file mode 100644 index 0000000000..76518a5f34 --- /dev/null +++ b/app/models/supplier.rb @@ -0,0 +1,33 @@ +class Supplier < ActiveRecord::Base + has_many :products, :class_name => 'Spree::Product' + belongs_to :address, :class_name => 'Spree::Address' + + accepts_nested_attributes_for :address + + validates_presence_of :name, :address + validates_associated :address + + after_initialize :initialize_country + before_validation :set_unused_address_fields + + def has_products_on_hand? + self.products.where('count_on_hand > 0').present? + end + + def to_param + "#{id}-#{name.parameterize}" + end + + + private + + def initialize_country + self.address ||= Spree::Address.new + self.address.country = Spree::Country.find_by_id(Spree::Config[:default_country_id]) if self.address.new_record? + end + + def set_unused_address_fields + address.firstname = address.lastname = address.phone = 'unused' if address.present? + end + +end diff --git a/app/views/spree/admin/products/_supplier_form.html.haml b/app/views/spree/admin/products/_supplier_form.html.haml index 0c0ae1df52..e4cd8280a7 100644 --- a/app/views/spree/admin/products/_supplier_form.html.haml +++ b/app/views/spree/admin/products/_supplier_form.html.haml @@ -1,5 +1,5 @@ = f.field_container :supplier do = f.label :supplier %br - = f.collection_select(:supplier_id, Spree::Supplier.all, :id, :name, :include_blank => true) - = f.error_message_on :supplier \ No newline at end of file + = f.collection_select(:supplier_id, Supplier.all, :id, :name, :include_blank => true) + = f.error_message_on :supplier diff --git a/app/views/spree/products/_add_to_cart.html.haml b/app/views/spree/products/_add_to_cart.html.haml index 174e9e15d9..34796f83a3 100644 --- a/app/views/spree/products/_add_to_cart.html.haml +++ b/app/views/spree/products/_add_to_cart.html.haml @@ -17,7 +17,7 @@ - order = current_order(false) - if order.nil? || order.can_change_distributor? %p Distributor - = select_tag "distributor_id", options_from_collection_for_select([Spree::Distributor.new]+@product.distributors, "id", "name", current_distributor.andand.id) + = select_tag "distributor_id", options_from_collection_for_select([Distributor.new]+@product.distributors, "id", "name", current_distributor.andand.id) - else = hidden_field_tag "distributor_id", order.distributor.id .distributor-fixed= "Your distributor for this order is #{order.distributor.name}" diff --git a/db/migrate/20120618061537_move_distributor_from_order_to_product.rb b/db/migrate/20120618061537_move_distributor_from_order_to_product.rb index 5b5c102331..ede96641f1 100644 --- a/db/migrate/20120618061537_move_distributor_from_order_to_product.rb +++ b/db/migrate/20120618061537_move_distributor_from_order_to_product.rb @@ -8,7 +8,7 @@ class MoveDistributorFromOrderToProduct < ActiveRecord::Migration end # Associate all products with the first distributor - distributor = Spree::Distributor.first + distributor = Distributor.first if distributor Spree::Product.all.each do |product| product.distributors << distributor diff --git a/db/migrate/20120626013846_extract_distributor_and_supplier_address_to_spree_address.rb b/db/migrate/20120626013846_extract_distributor_and_supplier_address_to_spree_address.rb index 5d7672a634..fdba0a03ef 100644 --- a/db/migrate/20120626013846_extract_distributor_and_supplier_address_to_spree_address.rb +++ b/db/migrate/20120626013846_extract_distributor_and_supplier_address_to_spree_address.rb @@ -2,9 +2,9 @@ class ExtractDistributorAndSupplierAddressToSpreeAddress < ActiveRecord::Migrati def up # -- Distributors add_column :distributors, :pickup_address_id, :integer - Spree::Distributor.reset_column_information + Distributor.reset_column_information - Spree::Distributor.all.each do |distributor| + Distributor.all.each do |distributor| pickup_address = Spree::Address.create!(:firstname => 'unused', :lastname => 'unused', :phone => 'unused', @@ -24,9 +24,9 @@ class ExtractDistributorAndSupplierAddressToSpreeAddress < ActiveRecord::Migrati # -- Suppliers add_column :suppliers, :address_id, :integer - Spree::Supplier.reset_column_information + Supplier.reset_column_information - Spree::Supplier.all.each do |supplier| + Supplier.all.each do |supplier| address = Spree::Address.create!(:firstname => 'unused', :lastname => 'unused', :phone => 'unused', @@ -51,9 +51,9 @@ class ExtractDistributorAndSupplierAddressToSpreeAddress < ActiveRecord::Migrati add_column :distributors, :post_code, :string add_column :distributors, :state_id, :integer add_column :distributors, :country_id, :integer - Spree::Distributor.reset_column_information + Distributor.reset_column_information - Spree::Distributor.all.each do |distributor| + Distributor.all.each do |distributor| distributor[:pickup_address] = distributor.pickup_address.address1 distributor.city = distributor.pickup_address.city distributor.post_code = distributor.pickup_address.zipcode @@ -71,9 +71,9 @@ class ExtractDistributorAndSupplierAddressToSpreeAddress < ActiveRecord::Migrati add_column :suppliers, :postcode, :string add_column :suppliers, :state_id, :integer add_column :suppliers, :country_id, :integer - Spree::Supplier.reset_column_information + Supplier.reset_column_information - Spree::Supplier.all.each do |supplier| + Supplier.all.each do |supplier| supplier[:address] = supplier.address.address1 supplier.city = supplier.address.city supplier.post_code = supplier.address.zipcode diff --git a/db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb b/db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb index 83f4eb26fe..cca0850150 100644 --- a/db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb +++ b/db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb @@ -10,7 +10,7 @@ class RenameDistributorsProductsToProductDistributions < ActiveRecord::Migration # Set default shipping method on all product distributions sm = Spree::ShippingMethod.first - Spree::ProductDistribution.update_all(:shipping_method_id => sm.id) if sm + ProductDistribution.update_all(:shipping_method_id => sm.id) if sm end def down diff --git a/db/seeds.rb b/db/seeds.rb index 50b0194e0b..e786ca7a1a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -60,7 +60,7 @@ end # -- Suppliers and distributors -unless Spree::Supplier.count > 0 +unless Supplier.count > 0 puts "[db:seed] Seeding suppliers and distributors" 3.times { FactoryGirl.create(:supplier) } @@ -74,19 +74,19 @@ unless Spree::Product.count > 0 FactoryGirl.create(:product, :name => 'Garlic', :price => 20.00, - :supplier => Spree::Supplier.all[0], - :distributors => [Spree::Distributor.all[0]], + :supplier => Supplier.all[0], + :distributors => [Distributor.all[0]], :taxons => [Spree::Taxon.find_by_name('Vegetables')]) FactoryGirl.create(:product, :name => 'Fuji Apple', :price => 5.00, - :supplier => Spree::Supplier.all[1], - :distributors => Spree::Distributor.all, + :supplier => Supplier.all[1], + :distributors => Distributor.all, :taxons => [Spree::Taxon.find_by_name('Fruit')]) FactoryGirl.create(:product, :name => 'Beef - 5kg Trays', :price => 50.00, - :supplier => Spree::Supplier.all[2], - :distributors => [Spree::Distributor.all[2]], + :supplier => Supplier.all[2], + :distributors => [Distributor.all[2]], :taxons => [Spree::Taxon.find_by_name('Meat and Fish')]) end diff --git a/lib/spree/product_filters.rb b/lib/spree/product_filters.rb index be1e501b8b..b7e3b0d6db 100644 --- a/lib/spree/product_filters.rb +++ b/lib/spree/product_filters.rb @@ -1,6 +1,6 @@ module Spree module ProductFilters - if Spree::Distributor.table_exists? + if Distributor.table_exists? Spree::Product.scope :distributor_any, lambda {|*opts| conds = opts.map {|o| ProductFilters.distributor_filter[:conds][o]}.reject {|c| c.nil?} @@ -8,8 +8,8 @@ module Spree } def ProductFilters.distributor_filter - distributors = Spree::Distributor.all.map(&:name).compact.uniq - conds = Hash[*distributors.map { |d| [d, "#{Spree::Distributor.table_name}.name = '#{d}'"] }.flatten] + distributors = Distributor.all.map(&:name).compact.uniq + conds = Hash[*distributors.map { |d| [d, "#{Distributor.table_name}.name = '#{d}'"] }.flatten] { :name => "Group", :scope => :distributor_any, :conds => conds, diff --git a/spec/factories.rb b/spec/factories.rb index f1939eb65f..bd2a08d09f 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -2,7 +2,7 @@ require 'faker' require 'spree/core/testing_support/factories' FactoryGirl.define do - factory :supplier, :class => Spree::Supplier do + factory :supplier, :class => Supplier do sequence(:name) { |n| "Supplier #{n}" } description 'supplier' long_description '

Hello, world!

This is a paragraph.

' @@ -10,7 +10,7 @@ FactoryGirl.define do address { Spree::Address.first || FactoryGirl.create(:address) } end - factory :distributor, :class => Spree::Distributor do + factory :distributor, :class => Distributor do sequence(:name) { |n| "Distributor #{n}" } contact 'Mr Turing' phone '1000100100' @@ -23,9 +23,9 @@ FactoryGirl.define do 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) } + factory :product_distribution, :class => ProductDistribution do + product { |pd| Spree::Product.first || FactoryGirl.create(:product) } + distributor { |pd| Distributor.first || FactoryGirl.create(:distributor) } shipping_method { |pd| Spree::ShippingMethod.where("name != 'Delivery'").first || FactoryGirl.create(:shipping_method) } end @@ -46,7 +46,7 @@ FactoryGirl.modify do # When this fix has been merged into a version of Spree that we're using, this line can be removed. sequence(:name) { |n| "Product ##{n} - #{Kernel.rand(9999)}" } - supplier { Spree::Supplier.first || FactoryGirl.create(:supplier) } + supplier { Supplier.first || FactoryGirl.create(:supplier) } on_hand 3 # before(:create) do |product, evaluator| diff --git a/spec/lib/spree/product_filters_spec.rb b/spec/lib/spree/product_filters_spec.rb index 29c7d2c688..eb879cfe11 100644 --- a/spec/lib/spree/product_filters_spec.rb +++ b/spec/lib/spree/product_filters_spec.rb @@ -4,7 +4,7 @@ describe Spree::ProductFilters do context "distributor filter" do it "provides filtering for all distributors" do 3.times { create(:distributor) } - Spree::ProductFilters.distributor_filter[:labels].should == Spree::Distributor.all.map { |d| [d.name, d.name] } + Spree::ProductFilters.distributor_filter[:labels].should == Distributor.all.map { |d| [d.name, d.name] } end end end diff --git a/spec/models/product_distribution_spec.rb b/spec/models/product_distribution_spec.rb index 7827b32a8a..bcfd131dea 100644 --- a/spec/models/product_distribution_spec.rb +++ b/spec/models/product_distribution_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Spree::ProductDistribution do +describe ProductDistribution do it "is unique for scope [product, distributor]" do pd1 = create(:product_distribution) pd1.should be_valid diff --git a/spec/requests/admin/distributors_spec.rb b/spec/requests/admin/distributors_spec.rb index a4f2a3c8e6..d409eba3ff 100644 --- a/spec/requests/admin/distributors_spec.rb +++ b/spec/requests/admin/distributors_spec.rb @@ -74,7 +74,7 @@ feature %q{ # Then my times should have been saved flash_message.should == 'Distributor collection times updated.' - Spree::Distributor.all.map { |d| d.next_collection_at }.should == %w(One Two Three) + Distributor.all.map { |d| d.next_collection_at }.should == %w(One Two Three) end end diff --git a/spec/support/spree/init.rb b/spec/support/spree/init.rb index 2f45cbc987..0614e5085b 100644 --- a/spec/support/spree/init.rb +++ b/spec/support/spree/init.rb @@ -1,7 +1,7 @@ # Initialise shipping method when created without one, like this: # create(:product, :distributors => [...]) # In this case, we don't care what the shipping method is, but we need one for validations to pass. -Spree::ProductDistribution.class_eval do +ProductDistribution.class_eval do before_validation :init_shipping_method def init_shipping_method