Рельсы, изменяющие полиморфный тип объекта - PullRequest
2 голосов
/ 07 декабря 2009

У нас есть родительская модель Vehicle, которая наследуется для изготовления классов Car, Truck, SUV. В нашей форме мы разрешаем пользователю редактировать данные для группы транспортных средств, и одним из атрибутов для каждого транспортного средства является меню выбора для «типа». HTML-атрибут с именем vehicle_type и обновляет фактический атрибут Polymorphic type в модели транспортного средства:

  # Get/Set Type bc rails doesnt allow :type to be set in mass
  def vehicle_type
    self.type
  end
  def vehicle_type=(type)
    self.type = type
  end

Проблема, с которой мы сталкиваемся, заключается в том, что когда мы вызываем update_attributes для данных формы и тип существующего транспортного средства изменяется, rails вызывает проверку для старого класса (не нового типа), что приводит к ошибкам. Что нам нужно сделать, так это то, что при смене типа транспортного средства модель меняется и на этот новый тип.

Есть ли способ сделать это?


Вот действие по обновлению (парк транспортных средств has_many):

  # PUT /fleet/1
  # PUT /fleet/1.xml
  def update
    @fleet = Fleet.find(params[:id])

    respond_to do |format|
      if @fleet.update_attributes(params[:fleet])
        flash[:notice] = 'Fleet of vehicles was successfully updated.'
        format.html { render :action => "edit" }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @fleet.errors, :status => :unprocessable_entity }
      end
    end
  end

Вот флот:

class Fleet < ActiveRecord::Base
  has_many :vehicles, :dependent => :destroy, :order => 'position ASC'
  accepts_nested_attributes_for :vehicles,
    :reject_if => proc { |attrs| attrs['name'].blank? },
    :allow_destroy => true

Ответы [ 2 ]

2 голосов
/ 07 декабря 2009

Можно использовать фабричный метод для создания правильного типа транспортного средства, а затем назначить атрибуты.

def Vehicle.factory(type)
   type.constantize.new
end
0 голосов
/ 07 декабря 2009

Когда вы вызываете @vehicle.save, вы можете добавить false в качестве первого параметра, чтобы пропустить проверку (@vehicle.save(false)). Другой вариант - использовать ActiveRecord::Base#update_attribute - что пропускает проверку.

Таким образом, вы можете сохранить свою модель без изменения столбца типа, а затем добавить @vehicle.update_attribute(:type, "Truck") в том же действии. Два запроса SQL, но могут быть необходимы для вашей ситуации.

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