dynamic table names for Active Record models

后端 未结 7 1434
感情败类
感情败类 2021-01-27 13:25

I have an interesting Active Record problem and I\'m not quite sure what the cleanest solution is. The legacy database that I am integrating with has a strange wrinkle in its sc

7条回答
  •  甜味超标
    2021-01-27 13:46

    Here's a way you can do it. The basics (before the 70 lines of code) are:

    • create a has_many for each car type
    • define a method "wheels" that uses the table name in the association to get the right wheels

    Let me know if you have any questions

    #!/usr/bin/env ruby
    %w|rubygems active_record irb|.each {|lib| require lib}
    ActiveSupport::Inflector.inflections.singular("toyota", "toyota")
    CAR_TYPES = %w|ford buick toyota|
    
    ActiveRecord::Base.logger = Logger.new(STDOUT)
    ActiveRecord::Base.establish_connection(
      :adapter => "sqlite3",
      :database => ":memory:"
    )
    
    ActiveRecord::Schema.define do
      create_table :cars do |t|
        t.string :name
      end
    
      create_table :car_to_wheel_table_map, :id => false do |t|
        t.integer :car_id
        t.string :wheel_table
      end
    
      CAR_TYPES.each do |car_type|
        create_table "wheels_for_#{car_type.pluralize}" do |t|
          t.integer :car_id
          t.string :color
        end
      end
    end
    
    CAR_TYPES.each do |car_type|
      eval <<-END
        class #{car_type.classify}Wheel < ActiveRecord::Base
          set_table_name "wheels_for_#{car_type.pluralize}"
          belongs_to :car
        end
      END
    end
    
    class Car < ActiveRecord::Base
      has_one :car_wheel_map
    
      CAR_TYPES.each do |car_type|
        has_many "#{car_type}_wheels"
      end
    
      delegate :wheel_table, :to => :car_wheel_map
    
      def wheels
        send("#{wheel_table}_wheels")
      end
    end
    
    class CarWheelMap < ActiveRecord::Base
      set_table_name "car_to_wheel_table_map"
      belongs_to :car
    end
    
    
    rav4 = Car.create(:name => "Rav4")
    rav4.create_car_wheel_map(:wheel_table => "toyota")
    rav4.wheels.create(:color => "red")
    
    fiesta = Car.create(:name => "Fiesta")
    fiesta.create_car_wheel_map(:wheel_table => "ford")
    fiesta.wheels.create(:color => "green")
    
    IRB.start if __FILE__ == $0
    

提交回复
热议问题