dynamic table names for Active Record models

后端 未结 7 1358
感情败类
感情败类 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:59

    How about this instead? (here's the gist: http://gist.github.com/111041)

    #!/usr/bin/env ruby
    %w|rubygems active_record irb|.each {|lib| require lib}
    ActiveSupport::Inflector.inflections.singular("toyota", "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
    
      create_table :wheels_for_fords do |t|
        t.integer :car_id
        t.string :color
      end
    
      create_table :wheels_for_toyotas do |t|
        t.integer :car_id
        t.string :color
      end
    end
    
    class Wheel < ActiveRecord::Base
      set_table_name nil
      belongs_to :car
    end
    
    class CarWheelMap < ActiveRecord::Base
      set_table_name "car_to_wheel_table_map"
      belongs_to :car
    end
    
    class Car < ActiveRecord::Base
      has_one :car_wheel_map
      delegate :wheel_table, :to => :car_wheel_map
    
      def wheels
        @wheels ||= begin
          the_klass = "#{wheel_table.classify}Wheel"
          eval <<-END
            class #{the_klass} < ActiveRecord::Base
              set_table_name "wheels_for_#{wheel_table.pluralize}"
              belongs_to :car
            end
          END
    
          self.class.send(:has_many, "#{wheel_table}_wheels")
          send "#{wheel_table}_wheels"
        end
      end
    end
    
    rav4 = Car.create(:name => "Rav4")
    rav4.create_car_wheel_map(:wheel_table => "toyota")
    
    fiesta = Car.create(:name => "Fiesta")
    fiesta.create_car_wheel_map(:wheel_table => "ford")
    
    rav4.wheels.create(:color => "red")
    fiesta.wheels.create(:color => "green")
    
    # IRB.start if __FILE__ == $0
    

提交回复
热议问题