简体   繁体   English

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

[英]Rails Parameters are not passed to 'params' variable

I'm making a application by using Rails 4. 我正在使用Rails 4进行应用程序。

Basically, I have two models, Card and CardCollection. 基本上,我有两个型号,Card和CardCollection。 CardCollections has_many Cards. CardCollections has_many卡。 I implemented this relationship with nested attributes. 我用嵌套属性实现了这种关系。

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

And form is like below. 形式如下。

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

When I put some data in the form and press the submit button, I can see that parameters are passing correctly to the server. 当我在表单中放入一些数据并按下提交按钮时,我可以看到参数正确传递给服务器。 (According to the server log) (根据服务器日志)

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"}

But when I really print 'params' variable in program code, params[:card_collection][:uploaded_cards_attributes] hash(nested attributes part) is suddenly missing. 但是当我在程序代码中真正打印'params'变量时,params [:card_collection] [:uploaded_cards_attributes] hash(嵌套属性部分)突然丢失。 So the printed params value is like below. 所以打印的params值如下所示。

"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

I don't know why this happen. 我不知道为什么会这样。 I think it doesn't have relationship with 'Strong Parameter' because problem is in the Rails-side parameter parsing part. 我认为它与'强参数'没有关系,因为问题出在Rails端参数解析部分。 (as I think) Please help me to find the exact problem and solution. (我认为)请帮我找到确切的问题和解决方案。

EDIT 编辑

this is my controller code 这是我的控制器代码

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

Solved Finally, I solved the problem thanks to @Rich Peck. 解决了最后,由于@Rich Peck,我解决了这个问题。 The real problem was about route part of Rails. 真正的问题是关于Rails的路由部分。 I was identifying specific record by two ways in one controller as you can see in 'set_card_collection' method. 我在一个控制器中通过两种方式识别特定记录,如'set_card_collection'方法中所示。

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

Original route.rb file was look like above. 原始route.rb文件看起来像上面。 I structured my route file (do not specify CardCollection id when user connect to upload page) like that to give flexibility to user choosing CardCollection dinamically in upload page. 我构建了我的路由文件(当用户连接上传页面时不指定CardCollection id),以便用户灵活地在上传页面中选择CardCollection。 But to connect edit page, user had to specify record id such as /card_collection/1/edit because it is Rails's default behavior. 但是要连接编辑页面,用户必须指定记录ID,例如/ card_collection / 1 / edit,因为它是Rails的默认行为。

Then I customized 'set_card_collection' method in the controller. 然后我在控制器中定制了'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])

Still, I don't know the EXACT cause, but using default :edit and :update route setting caused the problem that nested parameters would not be passed correctly. 尽管如此,我不知道确切原因,但使用默认值:编辑和:更新路由设置导致嵌套参数无法正确传递的问题。 So after I changed my route.rb file like below as unifying the way identifying a record, the problem was solved. 所以在我改变了我的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

There are a number of issues which could cause this 有许多问题可能导致这种情况

-- -

Error 错误

I see your system is correctly generating the uploaded_cards_attributes , which is the biggest hurdle to cross 我看到你的系统正在生成uploaded_cards_attributes ,这是跨越的最大障碍

This means the problem is either going to be with your strong params (which I doubt because the params hash is available in its entirety in your controller (it's the model where you want to restrict access); or how you're managing the params inside the controller 这意味着问题要么是你的strong params (我怀疑因为params哈希在你的控制器中完全可用(它是你想要限制访问的模型);或者你如何管理里面的params控制器

I don't know how to fix your problem, but it's likely not going to be a Rails issue 我不知道如何解决你的问题,但它可能不会成为Rails问题

-- -

Remedy 补救

I would initially look at how you're passing the params 我最初会看看你是如何通过参数的

Looks like you're using the edit / update method (by use of the PATCH verb). 看起来你正在使用edit / update方法(通过使用PATCH动词)。 This could be a problem, as Rails may not pass the data for an already-created object. 这可能是一个问题,因为Rails可能无法传递已创建对象的数据。

I would initially test using a new form - to see if you can create a new object with nested attributes. 我最初将使用new表单进行测试 - 以查看是否可以使用嵌套属性创建新对象。 If you can do this, I would then test using nested resources in your routes & edit the CardCollection object directly: 如果你可以这样做,我会测试你的路由中的nested resources并直接编辑CardCollection对象:

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

This will allow you to do something like: 这将允许您执行以下操作:

#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 %>

Bear in mind, that is a test - so I will not use that in production; 请记住,这是一个测试 - 所以我不会在生产中使用它; I just want to see why you're not receiving the params . 我只是想知道为什么你没有收到params

-- -

Attributes 属性

btw we use the attribute_names method to make our Strong Params dry: 顺便说一句,我们使用attribute_names方法使我们的Strong Params干:

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

In my case I had to add the MIME type in order to see all params in Rails. 在我的情况下,我必须添加MIME类型,以便在Rails中查看所有参数。 The Rails logs were kind of warning me about this by making me aware, that the request came in as "application/vnd.api+json". Rails日志通过让我意识到这个请求以“application / vnd.api + json”的形式出现来警告我。

I needed to add the following line to my config/initializers/mime_types.rb : 我需要config/initializers/mime_types.rb下行添加到我的config/initializers/mime_types.rb

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

See https://github.com/rails/rails/issues/28564 for this issue. 有关此问题,请参阅https://github.com/rails/rails/issues/28564

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM