Rails参数不会传递给'params'变量

时间:2014-06-10 21:35:12

标签: ruby-on-rails parameters

我正在使用Rails 4创建应用程序。

基本上,我有两个型号,Card和CardCollection。 CardCollections has_many卡。 我用嵌套属性实现了这种关系。

class Card < ActiveRecord::Base
  belongs_to :card_collection
end

class CardCollection < ActiveRecord::Base
  has_many :uploaded_cards, class_name: 'Card', dependent: :destroy
  accepts_nested_attributes_for :uploaded_cards, allow_destroy: true
end

表格如下所示。

<%= form_for @card_collection, options do |f| %>
  <%= f.fields_for :uploaded_cards do |ff| %>
    <%= render 'cards/card_form', f: ff %>
  <% end %>
<% end %>

当我在表单中放入一些数据并按下提交按钮时,我可以看到参数正确传递给服务器。 (根据服务器日志)

Parameters: {"utf8"=>"✓", "authenticity_token"=>"YFn7RsQzR4Sq1bjR+mOhCASWmeqAxw9B30oAHCL
9qzk=", "card_collection"=>{"collectible_id"=>"16", "collectible_type"=>"Scrapbook", "uplo
aded_cards_attributes"=>{"0"=>{"_destroy"=>"false", "image_url"=>"https://s3-ap-northeast-
1.amazonaws.com/bucketplace/uploads/image_content/src/2833/2b67142422.jpg", "place"=>"1",
"style"=>"0", "description"=>"생각을 짓다......", "id"=>"97"}, "1"=>{"image_url"=>"http://
hodoli.s3.amazonaws.com/uploads%2F14_06_02_17_17_56_62276930_468703135.jpg", "place"=>"7",
 "style"=>"1", "description"=>"123"}}}, "project_cover_image_url"=>"", "commit"=>"확인", "
id"=>"16"}

但是,当我真的打印&#39; params&#39;程序代码中的变量,params [:card_collection] [:uploaded_cards_attributes] hash(嵌套属性部分)突然丢失。所以印刷的参数值如下所示。

"params=  {\"utf8\"=>\"✓\", \"_method\"=>\"patch\", \"authenticity_token\"=>\"YFn7RsQzR4Sq
1bjR+mOhCASWmeqAxw9B30oAHCL9qzk=\", \"card_collection\"=>{\"collectible_id\"=>16, \"collec
tible_type\"=>\"Scrapbook\"}, \"project_cover_image_url\"=>\"\", \"commit\"=>\"확인\", \"a
ction\"=>\"update\", \"controller\"=>\"card_collections\", \"id\"=>\"16\"}"
Unpermitted parameters: collectible_id, collectible_type

我不知道为什么会这样。我认为它与强参数&#39;没有关系。因为问题出在Rails端参数解析部分。 (我认为) 请帮我找到确切的问题和解决方案。

修改

这是我的控制器代码

class CardCollectionsController < ApplicationController
before_action :set_card_collection, only: [:do_upload, :edit, :update]
before_action :authenticate_user!, only: [:upload, :do_upload, :edit, :update]
before_action :authenticate_card_collection_owner!, only: [:do_upload, :edit, :update]

# GET /card_collections/upload_select
def upload_select
end

# GET /card_collections/upload
def upload
    @card_collection = CardCollection.new
end

def do_upload
    respond_to do |format|
        p card_collection_params
        if @card_collection.update(card_collection_params)
            format.html do
                @card_collection.collectible.update(cover_image_url: params[:project_cover_image_url]) unless params[:project_cover_image_url].blank?
                redirect_to @card_collection.collectible, notice: 'CardCollection was successfully updated.'
            end
            format.json { head :no_content }
        else
            @card_collection = CardCollection.new(card_collection_params)
            format.html { render 'upload', alert: '에러' }
            format.json { render json: @card_collection.errors, status: :unprocessable_entity }
        end
    end
end

# GET /card_collections/1/edit
def edit
end

# PATCH/PUT /card_collections/1
# PATCH/PUT /card_collections/1.json
def update
    respond_to do |format|
        if @card_collection.update!(card_collection_params)
            format.html do
                @card_collection.collectible.update(cover_image_url: params[:project_cover_image_url]) unless params[:project_cover_image_url].blank?
                redirect_to @card_collection.collectible, notice: 'CardCollection was successfully updated.'
            end
            format.json { head :no_content }
        else
            format.html { render 'edit', alert: '에러' }
            format.json { render json: @card_collection.errors, status: :unprocessable_entity }
        end
    end
end

private

