Вопрос

У меня есть форма, которая позволяет мне добавлять в поток файлы разных форматов.Итак, поток состоит из множества файлов. Эти файлы являются XML-файлами, но в основном имеют разные схемы.У меня есть одна форма, которая позволяет пользователю добавлять любой файл, который он хочет. Я использую STI (который отлично работает, когда данные уже есть в таблице), моя проблема заключается в добавлении данных в таблицу.

Форма имеет одно поле ввода, просто file_field, которое позволяет пользователю выбрать файл, который он хочет загрузить.Поскольку у меня есть только одна форма, я не могу создать экземпляр правильного объекта, мне приходится делать это программно.и я не уверен, как это сделать.

Должен ли я просто (или могу ли я) добавить раскрывающийся список с возможными типами и назвать это поле «типом», чтобы при отправке формы рельсы создавали экземпляр типа записи объекта, поскольку предоставлен атрибут типа?

Какова наилучшая практика для этого..Я использую рельсы 2.3.4.

Это было полезно?

Решение

Я нашел решение на http://coderrr.wordpress.com/2008/04/22/building-the-right-class-with-sti-in-rails/#comment-1826

class GenericClass < ActiveRecord::Base
  class << self
    def new_with_cast(*a, &b)
      if (h = a.first).is_a? Hash and (type = h[:type] || h['type']) and (klass = type.constantize) != self
        raise "wtF hax!!"  unless klass < self  # klass should be a descendant of us
        return klass.new(*a, &b)
      end

      new_without_cast(*a, &b)
    end
    alias_method_chain :new, :cast
  end
end

Это отлично сработало для меня с минимальным количеством кода - я не знаю, хакерское оно или нет, но оно работает и довольно чистое.Мне понравилось то, что это всего лишь 10 строк кода.

Другие советы

Я не знаю, сколько у вас типов, но в прошлом я просто использовал отдельные контроллеры и представления для разных типов.Таким образом, вы не создаете новый объект базового класса и не пытаетесь установить тип, а просто используете модель, которая наследуется от базового класса.Каждая новая/редактируемая страница ваших ресурсов может отображать общий фрагмент в блоке form_for.Частичный файл будет содержать ваше file_field.

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

Недостатком, конечно, является большее количество файлов, и на какую бы страницу вы ни ссылались на «добавить новый файл», вам нужно добавить несколько ссылок, таких как «добавить новый файл этого типа», «добавить новый файл этого типа» и т. д.

Что касается установки типа в форме, я не уверен, работает ли это, сомневаюсь, но просто попробуйте (дайте нам знать).Вы можете сделать этот тип выпадающим из select_tag и при его изменении использовать Javascript для изменения местоположения действия в форме.

Отредактировано и добавлено базовое решение

Не то чтобы мне нравилось это решение, и я сомневаюсь, что оно ни в коем случае не лучшее, но если вам действительно не нужны отдельные контроллеры и вам нужно, чтобы оно работало, вы можете сделать что-то вроде этого:

class XmlFile < ActiveRecord::Base
end

class XmlFileTypeA < XmlFile 
end

class XmlFileTypeB < XmlFile 
end

def create
    # Leaving this case statement in the controller for simplicity but you probably want to move this to the model
    case params[:chosen_xml_type]
      when "file_type_a"
        @item = XmlFileTypeA.new(params)
      when "file_type_b"
        @item = XmlFileTypeB.new(params)
      else
        raise "Unknown file type!"
      etc
    end
end
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top