Как мне сохранить порядок ассоциаций в Rails3? - PullRequest
0 голосов
/ 28 декабря 2010

У меня есть массив локаций

locations = ["california", "new york", "florida"]

У меня есть модель под названием foobar, которая has_many :places. Place модель belongs_to :foobar и имеет один соответствующий столбец - name:string.

У меня есть вложенная форма, которая позволяет мне выбирать места, подходящие для foobar. Чтобы предложить варианты, я строю места на основе моего списка местоположений в моем контроллере:

class FoobarController < ApplicationController
  def edit
    @foobar = Foobar.find(params[:id])
    APP_CONFIG['locations'].each do |location|
       @foobar.places.find_by_name(location) || @foobar.places.build(:name => location)
    end
  end
end

Это работает почти без проблем. Причина, по которой я включаю метод редактирования, заключается в том, что это проблемный метод. Список мест ДОЛЖЕН быть заполнен, но Foobar уже существующие места отображаются сверху.


Пример времени! :)

  1. Я создаю новый Foobar. В моей форме Я прокручиваю вниз к местам и вижу варианты "Калифорния", "Нью-Йорк" и "Флорида". Я проверяю "Калифорния" и "florida" и создайте Foobar.

  2. Далее я иду редактировать Foobar. Опять я прокрутите вниз к местам, и я вижу что я проверил два варианта. Это отлично, разве что порядок в какие параметры появляются "Калифорния", "Флорида", "Нью-Йорк" - отмеченные места находятся на вершине.

Как сохранить порядок местоположений из моего исходного массива?

Спасибо!


Обновление: код просмотра:

<%= f.fields_for :places do |place| %>
    <div class="place">
        <%= place.hidden_field :name %>
        <%= place.check_box :checked %>
        <%= place.label :checked, place.object.name %>
    </div>
<% end %>

Ответы [ 2 ]

1 голос
/ 28 декабря 2010

Вы не можете ... По крайней мере, не так, как вы это делаете.Подумайте о том, что делает рельсы.Он автоматически упорядочивается по столбцу id (PK) таблицы.Поскольку записи, которые вы строите, не будут иметь идентификатора, они будут помещаться в конце - каждый раз.Вы МОЖЕТЕ найти и использовать CREATE и выдумки, но это грязно и может привести к серьезным проблемам.

Чтобы поддерживать порядок (каламбур), вам понадобится какая-то система указателей массива:

class FoobarController < ApplicationController
  def edit
    @foobar = Foobar.find(params[:id])
    @places = Array.new
    APP_CONFIG['locations'].each do |location|
      @places << @foobar.places.build(:name => location)
    end
  end
end

Затем, по вашему мнению, вам нужно будет перебрать массиви вручную построить форму.Я рекомендую просмотреть исходный код и посмотреть, как вначале появляется вложенная форма.

Вот как я бы к ней подходил - собирать каждый раз (без find_by_name).Затем в вашей модели вы хотите:

class Foo < ActiveRecord
  has_many :places

  accepts_nested_attributes_for :places, :reject_if => { |a| !APP_CONFIG['locations'].include?(a) || Place.find_by_name(a).nil? || !Place.find_by_name_and_foo_id(a, self.id).nil? }
end

Теперь я на самом деле не тестировал этот код именно для вашего случая, поэтому я разобью его;

1.) Отклонитьесли представленный атрибут отсутствует в глобальном массиве (больше из соображений безопасности)

2.) Отклонить, если имя не является допустимым местом (опять же, из соображений безопасности)

3.) Отклонить, если для этого foo существует место УЖЕ (ваш класс has_many: place)

0 голосов
/ 30 апреля 2012

Ознакомьтесь с Act_as_list >> https://github.com/rails/acts_as_list, Он явно хранит порядок элементов в коллекции has_many в столбце с именем "position".

...