为什么我的rails控制器回滚我的ajax提交?

时间:2014-07-07 13:52:17

标签: ruby-on-rails

我遇到一个神秘的问题,控制器接收我的ajax请求但没有将其保存在数据库中。在我的服务器日志中,我看到:

Started POST "/collection_maps" for 127.0.0.1 at 2014-07-07 07:14:04 -0600
Processing by CollectionMapsController#create as */*
  Parameters: {"collection_id"=>"2", "manufacturer_id"=>"1", "package_id"=>"14"}
   (0.1ms)  begin transaction
   (0.1ms)  rollback transaction
  Rendered collection_maps/create.js.erb (1.9ms)
Completed 200 OK in 19.2ms (Views: 4.8ms | ActiveRecord: 0.2ms)
127.0.0.1 - - [07/Jul/2014 07:14:04] "POST /collection_maps HTTP/1.1" 200 - 0.0627

我在create.js.erb文件中在浏览器中收到的响应表明参数为空 - 但正如您在上面所看到的那样,它们显然在那里。 (响应仅以文本形式出现,浏览器不会执行代码,但这是另一个问题。我认为。)

// Create a list of errors
var errors = $('<ul />');

errors.append('<li>Package can\&#x27;t be blank</li>');
errors.append('<li>Manufacturer can\&#x27;t be blank</li>');
errors.append('<li>Collection can\&#x27;t be blank</li>');

// Display errors on form
$("#collection-response").html(errors).show();

当我尝试在控制台中创建记录时,使用相同的参数,它可以工作:

irb(main):006:0> c = CollectionMap.new("collection_id"=>"2", "manufacturer_id"=>"1", "package_id"=>"12")
=> #<CollectionMap id: nil, package_id: 12, manufacturer_id: 1, collection_id: 2, created_at: nil, updated_at: nil>
irb(main):007:0> c.save
   (0.1ms)  begin transaction
  SQL (5.7ms)  INSERT INTO "collection_maps" ("collection_id", "created_at", "package_id", "manufacturer_id", "updated_at") VALUES (?, ?, ?, ?, ?)  [["collection_id", 2], ["created_at", Mon, 07 Jul 2014 06:38:47 UTC +00:00], ["package_id", 12], ["manufacturer_id", 1], ["updated_at", Mon, 07 Jul 2014 06:38:47 UTC +00:00]]
   (1.2ms)  commit transaction
=> true
irb(main):008:0> c
=> #<CollectionMap id: 6, package_id: 12, manufacturer_id: 1, collection_id: 2, created_at: "2014-07-07 06:38:47", updated_at: "2014-07-07 06:38:47">

我想也许它与CRSF保护有关(虽然我没有用户会话)所以我添加了skip_filter。这是我的控制器代码:

class CollectionMapsController < ApplicationController
  respond_to :js, :html
  skip_before_filter :verify_authenticity_token
  # POST /collection_maps
  # POST /collection_maps.xml
  def create
    @collection_map = CollectionMap.new(params[:collection_map])
    flash[:notice] = "Collection map successfully added" if @collection_map.save
    respond_with( @collection_map,  :layout => !request.xhr?)
  end

这是我的ajax代码:

$.ajax({ url: '<%="#{collection_maps_path}"%>',
         type: 'POST',
         beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token',
                                                         '<%="#{form_authenticity_token}"%>')},
         dataType: "js",
         data: {'collection_id' : this.value, 
                'manufacturer_id' : $("#remedy_manufacturer_id option:selected").val(),
                'package_id' : $("#remedy_package_id option:selected").val()},
       });

最后,我的模特:

class CollectionMap < ActiveRecord::Base
  belongs_to :manufacturer
  belongs_to :package
  belongs_to :collection
  validates_presence_of :package_id, :manufacturer_id, :collection_id
  attr_protected :created_at
  attr_protected :updated_at
  attr_accessible :package_id, :manufacturer_id, :collection_id
end

我感到非常困惑,所以非常感谢帮助。

更新:我的浏览器没有执行控制器返回的javascript的原因是因为我在ajax请求中有dataType: "js"。应该是dataType: "script"。剪切和粘贴的地方要小心!

2 个答案:

答案 0 :(得分:2)

您的AJAX请求正在发回您需要的三个参数,但您的控制器操作正在寻找嵌套在:collection_map键下方的参数。您可以将控制器更改为:

def create
    @collection_map = CollectionMap.new(params)
    flash[:notice] = "Collection map successfully added" if @collection_map.save
    respond_with( @collection_map,  :layout => !request.xhr?)
end

或者将您的AJAX请求更改为:

$.ajax({ url: '<%="#{collection_maps_path}"%>',
         type: 'POST',
         beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token',
                                                         '<%="#{form_authenticity_token}"%>')},
         dataType: "js",
         data: {'collection_map': {'collection_id' : this.value, 
                'manufacturer_id' : $("#remedy_manufacturer_id option:selected").val(),
                'package_id' : $("#remedy_package_id option:selected").val()}},
       });

更改AJAX请求可能更可取;将参数嵌套在单个键下方更多&#34; Rails-like&#34; / idiomatic。

答案 1 :(得分:1)

您还在混合attr_accessibleattr_protected。选一个。或者,如果这是一个较新的Rails(4.0 +)项目,请使用新的params方法,在CollectioMapsController中为'protection'创建一个类似'collection_map_params'的方法。