根据Flash文档,我应该能够通过Flash传递字符串、数组或散列。字符串和数组可以正常工作,但哈希不起作用。
这是我代码的精简版(但仍然失败(:
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
在散列的情况下,问题似乎出在赋值行上,键是存在的,但对于散列,method
和detail
总是为零。但当我在控制台中尝试相同的代码时,它工作得很好。。。
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
如果我理解正确的话,这是flash存储在会话中,会话对象作为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"}
但是,如果你故意在传递给flash的散列中复制密钥,则最后定义的密钥为";获胜";(在我有限的测试中,但这是有意义的,因为哈希很可能是按插入顺序迭代的(:
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