Добавить ассоциацию (<<) без фиксации в базе данных

Можно ли в Rails добавить ассоциацию ксуществующий записать без немедленной фиксации этого изменения в базе данных? Например. если у меня есть Post has_many: теги

post.tags < Tag.first
 Jesse Wolgamott27 июл. 2013 г., 22:26
@ Мохамад, если у вас есть автосохранение, я уверен, что это будет.
 mrbrdo09 янв. 2014 г., 17:55
Похоже, это может работать в зависимости от реализации, я должен попробовать
 mrbrdo02 нояб. 2012 г., 15:40
сборка работает нормально, но не при попытке добавить ассоциацию к уже существующей записи. Я неНе вижу аналогичного метода для добавления ассоциаций в существующие записи (здесь я имею в виду существующую дочернюю запись). Я обновил вопрос, если теперь это станет понятнее.
 Igor Kasyanchuk12 нояб. 2013 г., 09:27
как насчет post.post_tags = post.post_tags + [Tag.find (111)]?
 Mohamad27 июл. 2013 г., 21:55
@JesseWolgamott Это полезно, если вы хотите инициализировать дочерний объект и добавить его в родительский объект, внести изменения в родительский объект и сохранить все в одном вызове / транзакции, вызвав save для родительского объекта.
 Mohamad27 июл. 2013 г., 22:02
@JesseWolgamott Чтобы было ясно,build не позволяет инициализировать и предварительно обрабатывать дочерний объект, затем назначать его родительскому объекту, изменять родительский объект и сохранять оба в одной транзакции.
 Jesse Wolgamott02 нояб. 2012 г., 15:48
Нет, вы не можете иметь синтаксис, который вы хотите.
 mrbrdo02 нояб. 2012 г., 15:46
Я думаю, в идеале, не нарушая существующий код, я хотел бы что-то вроде post.tags.build id: Tag.first.id. Можно'не думаю о лучшей семантике для него, так как <<нажми и т. д. все уже определили поведение комитетов сразу. -_- Возможно post.tags.build_to Tag.first. Я точно не уверенМне просто нравится возможность сделать это.
 mrbrdo02 нояб. 2012 г., 15:49
Это'не синтаксис, который я хочу, этос функциональностью. Я'Я знаю, что << делает. (ну, это работает, как я хочу в случае, если сообщение является "новая запись?", но это'не очень помогает)
 Isaac Betesh27 июн. 2014 г., 17:07
@ igor-kasyanchuk, ваши предложения терпят неудачу в Rails 3.2.18 - он сразу же сохраняет запись. Не могли бы вы указать версию, где это должно работать?
 jefflunt02 нояб. 2012 г., 15:39
Какие'неправильно с использованиемbuild на родительском объекте? Можете ли вы объяснить более подробно, что, по вашему мнению, противоречит этому и / или как вы хотели бы, чтобы это выглядело в идеальном мире?build кажется "построенный» (если ты'простите за каламбур) для этой цели - добавление дочернего / связанного объекта без немедленной его фиксации.

Ответы на вопрос(4)

Решение Вопроса

post.association(:tags).add_to_target(Tag.first)

Смотрите эту суть:https://gist.github.com/betesh/dd97a331f67736d8b83a

Обратите внимание, что при сохранении родительского элемента сохраняется дочерний элемент, и этот child.parent_id НЕ устанавливается, пока вы не сохраните его.

РЕДАКТИРОВАТЬ 6/6/2015: для полиморфной записи:

post.association(:tags).send(:build_through_record, Tag.first)
# Tested in Rails 4.2.5
 inye06 нояб. 2017 г., 16:30
нет нормальная ассоциация
 Isaac Betesh06 нояб. 2017 г., 16:22
@inye Это для полиморфной ассоциации?
 Isaac Betesh07 нояб. 2017 г., 14:33
затемadd_to_target должен работать иbuild_through_record не должен, как вы заметили.
 inye03 нояб. 2017 г., 15:09
post.association(:tags).send(:build_through_record, Tag.first) у меня не работает на 4.2.9 ноpost.association(:tags).add_to_target(Tag.first) работает отлично

post.association(:tags).add_to_target(Tag.first) работает наhas_many отношения, но вы можете использоватьpost.association(:tag).replace(Tag.first, false) заhas_one отношения. Второй аргумент (false) говорит не сохранять; по умолчанию он будет зафиксирован в базе данных, если вы оставите аргумент пустым.

ПРЕДИСЛОВИЕ Это не совсем ответ на этот вопрос, но кто-то ищет этоДобрый функциональности может найти это полезным. Очень тщательно обдумайте этот и другие варианты, прежде чем бездумно вводить их в производственную среду.

В некоторых случаях вы можете использовать отношение has_one, чтобы получить то, что вы хотите. Опять же, действительно подумайте, что выпытаемся выполнить, прежде чем использовать это.

Код для рассмотрения У тебя естьhas_many отношения отTrunk вBranch и вы хотите добавить новую ветку.

class Trunk
  has_many :branches
end

class Branch
  belongs_to :trunk
end

Я также могу связать их друг с другом в единственном числе. Мы'добавлюhas_one отношение кTrunk

class Trunk
  has_many :branches
  has_one :branch
end

На этом этапе вы можете делать такие вещи, какTree.new.branch = Branch.new и ты'Я буду устанавливать отношения, которые не будут сохранены сразу, но после сохранения будут доступны из.Tree.first.branches

тем не мение, это создает довольно запутанную ситуацию для новых разработчиков, когда они смотрят на код и думают "Ну, что, черт возьми, это должно быть, один или много?

Для решения этой проблемы мы можем сделать более разумнымhas_one отношения сscope

class Trunk
  has_many :branches

  # Using timestamps
  has_one :newest_branch, -> { newest }, class_name: 'Branch'

  # Alternative, using ID. Side note, avoid the railsy word "last"
  has_one :aftm,ost_branch, -> { aftmost }, class_name: 'Branch'
end

class Branch
  belongs_to :trunk

  scope :newest, -> { order created_at: :desc }
  scope :aftmost, -> { order id: :desc }
end

Будьте осторожны с этим, но он может выполнять функции, запрашиваемые в OP.

post_tag = post.post_tags.find_or_initialize_by_tag_id(Tag.first.id)
post_tag.save
 jimworm27 июн. 2014 г., 14:11
Это работает. Я'Мы обновили ответ с правильным использованием кода. Rails 4 имеет другой синтаксис.find_or_initialize_by(attr_hash)

Ваш ответ на вопрос