# Use callbacks to share common setup or constraints between actions.
def set_card_collection
    if params[:id]
        @card_collection = CardCollection.find(params[:id])
        params[:card_collection] = {collectible_id: @card_collection.collectible_id, collectible_type: @card_collection.collectible_type}
    elsif params[:card_collection][:collectible_id].blank?
        @card_collection = CardCollection.new(card_collection_params)
        flash.now[:alert] = '스크랩북을 선택해 주세요'
        render 'upload'
    else
        @card_collection = CardCollection.find_by_collectible_id_and_collectible_type(params[:card_collection][:collectible_id], params[:card_collection][:collectible_type])
    end
end

# Never trust parameters from the scary internet, only allow the white list through.
def card_collection_params
    params.require(:card_collection).permit(CardCollection.param_names + [uploaded_cards_attributes: Card.param_names])
end

def authenticate_card_collection_owner!
    redirect_to previous_url if current_user != @card_collection.user
end
end

class CardCollection < ActiveRecord::Base
def self.param_names
    [:id, :name, :description]
end
end

class Card < ActiveRecord::Base
    def self.param_names
    [:id, :image_url, :description, :place, :style, :source, :width, :height]
end
end

解决 最后,由于@Rich Peck,我解决了这个问题。 真正的问题是关于Rails的路由部分。 我在一个控制器中通过两种方式识别特定记录,您可以在&#39; set_card_collection&#39;中看到。方法

resources :card_collection, only: [:edit, :update] do
  get :upload, on: :collection
  patch :do_upload, on: :collection 
end

原始route.rb文件如上所示。 我构建了我的路由文件(当用户连接上传页面时不指定CardCollection id),以便用户灵活地在上传页面中选择CardCollection。 但是要连接编辑页面,用户必须指定记录ID,例如/ card_collection / 1 / edit,因为它是Rails的默认行为。

然后我定制了&#39; set_card_collection&#39;控制器中的方法。

if params[:id]
        @card_collection = CardCollection.find(params[:id])
        params[:card_collection] = {collectible_id: @card_collection.collectible_id, collectible_type: @card_collection.collectible_type}
    elsif params[:card_collection][:collectible_id].blank?
        @card_collection = CardCollection.new(card_collection_params)
        flash.now[:alert] = '스크랩북을 선택해 주세요'
        render 'upload'
    else
        @card_collection = CardCollection.find_by_collectible_id_and_collectible_type(params[:card_collection][:collectible_id], params[:card_collection][:collectible_type])

尽管如此,我还不知道确切的原因,但是使用默认值:编辑和:更新路由设置会导致嵌套参数无法正确传递的问题。所以在我改变了我的route.rb文件之后,统一了识别记录的方式,问题就解决了。

resources :card_collections, only: [] do
    get :upload_select, on: :collection
    get :upload, on: :collection
    post :upload, on: :collection, to: :do_upload
    get :edit, on: :collection
    patch :update, on: :collection
    put :update, on: :collection
end

2 个答案:

答案 0 :(得分:1)

有许多问题可能导致此问题

-

错误

我看到你的系统正在生成uploaded_cards_attributes,这是跨越

的最大障碍

这意味着问题可能与您的strong params有关(我怀疑是因为params哈希在您的控制器中完全可用(它是您要限制访问的模型) ;或者你如何管理控制器内的参数

我不知道如何解决您的问题,但可能将成为Rails问题

-

<强>解决方法

我最初会看看你如何通过参数

您似乎正在使用edit / update方法(使用PATCH动词)。这可能是一个问题,因为Rails可能无法传递已创建对象的数据。

我最初会使用new表单进行测试 - 看看你是否可以创建具有嵌套属性的新对象。如果你能做到这一点,我会在你的路线&amp;中使用nested resources进行测试。直接编辑CardCollection对象:

#config/routes.rb
resources :card_collections do
   resources :card_uploads
end

这将允许您执行以下操作:

#app/controllers/card_collections_controller.rb
class CardCollectionsController < AppicationController
   def edit
       @card_collection = CardCollection.find params[:card_collection_id]
       @card_upload = @card_collectiom.new #-> might need to change
   end
end

#app/views/card_collections/edit.html.erb
<%= form_for @card_upload do |f| %>
    <%=  f.file_field :image %>
    <%=  f.submit %>
<% end %>

请记住,这是一个测试 - 所以我不会在生产中使用它;我只是想看看为什么你没有收到params

-

<强>属性

顺便说一下,我们使用attribute_names方法让我们Strong Params干:

def your_params
    parameters = Model.attribute_names - %w(id created_at updated_at)
    params.require(:parent).permit(parameters)
end

答案 1 :(得分:0)

在我的情况下,我必须添加MIME类型才能查看Rails中的所有参数。 Rails日志通过提醒我该请求以“ application / vnd.api + json”的形式来警告我。

我需要在config/initializers/mime_types.rb上添加以下行:

Mime::Type.register "application/vnd.api+json", :json

有关此问题,请参见https://github.com/rails/rails/issues/28564