Rails - добавить данные в таблицу отношений - PullRequest
0 голосов
/ 23 сентября 2019

у меня есть questions, answers и photos models.Я использую paperclip для изображений.

Я не могу добавить answer's image к photos table, используя приведенный ниже код.

 q = Question.new(
            title:  p[:title],
            post:  p[:post]
            )

p[:answers].each do |a|
  q.answers.build(body: a[:body])
  if a[:images]
    a[:images].each do |e|
      q.answers.photos.create(image: e) #this line gives the error
    end
  end
end

Строка ошибки q.answers.photos.create(image: e)

Ошибка:

undefined method `photos' for #<Answer::ActiveRecord_Associations_CollectionProxy:0x00007f9592208800>

Я создал ассоциации для своих моделей, например:

class Answer < ApplicationRecord
 belongs_to :question
 has_many :photos
end

class Photo < ApplicationRecord
  belongs_to :question
  belongs_to :answer

  has_attached_file :image,
                    :path => ":rails_root/public/img/:filename", validate_media_type: false

  do_not_validate_attachment_file_type :image
end


Ответы [ 2 ]

4 голосов
/ 23 сентября 2019

Фотография принадлежит одному вопросу и одному ответу.Но вы пытаетесь создать фотографию, которая принадлежит нескольким q.answers.

Возможно, вы захотите сделать что-то вроде этого:

question = Question.new(title: p[:title], post: p[:post])

p[:answers].each do |a|
  answer = q.answers.create(body: a[:body])
  if a[:images]
    a[:images].each do |e|
      answer.photos.create(image: e, question: q)
    end
  end
end
3 голосов
/ 23 сентября 2019

Прежде всего, это не ruby-ish, чтобы делать p[:title], a[:image] и т. Д. (Кроме того, вы вводите три дополнительных символа на вызов метода, и вы знаете, жизнь коротка.) Просто сделайте p.title, a.image и т. Д. Итак, ваш код должен выглядеть следующим образом:

q = Question.new(title: p.title, post: p.post)

p.answers.each do |answer|
  q.answers.build(body: answer.body)
  if answer.images
    answer.images.each do |image|
      q.answers.photos.create(image: image)
    end
  end
end

Теперь вы хотите создать новые фотографии для answer, который вы создали здесь:

q.answers.build(body: answer.body)

Вместо этого вы пытаетесь вызвать photos для перечислимого, возвращаемого q.answers.photos.И, естественно, у перечислимого (ActiveRecord_Associations_CollectionProxy в данном случае) такого метода нет.Итак, вы получаете ошибку undefined method.

Вы можете попробовать:

q = Question.new(title: p.title, post: p.post)

p.answers.each do |answer|
  new_answer = q.answers.build(body: answer.body)
  if answer.images
    answer.images.each do |image|
      new_answer.photos.create(image: image)
    end
  end
end

За исключением того, что вы еще не сохранили new_answer, поэтому у него нет id.В этом случае это может все еще ошибка.

Итак, возможно:

q = Question.new(title: p.title, post: p.post)

p.answers.each do |answer|
  new_answer = q.answers.create(body: answer.body)
  if answer.images
    answer.images.each do |image|
      new_answer.photos.create(image: image)
    end
  end
end

Я не уверен, если вы действительно хотите все эти дубликаты Photo с (возможно, вы делаете).Но, если вы этого не сделаете, я думаю, что я бы сделал что-то вроде:

class AnswerPhoto < ApplicationRecord
  belongs_to :answer
  belongs_to :photo
end

class Answer < ApplicationRecord
  belongs_to :question
  has_many :answer_photos
  has_many :photos, through: :answer_photos
end

class Photo < ApplicationRecord
  belongs_to :question
  has_many :answer_photos
  has_many :answers, through: :answer_photos
end

В этом случае вы могли бы сделать что-то вроде:

q = Question.new(title: p.title, post: p.post)

p.answers.each do |answer|
  new_answer = q.answers.create(body: answer.body)
  new_answer.photos << answer.photos
end

Мне кажется, у вас есть некоторыеN+1 Запросы продолжаются там, так что вы захотите посмотреть на .include.И, поскольку вы на самом деле не используете answer.photos в качестве правильных объектов ruby ​​(вам действительно нужны эти id s), вы можете заглянуть в .pluck.

...