为什么我不能访问散列的闪存内容?

Why can't I access contents of flash when it's a hash?

根据 Flash documentation,我应该能够通过 Flash 传递字符串、数组或散列。字符串和数组工作正常但散列不起作用。

这是我的代码的精简版(但仍然失败):

部分快讯

# views/layouts/flash_messages.html.haml

- flash.each do |type, content|
  - message = content if content.class == String
  - message, detail = content if content.class == Array
  - message, detail = content[:message], content[:detail] if content.class == Hash
  - if message || detail
    .alert
      %h3= message if message.present?
      %p= detail if detail.present?

家庭控制器

class HomeController < ApplicationController
  def index
  end

  def test_string
    redirect_to root_url, alert: 'Plain string works'
  end

  def test_array
    redirect_to root_url, alert: ['Array works', 'Tested with 0, 1, 2 or more items without problems']
  end

  def test_hash
    redirect_to root_url, alert: {message: 'Hash not working :(', detail: 'Even though I think it should'}
  end
end

在散列的情况下,问题似乎出在分配行上,键存在,但 methoddetail 对于散列总是以 nil 结尾。但是当我在控制台中尝试相同的代码时它工作正常...

IRB

irb> content = { message: 'This hash works...', detail: '...as expected' }
=> {:message=>"This hash works...", :detail=>"...as expected"}
irb> message, detail = content[:message], content[:detail] if content.class == Hash
=> [ 'This hash works...', '...as expected' ]
irb> message
=> 'This hash works...'
irb> detail
=> '...as expected'

仔细检查发现,虽然确实设置了键,但它们已从符号转换为字符串。

为了解决这个问题,我不得不将控制器的第 4 行从符号更改为字符串:

- message, detail = content[:message], content[:detail] if content.class == Hash
- message, detail = content['message'], content['detail'] if content.class == Hash

如果我 understand correctly,这是由于闪存存储在会话中并且会话对象作为 JSON 对象存储在 cookie 中的结果。 JSON 不支持符号化键。

作为实验,我尝试设置匹配的字符串和符号键。如果您尝试在一个作业中同时执行这两项操作,Ruby 将获取第一个键和第二个值(带有警告):

irb> content = { message: 'Symbol key first', 'message': 'String key second' }
=> warning: key :message is duplicated and overwritten on line X
=> {:message=>"String key second"}

但是如果你故意复制传递给闪存的散列中的键,最后定义的那个“获胜”(在我有限的测试中,但考虑到散列是 是有意义的):

symbol_first = {}
symbol_first[:message] = 'Symbol wins'
symbol_first['message'] = 'String wins'
flash[:alert] = symbol_first # 'String wins' is displayed

string_first = {}
string_first['message'] = 'String wins'
string_first[:message] = 'Symbol wins'
flash[:alert] = string_first # 'Symbol wins' is displayed