如何在Rails控制器中解析API响应

时间:2017-02-01 21:47:21

标签: ruby-on-rails ruby ruby-on-rails-5

我正在开发集成Scale的API,并且无法在我的Rails控制器中解析响应。

从Scale发布到控制器的参数类似于:

Parameters: {"task"=>{"task_id"=>"589253a3b36b2d...1fe68", "created_at"=>"2017-02-01T21:31:15.607Z", "completed_at"=>"2017-02-01T21:31:15.612Z", "callback_url"=>"http://...", "type"=>"categorization", "status"=>"completed", "instruction"=>"Is this company public or private?", "params"=>{"allow_multiple"=>true, "categories"=>["NCI....

我的控制器方法:

 def create
   # check authorization
   callback = $scale.build_callback params, 'task', callback_key: request.headers['scale-callback-auth']

   response = callback.response # Response content hash (code and result)
   task = callback.task     # Scale::Resources::Task object


   return nil if ScaleWebhook.exists?(task_id: task.task_id)
   ScaleWebhook.create!(task_id: task.task_id, response: task.response)    
end

在控制台中,当我得到Scale::Resources::Task时,我可以执行task.task_id之类的操作。示例对象:

#<Scale::Resources::Task:0x007fad81573e70 @task_id="589252b2b36b2d060061fd19", @type="categorization", @instruction="Is this company public or private?", @params={"allow_multiple"=>false, "categories"=>["public", "private"], "attachment"=>"http://www.google.com/", "attachment_type"=>"website"}, @urgency="day", @response=nil, @callback_url="http://www.example.com/callback", @status="pending", @created_at=2017-02-01 21:27:14 UTC, @completed_at=nil> 

但是我的Rails控制器正在执行此操作:

ScaleWebhook Exists (0.8ms)  SELECT  1 AS one FROM "scale_webhooks" WHERE "scale_webhooks"."task_id" = $1 LIMIT $2  [["task_id", "#<ActionController::Parameters:0x007fd680575130>"], ["LIMIT", 1]]
  SQL (0.4ms)  INSERT INTO "scale_webhooks" ("task_id", "response", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["task_id", "#<ActionController::Parameters:0x007fd680575130>"], ["response", "#<ActionController::Parameters:0x007fd68058d578>"], ["created_at", 2017-02-01 21:31:15 UTC], ["updated_at", 2017-02-01 21:31:15 UTC]]

如您所见,它将#<ActionController::Parameters插入数据库,而不是值。我猜这与rails&#39;有关。强大的参数,但我尝试了几种允许的方式,甚至允许所有参数作为测试,我仍然无法访问#<ActionController::Parameters以外的任何内容。

我使用build_callback提供的scaleapi-ruby方法,因为它验证了从Scale发送的auth_key,但我想我真的不需要用它来解析进一步响应,如params['task_id']之类的作品。

更新: 看起来模型被设置为序列化所有参数,序列化关闭,我得到以下错误:

TypeError (can't cast ActionController::Parameters):
app/controllers/scale_api_controller.rb:13:in `create'

这是第13行:

return nil if ScaleWebhook.exists?(task_id: task.task_id)

在评论第13行时,我遇到的问题与#<ActionController::Parameters:0x007fd6815317b8>相似,而不是实际的任务ID。

更新2:

使用binding.pry,我得到了:

#<Scale::Resources::Task:0x007fd919aa1f78
 @callback_url=nil,
 @completed_at=nil,
 @created_at=nil,
 @instruction=nil,
 @params={},
 @response=<ActionController::Parameters {"category"=>["Blackish", "Sherlock"]} permitted: false>,
 @status=nil,
 @task_id=
  <ActionController::Parameters {"task"=>{"task_id"=>"58925f...00620894", "created_at"=>"2017-02-01T22:20:25.921Z", "completed_at"=>"2017-02-01T22:20:25.927Z", "callback_url"=>"...", "type"=>"categorization", "status"=>"completed", "instruction"=>"Is this company public or private?", "params"=>{"allow_multiple"=>true, "categories"=>["Arrow", "Last Man on Earth", "The Real O'Neals", "Blackish", "Sherlock", "Riverdale"], "attachment"=>"...", "attachment_type"=>"image"}, "is_test"=>true, "urgency"=>"day", "metadata"=>{"name"=>"...", "user_id"=>1}, "response"=>{"category"=>["Blackish", "Sherlock"]}}, "response"=>{"category"=>["Blackish", "Sherlock"]}, "task_id"=>"58925f29b36b2d0600620894", "controller"=>"scale_api", "action"=>"create", "scale_api"=>{"task"=>{"task_id"=>"58925f29.....600620894", "created_at"=>"2017-02-01T22:20:25.921Z", "completed_at"=>"2017-02-01T22:20:25.927Z", "callback_url"=>"...", "type"=>"categorization", "status"=>"completed", "instruction"=>"Is this company public or private?", "params"=>{"allow_multiple"=>true, "categories"=>["Arrow", "Last Man on Earth", "The Real O'Neals", "Blackish", "Sherlock", "Riverdale"], "attachment"=>"https://s3.amazonaws.com...", "attachment_type"=>"image"}, "is_test"=>true, "urgency"=>"day", "metadata"=>{"name"=>"...", "user_id"=>45}, "response"=>{"category"=>["Blackish", "Sherlock"]}}, "response"=>{"category"=>["Blackish", "Sherlock"]}, "task_id"=>"58925f29b...b2d0600620894"}} permitted: false>,
 @type=nil,
 @urgency=nil>

2 个答案:

答案 0 :(得分:1)

问题是ActionController :: Parameters意味着作为传递给ActiveRecord构建器方法的唯一数据。 (创建!,创建,新建等)当你说

ScaleWebhook.create!(task_id: task.task_id, response: task.response)`

您没有将ActionController :: Parameters对象传递给.create!。您正在传递一个常规哈希值,其中一个值恰好是ActionController :: Parameters的一个实例。由于该列设置为接受序列化数据,因此AR将该实例视为另一个要序列化的对象,并将其原始形式推送到列中。

你需要这样做才能使传递给.create!进行质量分配的唯一数据是task.response中的ActionController :: Parameters对象。您仍然可以在块中设置其他值。

此外,task.task_id似乎也返回了一个ActionController :: Parameters。您可能希望通过说task.task_id.require(:task).require(:task_id)

来提取任务ID(真实 task_id,&#34; 58925f ... 00620894&#34;数据)

总而言之,你可能想要这样的东西:

ScaleWebhook.create!(task.response) do |scale_web_hook|
  scale_web_hook.task_id = task.task_id.require(:task).require(:task_id)
end

此时,您可能会根据您的型号获得分配/质量分配错误。确保允许您允许的所有数据通过批量分配到您的模型上。

我不熟悉Scale API,但我建议稍微阅读一下文档。可能有一种更优雅的方式来访问task_id。

答案 1 :(得分:1)

问题是由于宝石中的错误引起的。有关详细信息,请参阅this issue

  

问题与Rails如何处理参数(ActionController::Parameters)以及此库如何管理它们(ActiveSupport::HashWithIndifferentAccess)之间的冲突有关。

     

此gem的先前版本错误地使用了Scale::to_hash中的ActiveSupport::HashWithIndifferentAccess构造函数。现在,通过对同一method进行一些检查来修复错误。

     

如果您无法更新gem(或不想更新),您可能希望使用scale.build_callback将哈希值传递给ActionController::Parameters#to_unsafe_hash

callback = $scale.build_callback params.to_unsafe_hash, 'task',
                                 callback_key: request.headers['scale-callback-auth']
相关问题