2017-02-01 22 views
1

我正在整合Scale的API,並且在解析Rails控制器中的響應時遇到了麻煩。如何解析Rails控制器中的API響應

從規模看像貼到控制器的PARAMS:

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到數據庫,而不是價值。我猜這與軌道的強大參數有關,但我嘗試了一些允許的變體,甚至允許所有參數作爲測試,並且我仍然無法訪問#<ActionController::Parameters以外的任何內容。

我使用由scaleapi-ruby提供的build_callback方法,因爲它證實了從規模送來的AUTH_KEY,但我想我並不真的需要用它來解析響應。此外,像下面的params['task_id']作品。

UPDATE: 它看起來像模型設定連載所有的參數,可以用序列化的時候,我得到以下錯誤:

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> 
+0

不是將整個'params'傳遞給API,只是將其過濾爲所需的屬性。即'params.select {| k,v |親屬? ['key1','key2']}' –

+0

@maxple我不清楚這將如何解決這個問題。我試圖解析來自API的響應,不向API傳遞任何東西,但似乎無法訪問任何響應 – Slick23

+0

你檢查使用'binding.pry'你的任務對象(Scale :: Resources: :任務)是否正常? –

回答

1

問題是由於寶石中的一個bug造成的。更多信息請參見this issue

The problem was related to a conflict between how Rails handles parameters (ActionController::Parameters) and how this library manages them (ActiveSupport::HashWithIndifferentAccess).

The previous version of this gem used wrongly the ActiveSupport::HashWithIndifferentAccess constructor in Scale::to_hash . Now, the bug is fixed with some checks on the same method .

If you can't update the gem (or don't want to), you may want to pass a hash instead to scale.build_callback by using ActionController::Parameters#to_unsafe_hash :

callback = $scale.build_callback params.to_unsafe_hash, 'task', 
           callback_key: request.headers['scale-callback-auth'] 
1

問題是ActionController的::參數是爲了工作,爲被傳遞給ActiveRecord的生成器方法的唯一數據。 (創造!創造,新等),當你說

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

你是不是傳遞一個的ActionController ::參數反對.create!。您正在傳遞一個常規散列,其中一個值恰好是ActionController :: Parameters的一個實例。由於該列設置爲接受序列化數據,因此AR將該實例看作是另一個要序列化的對象,並將其原始形式推送到列中。

您需要創建它,因此傳遞給.create!進行批量分配的唯一數據是task.response中的ActionController :: Parameters對象。您仍然可以在塊中設置其他值。

此外,task.task_id似乎也返回一個ActionController :: Parameters。你可能想通過說task.task_id.require(:task).require(:task_id)

所以在和拉任務的標識(真正 TASK_ID的「58925f ... 00620894」的數據)時,你可能想是這樣的:

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。

+0

這是一個封裝Scale API的gem,他們沒有Ruby SDK。我仍然'現在不能創建Singleton'實例的錯誤。我有權訪問params哈希值,我想我只是從那裏重建對象,而不是依賴創建者來做。 – Slick23

+0

這可能是最好的。最好的做法是在第三方apis和您的應用之間建立一個分離層。 – Glyoko