Как я могу переназначить атрибут ActiveRecord во внешний ключ с минимумом нарушений? - PullRequest
1 голос
/ 30 декабря 2011

У меня есть модель, которую я строю в своем приложении Rails для цены продукта:

class Price < ActiveRecord::Base
  validates_presence_of :country_code, :product, :amount
  validates_uniqueness_of :product, :scope => [:country_code]
end

Соответственно, модель БД выглядит следующим образом:

create_table :prices do |t|
  t.string :country_code
  t.integer :product_id
  t.integer :amount
end

Сложность состоит в том, что на данный момент Product не является реальной моделью ActiveRecord - это Struct, обернутый вокруг одного атрибута ID (item_code) с множеством констант и вспомогательных методов. В будущем спринте есть планы по правильному рефакторингу обратно в базу данных, но сейчас большая часть кода нашего приложения использует Product, как будто он уже поступает из БД, и в идеале я бы хотел выделить как можно больше изменений за один раз. Продукт становится подходящей таблицей только для моделей, которые будут иметь прямые связи в БД.

Таким образом, вопрос состоит в том, чтобы аккуратно обработать отношение внешнего ключа в модели, когда в базовой БД нет другой действительной таблицы. Чтобы обойти это логически, я добавил следующую проверку в Price:

validates_inclusion_of :product, :in => Product.all

Где Product.all - это метод, который имитирует эти объекты, приходящие из таблицы, не являясь фактическим классом ActiveRecord.

Все это вместе приводит к проблеме, которая, насколько я понимаю, из-за того, что нет таблицы Product, ActiveRecord не создает: средства доступа к продукту (а вместо этого использует: product_id напрямую). Однако, если я полагаюсь на: product_id, я усложнил миграцию после того, как Product стал настоящим классом ActiveRecord.

Существует ли простой способ «псевдонима» атрибута: product для поля: product_id, чтобы код был изолирован внутри продукта (или даже модели Price) таким образом, чтобы для всех целей и задач: Продукт автоматически отображается, как если бы была связь в таблицах базы данных? Очевидно, что идеальным решением было бы использование некоторого метода или инструкции псевдонима, которые можно было бы просто удалить в будущем, и внезапно все стало бы так, как будто product_id всегда указывал на таблицу products.

1 Ответ

0 голосов
/ 30 декабря 2011

Если вы просто хотите подделать поля, как если бы у вас была установка отношения has_one в модели Price, вы можете просто сами определить методы в своей модели Price. Поскольку вы не привели пример того, как вы выбираете из Структуры продукта, ниже приведен пример кода, если вы пытались повторно реализовать его для ActiveModel.

def product
    if self.product_id
        if !@product or @product.id != self.product_id
            @product = Product.find(self.product_id)
        else
            @product
        end
    end
end

def product=(product)
    @product = product
    self.product_id = product._id
end

Это дублирует отношение has_one, где вы можете изменить его, задав для него значение product или product_id, и оно будет искать товар только один раз, а затем снова, если он изменится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...