我强烈建议您研究 Ruby 的 ORM 之一,例如Sequel、DataMapper或Active Record。
它们将使您的生活变得更简单,通过使用自己的 DSL 抽象查询,让您专注于逻辑,并且它们会将字段的内容作为 Ruby 中的本机对象返回。没有更多像你看到的问题。
这些工具生成的 SQL 等同于您手动生成的 SQL;你必须努力让他们做错事,而且你很少能改进他们产生的东西。
此外,只需更改您的连接 DSN,您就可以切换到完全不同的数据库管理器,他们会感觉到架构差异,并为新环境生成优化的 SQL。尝试直接与 MySQL、PostgreSQL、Oracle 或 SQLite 驱动程序对话。
这是使用 Sequel 和 SQLite 的代码示例:
require 'sequel'
DB = Sequel.sqlite # memory database
DB.create_table :items do
primary_key :id
String :name
Integer :number
Float :price
end
items = DB[:items] # Create a dataset
# Populate the table
items.insert(:name => 'abc', :number => 1, :price => rand * 100)
items.insert(:name => 'def', :number => 3, :price => rand * 100)
items.insert(:name => 'ghi', :number => 7, :price => rand * 100)
# Print out the number of records
puts "Item count: #{ items.count }"
# Print out the values:
items.each do |i|
puts i
end
运行后返回:
Item count: 3
{:id=>1, :name=>"abc", :number=>1, :price=>48.3673258126733}
{:id=>2, :name=>"def", :number=>3, :price=>41.87676958348104}
{:id=>3, :name=>"ghi", :number=>7, :price=>62.54605297923891}
在循环中提取行:
items.each do |i|
puts i
end
每次循环i
都是一个散列,可以很容易地提取单个字段。再次运行代码:
>> item = items.first
{
:id => 1,
:name => "abc",
:number => 1,
:price => 70.81654554223003
}
>> item.class
Hash < Object
请注意,整数和浮点值是我们所期望的。(“价格”字段的值会有所不同,因为它们是随机的。)
对于 Rails,您会遇到 Active Record,因为它是 ORM。在 Rails 之外使用 Active Record 是可行的,但它是面向该框架的。我们在我的团队中广泛使用 Sequel 进行数据库交互。我的代码合作伙伴最近在大约一个小时内完成了从基于 MySQL 的数据库到 PostgreSQL 的完全转换,方法是更改连接字符串、运行我们设置的迁移并启动数据重新加载。他对它的简单性感到非常满意,尤其是因为他不必编写任何 SQL。
Sequel 带有一个基于 IRB 的命令行版本。您可以交互式地查询数据库、修改它们、查看和查看它们的内容。这也是查看将生成什么的好方法:
Your database is stored in DB...
Welcome to SEQUEL. You are using ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0]. Have fun ;)
>> require 'logger'
true
>> DB.loggers << Logger.new(STDOUT)
[
[0] #<Logger:0x007f7fe41dd880 @progname=nil, @level=0, @default_formatter=#<Logger::Formatter:0x007f7fe41dd858 @datetime_format=nil>, @formatter=nil, @logdev=#<Logger::LogDevice:0x007f7fe41dd808 @shift_size=nil, @shift_age=nil, @filename=nil, @dev=#<IO:<STDOUT>>, @mutex=#<Logger::LogDevice::LogDeviceMutex:0x007f7fe41dd7e0 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x007f7fe41dd790>>>>
]
>> DB.create_table :items do
> primary_key :id
| String :name
| Integer :number
| Float :price
| end
I, [2013-10-06T09:51:55.752052 #6721] INFO -- : CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT, name varchar(255), number integer, price double precision)
nil
>> items = DB[:items]
#<Sequel::Mock::Dataset: "SELECT * FROM items">
>> items.insert(:name => 'abc', :number => 1, :price => rand * 100)
I, [2013-10-06T09:52:15.421974 #6721] INFO -- : INSERT INTO items (name, number, price) VALUES ('abc', 1, 22.32640955200822)
nil
>> items.insert(:name => 'def', :number => 3, :price => rand * 100)
I, [2013-10-06T09:52:15.432649 #6721] INFO -- : INSERT INTO items (name, number, price) VALUES ('def', 3, 43.182983199793824)
nil
>> items.insert(:name => 'ghi', :number => 7, :price => rand * 100)
I, [2013-10-06T09:52:15.441312 #6721] INFO -- : INSERT INTO items (name, number, price) VALUES ('ghi', 7, 67.81054007143193)
nil
>> items.count
I, [2013-10-06T09:52:23.683121 #6721] INFO -- : SELECT count(*) AS count FROM items LIMIT 1
0