Ruby哈希中神奇的Symbol
ruby 在 1.9.x
版本开始支持使用json方式
创建哈希(Hash),示例代码如下:
1 2 3 4 5 6 7 8
| user1 = {"name": 'Jhon', "age": 21}
user2 = {name: 'Jhon', age: 21}
user3 = {:name => 'Jhon', :age => 21}
|
#1 和 #2 中 user 的 Key(name 和 age)都默认是 Symbol
类型,而 #3 的 user 已经指定了 Key 类型是 Symbol
。
而在 ruby 1.9.x
之前的版本不可以使用冒号:
即类似#2方式语法创建,只能像下面这样创建 Hash:
1 2 3
| user1 = {"name" => 'Jhon', "age" => 21}
user2 = {:name => 'Jhon', :age => 21}
|
可以看出 Symbol
一直都存在,并且在新版本得到了“重用”。
当然了,最新的 ruby 版本也支持 1.9.x
之前 Hash 创建方式:
1
| user4 = {"name" => 'Jhon', "age" => 21}
|
这个创建 Hash 的方法,Key 是 String
类型而不是 Symbol
类型。
我现在用的是 ruby 2.7.x
版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
user1 = { "name": 'Jhon', "age": 21 } user1.each_key do |key| puts "user1 key 类型:#{key.class.to_s}" end
puts("--------------------天生我材必有用--------------------")
user2 = { name: 'Jhon', age: 21 } user2.each_key do |key| puts "user2 key 类型:#{key.class.to_s}" end
puts("-------------------不以物喜不以己悲-------------------")
user3 = { :name => 'Jhon', :age => 21 } user3.each_key do |key| puts "user3 key 类型:#{key.class.to_s}" end
puts("--------------------桃花依旧笑春风--------------------")
user4 = { "name" => 'Jhon', "age" => 21 } user4.each_key do |key| puts "user4 key 类型:#{key.class.to_s}" end
|
运行得到结果
user1 key 类型:Symbol
user1 key 类型:Symbol
——————–天生我材必有用——————–
user2 key 类型:Symbol
user2 key 类型:Symbol
——————-不以物喜不以己悲——————-
user3 key 类型:Symbol
user3 key 类型:Symbol
——————–桃花依旧笑春风——————–
user4 key 类型:String
user4 key 类型:String
看到这里,你可能会很疑惑:写这么多,你到底是遇到了什么问题?!
我们先做好情绪管理,书归正传。
情景是这样的,我要从数据库(MySQL)user 表中读取数据,将读取的数据实例化为 ruby 的 User 类。这里我没有采用任何 ORM 工具,纯手工打造。
ruby user.rb
代码片段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class User attr_accessor :id, :phone, :avatar, :age, :motto, :created_at, :updated_at
def initialize(attributes = {}) @id = attributes[:id] @phone = attributes[:phone] @avatar = attributes[:avatar] @age = attributes[:age] @motto = attributes[:motto] @created_at = attributes[:created_at] @updated_at = attributes[:updated_at] end end
|
User 类的属性和数据库表 user 的字段保持一致。
db.ruby
代码片段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
require 'mysql2' require_relative '../model/user'
begin client = Mysql2::Client.new( host: 'localhost', username: 'root', password: "", database: "db" )
result = client.query("select * from user where id=1") result.each do |row| puts "query form table #{row}" end
user_record = result.first
user = User.new(user_record)
puts "user phone is: #{user.phone}"
ensure client.close if client end
|
结果有点出乎意料,实例化的 user 各个属性居然为空。百思不得骑jie……
开始调试,我用的是 RubyMine 进行开发的,会让你安装 ruby-debug-ide
、debase
,直接安装就可以了。
真相就要大白了,我加个打印,各位看官就明白了。
1 2 3 4
| user_record = result.first user_record.each_key do |key| puts "user_record key 类型: #{key.class.to_s}" end
|
打印结果清一色是 String
,而在 User 构造方法中的 Key 都是 Symbol
类型,明显类型不一致,所以实例化失败,导致 user 各个属性字段就为空了🤕。
解决方法很简单,从 MySQL 查询出来的 Hash 数据的 Key 类型(String)转换为 Symbol
即可,有两个常用的方法可以进行转换:
1 2 3 4 5 6 7 8 9 10
| user_hash = user_record.transform_keys(&:to_sym)
user_hash = user_record.each_with_object({}) do |(column, value), hash| hash[column.to_sym] = value end
user = User.new(user_hash)
|
至此,问题解决。
附上来自 AI 的解答:
使用 mysql2
查询 MySQL 数据库时,默认得到的哈希键是字符串类型,这是出于对不同数据库类型和查询结果灵活性的考虑。如果需要,您可以在处理查询结果时将这些字符串键转换为你需要的类型。
Ruby 是一门简单上手的编程语言,小巧可爱,有需要就去看看吧。顺便推一下自己的 Ruby on Rails 笔记:点此处直接飞往✈️。