当我调用Hash#merge
函数时,我很难理解为什么我的哈希被视为字符串。调用以下代码时,我收到一个NoMethodError method 'merge' for #<String:0x000...
引发错误的代码行如下:topic.publish({subject: 'LAB_COMPLETE', message: lab_attribs.merge(full_name: current_user.full_name)}.to_json)
。出于某种原因,Ruby将lab_attribs
变量视为String而不是Hash。根据以下来源,我可能看不到这是怎么回事。
lab_attribs = {
name: create_params['lab_name'],
completed: DateTime.now,
duration: create_params['duration'],
final_grade: create_params['final_grade'],
cpe: create_params['cpe'],
user_id: create_params['user_id']
}
lab = Lab.new(lab_attribs)
if lab.save
logger.debug("lab_attribs class: #{lab_attribs.class}, lab_attribs value: #{lab_attribs}" )
sns = Aws::SNS::Resource.new
topic = sns.topic(Rails.application.secrets.lab_results_topic)
topic.publish({subject: 'LAB_COMPLETE', message: lab_attribs.merge(full_name: current_user.full_name)}.to_json)
render json: { lab_name: lab.name }
else
render json: { status: 422, errors: lab.errors }
end
logger.debug
输出以下内容:
lab_attribs class: Hash, lab_attribs value: {:name=>"Updating Firewall Rules", :completed=>Tue, 14 Aug 2018 11:36:01 +0000, :duration=>"1 minute", :final_grade=>"0", :cpe=>"0", :user_id=>"<snipped>"}
I, [2018-08-14T11:36:00.943514 #1930] INFO -- : [d9f4566a-5b25-4e07-ace3-06f301ecf0cb] Started POST "/api/v1/labs" for 172.68.65.103 at 2018-08-14 11:36:00 +0000
I, [2018-08-14T11:36:00.946228 #1930] INFO -- : [d9f4566a-5b25-4e07-ace3-06f301ecf0cb] Processing by Api::V1::LabsController#create as */*
I, [2018-08-14T11:36:00.946311 #1930] INFO -- : [d9f4566a-5b25-4e07-ace3-06f301ecf0cb] Parameters: {"lab"=>{"lab_name"=>"[FILTERED]", "task1"=>"Saved a local copy of the firewall rules", "score1"=>"0", "weight1"=>"50", "task2"=>"Blocked port 3600", "score2"=>"0", "weight2"=>"50", "final_grade"=>"0", "cpe"=>"0", "duration"=>"1 minute", "user_id"=>"<snipped>"}}
...<snipped DB calls>...
D, [2018-08-14T11:36:01.408369 #1930] DEBUG -- : [d9f4566a-5b25-4e07-ace3-06f301ecf0cb] lab_attribs class: Hash, lab_attribs value: {:name=>"Updating Firewall Rules", :completed=>Tue, 14 Aug 2018 11:36:01 +0000, :duration=>"1 minute", :final_grade=>"0", :cpe=>"0", :user_id=>"<snipped>"}
I, [2018-08-14T11:36:01.414112 #1930] INFO -- : [d9f4566a-5b25-4e07-ace3-06f301ecf0cb] Completed 500 Internal Server Error in 468ms (ActiveRecord: 26.7ms)
F, [2018-08-14T11:36:01.414612 #1930] FATAL -- : [d9f4566a-5b25-4e07-ace3-06f301ecf0cb]
F, [2018-08-14T11:36:01.414689 #1930] FATAL -- : [d9f4566a-5b25-4e07-ace3-06f301ecf0cb] NoMethodError (undefined method `merge' for #<String:0x0055e4df9d9558>):
F, [2018-08-14T11:36:01.414720 #1930] FATAL -- : [d9f4566a-5b25-4e07-ace3-06f301ecf0cb]
F, [2018-08-14T11:36:01.414758 #1930] FATAL -- : [d9f4566a-5b25-4e07-ace3-06f301ecf0cb] app/controllers/api/v1/labs_controller.rb:30:in `create'
答案 0 :(得分:6)
哈希没有被视为字符串;您误读了该错误。
我不确定您的回溯是否被某些东西意外地截断了,或者您只是编辑了重要部分,但是错误不在您认为的位置。
您正在呼叫merge
的事实与您的问题无关,这是因为the publish
method you are calling在其参数上调用merge
...您将以{{1} }构建的字符串,而不是预期的哈希值。
您需要删除通话中的to_json
。
答案 1 :(得分:1)
在哈希上调用to_json
会将其转换为字符串。
irb(main):001:0> { foo: 'bar' }.to_json.class
=> String
签名为Aws::SNS::Topic#publish(options = {}) ⇒ Types::PublishResponse
。
因此,您应该将其称为:
topic.publish(
subject: 'LAB_COMPLETE',
message: lab_attribs.merge(full_name: current_user.full_name).to_json
)
您可以使用Active Job和一些基本的哈希操作来清理整个凌乱的示例:
# app/jobs/publish_job.rb
class PublishJob < ApplicationJob
queue_as :default
def perform(**options)
sns = Aws::SNS::Resource.new
topic = sns.topic(Rails.application.secrets.lab_results_topic)
topic.publish(options)
end
end
# ...
def create
lab = Lab.new(lab_attributes)
if lab.save
PublishJob.perform_now(
subject: 'LAB_COMPLETE',
message: lab_attributes.merge(full_name: current_user.full_name).to_json
)
render json: { lab_name: lab.name }
else
render json: { status: 422, errors: lab.errors }
end
end
private
def lab_attributes
create_params.slice(:duration, :final_grade, :cpe, :user_id).merge(
completed: DateTime.now,
name: create_params[:lab_name]
)
end