我正在使用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
答案 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