未授权的参数,嵌套表单 - Ruby On Rails

3
我跟随Michael Hartl的教程学习,并想要在微博中添加照片。但是当我提交微博时,图片没有保存在数据库中,在开发日志中我可以看到未被允许的参数:image。我查看了其他帖子并遵循他们的建议,但对我来说没有用。

模型

micropost.rb

class Micropost < ActiveRecord::Base
  belongs_to :user
  has_one :photo
  default_scope -> { order('created_at DESC') }
  validates :content, presence: true, length: { maximum: 140 }
  validates :user_id, presence: true
end

photo.rb

class Photo < ActiveRecord::Base
    belongs_to :micropost
    has_attached_file :image
end

CONTROLLERS

photos_controller.rb

class PhotosController < ApplicationController
  before_action :signed_in_user, only: [:create, :destroy, :index]
  
  def create
    @photo = Photo.new(photo_params)

    respond_to do |format|
      if @photo.save
        format.html { redirect_to @photo, notice: 'Photo was successfully created.' }
        format.json { render action: 'static_pages/home', status: :created, location: @photo }
      else
        format.html { render action: 'static_pages/home' }
        format.json { render json: @photo.errors, status: :unprocessable_entity }
      end
    end
  end

  private
    def photo_params
      params.require(:photo).permit(:image)
    end
end

microposts_controller.rb

class MicropostsController < ApplicationController
  before_action :signed_in_user, only: [:create, :destroy]
  
  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to root_url
    else
      @feed_items = []
      render 'static_pages/home'
    end
  end
  
  private

  def micropost_params
    params.require(:micropost).permit(:content, photo_attributes: [:photo_id, :image])
  end
end

视图

_micropost_form.html.erb 我不知道如何构建这个表单,我已经尝试了很多不同的构造方式

<%= form_for(@micropost) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="field">
    <%= f.text_area :content, placeholder: "Compose new micropost..." %>
  </div>

  <%= f.fields_for :image, :html => { :multipart => true } do |builder| %>
    <%= f.file_field :image, :f => builder %>
  <% end %>

  <%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>

当我想提交表格时,一切都正常,但“photo_id”列为空。而且照片没有保存到数据库中。

服务器日志

Started POST "/microposts" for 127.0.0.1 at 2013-11-27 15:06:06 +0100
Processing by MicropostsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"<my_private_token>", "micropost"=>{"content"=>"Hello world", "image"=>#<ActionDispatch::Http::UploadedFile:0x00000003401a48 @tempfile=#<Tempfile:/tmp/RackMultipart20131127-4010-1r6qt80>, @original_filename="paint.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"micropost[image]\"; filename=\"paint.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "commit"=>"Post"}
  [1m[36mUser Load (0.2ms)[0m  [1mSELECT "users".* FROM "users" WHERE "users"."remember_token" = '342df8f039f7f40698b3691f77d2539dc8b9c101' LIMIT 1[0m
Unpermitted parameters: image
  [1m[35m (0.1ms)[0m  begin transaction
  [1m[36mSQL (0.4ms)[0m  [1mINSERT INTO "microposts" ("content", "created_at", "updated_at", "user_id") VALUES (?, ?, ?, ?)[0m  [["content", "Hello world"], ["created_at", Wed, 27 Nov 2013 14:06:06 UTC +00:00], ["updated_at", Wed, 27 Nov 2013 14:06:06 UTC +00:00], ["user_id", 101]]
  [1m[35m (145.1ms)[0m  commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 153ms (ActiveRecord: 145.7ms)

我现在完全被卡住了,如果你能找到一些可以帮助我的东西,告诉我在哪里找到解决方案,非常感谢!!!


看起来你有嵌套的像{:micropost => {:image => ...}},所以你需要params.require(:micropost).permit(:content, :image, ...) - Farley Knight
你的意思是像这样:def micropost_params params.require(:micropost).permit(:content, photo_attributes: [:photo_id, :image, image_file_name, :image_content_type, :image_file_size, :image_update_at]) end,但是仍然没有允许:image。 - 2ueenO
我发现这篇帖子很有用。http://stackoverflow.com/questions/20334124/unpermitted-parameters-error-for-permitted-attributes - Evolve
1个回答

0
你需要在你的 Micropost 类中使用 accepts_nested_attributes_for
class Micropost < ActiveRecord::Base
  belongs_to :user
  has_one :photo
  accepts_nested_attributes_for :photo
  default_scope -> { order('created_at DESC') }
  validates :content, presence: true, length: { maximum: 140 }
  validates :user_id, presence: true
end

看起来你的表单是将图片与你的微博相关联,而不是与微博的照片相关联。请查看fields_for的Ruby文档。你可以尝试将表单的一部分更改为以下内容吗?

<%= f.fields_for :photo, :html => { :multipart => true } do |photo_fields| %>
  <%= photo_fields.file_field :image %>
<% end %>

如果您这样做,您需要确保在呈现视图的控制器操作中调用@micropost.build_photo

我认为您不需要在microposts_controller.rb的strong参数中列出photo_id。一旦记录保存到数据库中,它就应该被设置。

您还可以阅读Rails指南构建复杂表单。该指南介绍了如何设置模型、视图和控制器以处理嵌套属性。如果您还没有,请查看他们关于强参数的描述,可能会有所帮助。


我更新了我的回答。尝试在你的模型中添加accepts_nested_attributes_for - Michael Stalker
非常抱歉没有仔细阅读您的第一条评论。我应该注意到您已经尝试过accepts_nested_attributes_for。如果字段消失了,这很奇怪。如果您查看HTML源代码,元素是否存在?这可能有助于确定这是CSS问题还是Rails问题。 - Michael Stalker
Rails问题,视图中仍然存在行。服务器日志显示视图仍在页面上呈现!也许这是因为我在微博控制器的新功能中缺少了一些有关构建照片的东西?(我在某个地方读到过)。但我认为它已经在创建函数中完成了。 - 2ueenO
服务器日志会告诉你页面是否已经渲染,但我认为它们不会告诉你页面上的元素是否已经渲染。我们需要弄清楚表单是否被渲染,并且被某些东西隐藏了,或者Rails根本没有渲染HTML表单。 - Michael Stalker
是的...!这就是问题,但我真的不明白为什么。 - 2ueenO
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接