首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这个哈希被看作是字符串?

为什么这个哈希被看作是字符串?
EN

Stack Overflow用户
提问于 2018-08-14 11:17:55
回答 2查看 139关注 0票数 0

问题

当我调用Hash#merge函数时,我很难理解为什么我的Hash被当作字符串对待。调用以下代码时,我将收到一个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变量视为字符串而不是哈希。根据下面的消息来源,我看不出这是怎么回事。

来源

代码语言:javascript
复制
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输出以下内容:

代码语言:javascript
复制
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>"}
  • Ruby版本:2.3.1
  • Rails版本:5.1

日志

代码语言:javascript
复制
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'
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-14 12:16:44

哈希没有被视为字符串;您正在误读错误。

我不知道你的回溯是不是被什么东西突然截断了,或者你刚刚修改了重要的部分,但错误不是你想的那样。

您调用merge的事实与您的问题无关,即 method you are calling在其论点上调用了merge .它是作为to_json-built字符串传递的,而不是它所期望的哈希。

您需要删除调用中的.to_json

票数 6
EN

Stack Overflow用户

发布于 2018-08-14 12:31:05

对散列调用to_json会将其转换为字符串。

代码语言:javascript
复制
irb(main):001:0> { foo: 'bar' }.to_json.class
=> String

WHile签名是Aws::SNS::Topic#publish(options = {}) ⇒ Types::PublishResponse

所以你应该称它为:

代码语言:javascript
复制
topic.publish(
  subject: 'LAB_COMPLETE', 
  message: lab_attribs.merge(full_name: current_user.full_name).to_json
)

您可以通过使用活动作业和一些基本的哈希操作来清理整个混乱的示例:

代码语言:javascript
复制
# 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
代码语言:javascript
复制
# ...
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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51840178

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档