Иногда не уместно использовать << в ассоциациях ActiveRecord? - PullRequest
0 голосов
/ 27 января 2011

Иногда это работает, а иногда нет:

class Foo
  has_many :bars
end

class Bar
  belongs_to :foo
end

foo = Foo.create
bar1 = Bar.create
bar2 = Bar.create

foo.bars << [bar1, bar2]

Исправление заключается в назначении их индивидуально:

foo.bars << bar1
foo.bars << bar2

обновлен

в тех случаях, когда я экспериментирую, foo и bar s не являются новыми объектами.

Я не видел шаблон, когда он работает или не работает. Более того, похоже, что рельсы справляются с массовым присваиванием (attr_accessible) здесь странно. Если у меня есть код для создания исключения, если выполняется массовое присвоение (чтобы помочь мне обнаруживать ошибки во время разработки), это не работает. Но если я не подниму эти исключения, это сработает, даже если foo_id нет в списке attr_accessible в любом случае.

Ответы [ 3 ]

2 голосов
/ 27 января 2011

Обычно, если вы делаете «<< [x, y]», вы не помещаете x и y в массив, а скорее в новый массив, содержащий x и y (делая его многомерным массивом): </p>

> test = Array.new
=> []
> test << [1, 2]
=> [[1, 2]]

Вместо этого вы можете использовать «<< x << y»: </p>

> test = Array.new
=> []
> test << 1 << 2
=> [1, 2]
1 голос
/ 27 января 2011

Для вновь созданных объектов, я бы рекомендовал использовать has_many вспомогательные методы ассоциации build или create:

foo = Foo.create
bar1 = foo.bars.create  # saves the record
bar2 = foo.bars.build   # does not save the record
bar2.save!              # actually creates the object

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

Если объект Bar, который вы пытаетесь добавить к foo, уже существует, я бы предпочел установить связь в объекте bar:

foo = Foo.create   # alternately Foo.find(1)
bar = Bar.find(1)  # alternately Bar.new, but then use Foo.bars.build
bar.foo = foo
bar.save!

Таким образом, намного легче отследить проблемы, например, Вы можете легко справиться с ошибкой проверки. Единственное отличие от << в том, что он обновляет foo.bars без перезагрузки, поэтому, если вам нужно, чтобы foo.bars был немедленно обновлен с полным списком баров (старые и новые связанные бары), возможно, захотите использовать <<.

В качестве заключительной сноски вы также можете использовать помощники build, чтобы создать все сразу:

foo = Foo.new
bar1 = Foo.bars.build
bar2 = Foo.bars.build
foo.save!          # saves foo, bar1, and bar2 in one transaction,
                   # provided they are all valid
0 голосов
/ 28 января 2011

С синтаксисом foo.bars << [bar1,bar2] все в порядке.Что касается метода <<, определенного в ассоциации has_many, Rails API говорит:

collection << (объект,…) </strong>

Добавляет один или несколько объектов в коллекцию, устанавливая их внешние ключи в первичный ключ коллекции.Обратите внимание, что эта операция немедленно запускает обновление sql без ожидания вызова сохранения или обновления родительского объекта.

Это может дать вам некоторые подсказки относительно (по-видимому) противоречивого поведения.

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