4

将 Datamapper 与 Sinatra 一起使用,保存文本属性非常容易:

DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/tailor.db")  
class Person  
  include DataMapper::Resource  
  property :id, Serial  
  property :name, String, :required => true
  property :height, String, :required => false
end  
DataMapper.finalize.auto_upgrade!

...

put '/:id/edit' do
  p = Person.get params[:id]
  p.name = params[:name]
  p.height = params[:height]
  p.save
end

和观点:

%form
  %input{:type => 'text', :name => 'name'}
  %input{:type => 'text', :name => 'height'}
  %input{:type => 'submit', :value => 'Save'}

有了:type => 'text'它是一件轻而易举的事。但是,我在尝试property :test, Boolean, :required => false使用复选框设置布尔值 ( ) 时遇到了麻烦。这个问题是相似的,但没有解决如何做一个简单的布尔值。

此外,设置不接受任何字符串的值的最简单方法是什么,而只是一组预定义的选项——无论是作为允许一个选择的选择,还是一组允许多个选择的单选按钮?

编辑:

我想出了复选框:

p.bool = !params[:bool].nil?

在视图中:

  %input{:type => 'checkbox', :name => 'bool', :value => "#{@bool}", :checked => @p.bool}
4

1 回答 1

5

当您使用 提交表单时checkbox,如果您未指定value表单,则默认为 string on。此外,如果未选中该复选框,则根本不会提交。所以结果是在你的处理程序中,params[:test](假设checkbox被命名test)要么nil是未选中,要么是字符串on

Datamapper 中的布尔属性期望被分配一个布尔值(truefalse),或者它会隐式转换的一小组值中的一个。on并且nil不在这些值中,因此当您尝试将值分配给 Datamapper 时,它将失败验证并且不保存:

...
p.test = 'on'
if !p.save
  p p.errors[:test]
end

产生:

["Test must be of type TrueClass"]

解决此问题的一种方法是检查您的处理程序并在分配给属性时将值显式转换为布尔值:

p.test = params[:test] == 'on' ? true : false

另一种技术是将valueHTML 复选框中的 设置为 Datamapper 将转换的值之一,以便您可以直接传递它。一个表单中可以有多个同名的控件,它们将按照它们在页面中出现的顺序提交。Sinatra 在创建哈希时只会使用最后一个params,因此如果您在复选框之前hidden添加与复选框同名的输入,则如果未选中,则该值将是隐藏输入的值。如果它被选中,它的值将覆盖隐藏输入的值。

%input{:type => 'hidden', :name => 'foo', :value => 'f'}
%input{:type => 'checkbox', :name => 'foo', :value => 't'}

现在params[:test]将是'f'或者't',,这两个 Datamapper 都会为您转换,所以您可以简单地做

p.test = params[:test]
于 2012-12-01T09:44:24.570 回答