35

Rails 4.xベータ版で遊んでいて、ネストされた属性をcarrierwaveで機能させようとしていました。私がしていることが正しい方向であるかどうかはわかりません。周りを検索し、最終的にレールのソースと強力なパラメータを調べた後、以下のメモを見つけました。

# Note that if you use +permit+ in a key that points to a hash,
# it won't allow all the hash. You also need to specify which
# attributes inside the hash should be whitelisted.

https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb

つまり、has内のすべての属性をすべて指定する必要があるということで、私は次のことを試しました。

Paramの例:

{"utf8"=>"✓",
 "authenticity_token"=>"Tm54+v9DYdBtWJ7qPERWzdEBkWnDQfuAQrfT9UE8VD=",
 "screenshot"=>{
   "title"=>"afs",
   "assets_attributes"=>{
     "0"=>{
       "filename"=>#<ActionDispatch::Http::UploadedFile:0x00000004edbe40
                      @tempfile=#<File:/tmp/RackMultipart20130123-18328-navggd>,
                      @original_filename="EK000005.JPG",
                      @content_type="image/jpeg",
                      @headers="Content-Disposition: form-data; name=\"screenshot[assets_attributes][0][filename]\"; filename=\"EK000005.JPG\"\r\nContent-Type: image/jpeg\r\n">
     }
   }
 },
 "commit"=>"Create Screenshot"}

コントローラ

def screenshot_params
  params.require(:screenshot).permit(:title,
    :assets_attributes => [:filename => [:@tempfile,:@original_filename,:@content_type,:@headers] 

上記は「機能」していません(carrierwaveをトリガーしていません)が、私が見つけた標準のネストされた例を使用したときにエラー(許可されていないパラメーター:ファイル名)が発生しなくなりました。

def screenshot_params
  params.require(:screenshot).permit(:title, assets_attributes: :filename)

誰かが助けることができればそれは素晴らしいでしょう。ハッシュを指すキーがネストされた例を見つけることができませんでした。

4

6 に答える 6

34

私の他の答えはほとんど間違っていました-新しい答え。

params ハッシュでは、:filename は別のハッシュに関連付けられておらず、ActiveDispatch::Http::UploadedFile オブジェクトに関連付けられています。最後のコード行:

def screenshot_params
  params.require(:screenshot).permit(:title, assets_attributes: :filename)

は実際には正しいですが、許可されているスカラー型の 1 つではないため、ファイル名属性は許可されていません。コンソールを開いて、params オブジェクトを次の形で初期化すると、次のようになります。

params = ActionController::Parameters.new screenshot: { title: "afa", assets_attributes: {"0" => {filename: 'a string'}}}

そして、最後の行に対して実行します:

p = params.require(:screenshot).permit(:title, assets_attributes: :filename)
# => {"title" => "afa", "assets_attributes"=>{"0"=>{"filename"=>"abc"}}}

ただし、アップロードされたファイルの params ハッシュに対して同じことを行うと、次のようになります。

upload = ActionDispatch::Http::UplaodedFile.new tempfile: StringIO.new("abc"), filename: "abc"
params = ActionController::Parameters.new screenshot: { title: "afa", assets_attributes: {"0" => {filename: upload}}}
p = params.require(:screenshot).permit(:title, assets_attributes: :filename)

# => {"title" => "afa", "assets_attributes"=>{"0"=>{}}}

そのため、バグを報告するか、Rails にプル リクエストを送信する価値はありますが、それまでの間は、rawparamsオブジェクトを使用してファイル名パラメーターに直接アクセスする必要があります。

params[:screenshot][:assets_attributes]["0"][:filename]
于 2013-01-23T18:31:51.093 に答える
4

実際には、ネストされたすべてのパラメーターをホワイトリストに登録する方法があります。

params.require(:screenshot).permit(:title).tap do |whitelisted|
  whitelisted[:assets_attributes ] = params[:screenshot][:assets_attributes ]
end

この方法は、他のソリューションよりも優れています。深くネストされたパラメーターを許可できます。

他のソリューションは次のようになります。

params.require(:screenshot).permit(:title, :assets_attributes => [:filename, :id, :screenshot_id])

しないでください。


ソース:

https://github.com/rails/rails/issues/9454#issuecomment-14167664

于 2014-09-25T21:00:03.143 に答える
0

私は同じ問題を抱えていましたが、今それを修正しました。あなたがしなければならないのは

params.require(:vehicle).permit(:user_id, assets_attributes: [:id, :image]).

pry gem を使用して、アセット オブジェクトが持っている属性の種類を確認して、id があることを確認し、他の不足している属性を追加すると、完全に機能するはずです。使用しているペーパークリップ アセットは、車両クラス内のネストされたオブジェクトであり、画像の添付ファイルがアセットに追加されます。モデルで検証を行っていることを確認してください

accepts_nested_attributes_for :assets, allow_destroy: true
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/

ビュー内でアセットをループして各画像を取得します

<%= @vehicle.assets.size %>
    <% for asset in @vehicle.assets %>
        <%=link_to image_tag (asset.image.url(:thumb)) %>
    <% end %>

正しい場合、問題は、asset_attributes が配列であり、各画像にインデックス列と画像があることです。

form_for にはこれに似たものが必要です。必要に応じてプレビューを含めて、アップロードで画像を表示できるようにすることもできます。そのための下部のコードを使用します。

<div class="field">
    <h3>Vehicle Image Upload</h3>
    <%= f.fields_for :assets do |asset_fields| %>

        <% if asset_fields.object.new_record? %>
            <p>
                <%= asset_fields.file_field :image %>
            </p>
        <% end %>
    <% end %>
</div>

<div class="field">
    <h4>Vehicle Image</h4>
    <%= f.fields_for :assets do |asset_fields| %>

        <% unless asset_fields.object.new_record? %>
          <%= link_to image_tag(asset_fields.object.image.url(:thumb)),
                    asset_fields.object.image.url(:original)%>
          <%= asset_fields.check_box :_destroy %>
        <% end %>
    <% end %>
</div>
于 2016-03-04T17:43:04.757 に答える