Не удается сохранить атрибуты изображения с помощью скрепки в рельсах 4

В моем приложении Rails 4 есть две связанные модели: product.rb и image.rb. Модель Image позволяет прикреплять файлы, используя драгоценный камень Paperclip.

Изображения belong_to a Продукт и продукт has_many Изображения.

Я хотел бы использовать представление Product new для создания и прикрепления изображения при создании продукта. Каждый раз, когда я пытаюсь, параметры, связанные с изображением Paperclip, не сохраняются и заканчиваются nil.

Вот модели:

Product.rb

class Product < ActiveRecord::Base
  validates :name, :part_number, presence: true
  has_many :images, dependent: :destroy
  belongs_to :category
  accepts_nested_attributes_for :images, allow_destroy: true
end

Image.rb

class Image < ActiveRecord::Base
  belongs_to :product
  has_attached_file :image
end

Просматривая прошлые вопросы о переполнении стека, я нашел некоторые соответствующие вопросы и ответы, но ни один из них, похоже, не помогает моей конкретной ситуации. Пока я могу представить файл с правильными атрибутами, но он не сохраняет их в базе данных.

ProductsController#create

def create
  @product = Product.new(product_params)
end

def product_params
  params.require(:product).permit(:name,
                                  :category_id,
                                  :part_number,
                                  images_attributes: [:image])
end

ProductsController#new

def new
  @product = Product.new
  @categories = # irrelevant to question
end

products/new.html.haml

= form_for @product, :html => 
  = f.label :name
  = f.text_field :name
  = f.label :part_number
  = f.text_field :part_number
  = f.label :category_id
  = f.select :category_id, @ca
  = f.fields_for :image do |ff|
    = ff.label :image 
    = ff.file_field :image
  = f.submit('Create Product')

Глядя на параметры, я могу сказать, что передаются правильные атрибуты:

Параметры примера:

{"utf8"=>"✓",
 "authenticity_token"=>"jGNy/TasHzP0EcWDFzZ3XH5/fpxb6vD+ncQ2PZSQ3/I=",
 "product"=>{"name"=>"bar",
 "part_number"=>"foo",
 "category_id"=>"30",
 "image"=>{
 "image"=>#<ActionDispatch::Http::UploadedFile:0x007fc82f58e0e0
 @tempfile=#<Tempfile:/var/folders/04/23d9grkj5fv3wkj2t8858kx40000gn/T/RackMultipart20131029-64949-1ldkz4g>,
 @original_filename="FPE230_b.jpg",
 @content_type="image/jpeg",
 @headers="Content-Disposition: form-data; name=\"product[image][image]\"; filename=\"FPE230_b.jpg\"\r\nContent-Type: image/jpeg\r\n">}},
 "commit"=>"Create Product"}

Однако изображение фактически не сохраняется в базе данных. Как я могу это исправить?

ИЗМЕНИТЬ

Внимательно изучая журналы, я вижу, что получаю ошибку "unpermitted parameters: image". Это даже после добавления images_attributes: [:image] к моему методу product_params.

Ответ 1

Мне удалось настроить настройки, похожие на ваши, со следующими изменениями:

В ProductsController#create вместо создания изображения отдельно, пусть вложенные атрибуты обрабатывают его и просто делают:

@product = Product.new(product_params)

И разрешите вложенные параметры (я понял image_attributes: [:image] из этот вопрос):

def product_params
  params.require(:product).permit(:name, :part_number, images_attributes: [:image])
end

Вот как выглядят мои параметры в журналах для запроса create:

{
   "utf8"=>"✓", 
   "authenticity_token"=>"7EsPTNXu127itgp4fbohu672/L4XnSwLEkrqUGec3pY=", 
   "product"=>{
     "name"=>"whatever", 
     "part_number"=>"12345", 
     "images_attributes"=>{
       "0"=>{
         "image"=>#<ActionDispatch::Http::UploadedFile:0x007feb0c183b08 
           @tempfile=#<Tempfile:/var/folders/6k/16k80dds0ddd6mhvs5zryh3r0000gn/T/RackMultipart20131031-51205-emaijs>, 
           @original_filename="some-image.png", 
           @content_type="image/png", 
           @headers="Content-Disposition: form-data; name=\"product[images_attributes][0][image]\"; filename=\"ponysay.png\"\r\nContent-Type: image/png\r\n">
        }
      }
    }, 
    "commit"=>"Create"}

И я вижу вставку в products и вставку в images.

Если это не сработает, можете ли вы разместить свою ProductsController#new и новую форму продукта?

ИЗМЕНИТЬ ПОСЛЕ ВАШЕГО ИЗМЕНЕНИЯ:

У меня есть 3 разных объекта в app/views/products/new.html.erb и ProductsController#new, которые могут повлиять на ваши результаты:

  • В form_for у меня есть multipart: true, как в документация paperclip:

    <%= form_for @product, :url => products_path, :html => { :multipart => true } do |f| %>
    
  • Поскольку Product has_many :images, в моей форме у меня есть fields_for :images вместо fields_for :image:

    <%= f.fields_for :images do |i| %>
      <%= i.file_field :image %>
    <% end %>
    
  • Этот fields_for не показывает ничего на странице, если только в ProductsController#new я не создаю образ; ваш Product.new делает это случайно?

    def new
      @product = Product.new
      @product.images.build
    end
    

Есть ли какие-то особые причины для этих различий? Работает ли ваш код, если вы меняете его в соответствии с моим?