【问题标题】:Sinatra matches params[:id] as string type, additional conversion needed to match the database id?Sinatra 将 params[:id] 匹配为字符串类型,需要额外转换才能匹配数据库 id?
【发布时间】:2013-04-30 15:56:02
【问题描述】:

我正在使用 sinatra 和 DataMapper 来访问 sqlite3 数据库。拨打get(params[:id]) 时,我总是收到nil。但是当我拨打get(params[:id].to_i) 时,我可以获得正确的记录。有什么问题需要我明确地进行转换吗?

sinatra 应用程序很简单:

class Record
  include DataMapper::Resource
  property :id, Serial
  ....
end

get '/list/:id' do
  r = Record.get(params[:id])
  ...
end

【问题讨论】:

标签: ruby sinatra datamapper


【解决方案1】:

显然这是 Datamapper 的一个问题(如果您认为它应该将字符串转换为 id 的数字),但 Sinatra 可以通过一些方法来缓解它。当参数进来时你需要检查:

  • 它们存在。
  • 它们是正确的类型(或可铸造的)。
  • 它们在要求或预期的值范围内。

例如:

get '/list/:id' do
  r = Record.get(params[:id].to_i)
  # more code…


curl http://example.org/list/ddd

这样不行,最好检查并返回错误信息:

get '/list/:id' do |id| # the block syntax is helpful here
  halt 400, "Supply an I.D. *number*" unless id =~ /\d+/

然后是consider whether you want a default valuewhether the value is in the right range 等。在获取 ID 时,我倾向于使用 the regex syntax for routes,因为它也不会跟随子路由被吞噬,同时提供一些简单的类型检查:

get %r{/list/(\d+)} do |id|

助手在这种情况下也很有用:

helpers do
  # it's not required to take an argument,
  # the params helper is accessible inside other helpers
  # it's but easier to test, and (perhaps) philosophically better.
  def id( ps ) 
    if ps[:id]
      ps[:id].to_i
    else
      # raise an error, halt, or redirect, or whatever!
    end
  end
end

get '/list/:id' do
  r = Record.get id(params)

【讨论】:

  • 嗨@iain,我完全同意手动转换to_i 绝不是一个好主意。我没有过多考虑 params[:id] 的隐式转换,这是一个很好的话题,我会研究一下其他框架如何处理您上面提到的三点。感谢helper 的良好实践!
【解决方案2】:

为了澄清,@mbj 在原始问题中的评论是正确的。这是 Ruby 2.0 的 dm-core 中的一个错误。它适用于 ruby​​ 1.9。您可能使用 dm-core 版本 1.2 并且需要 1.2.1,您可以通过运行“gem update dm-core”来获得。

【讨论】:

    猜你喜欢
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多