How do I work with checkboxes with DataMapper and Sinatra?

≡放荡痞女 提交于 2019-12-08 13:29:36

问题


I'm trying to make a simple room management service. The rooms have these properties:

class Room
  include DataMapper::Resource
  validates_is_unique :number

  property :id, Serial
  property :number, Integer
  property :guest, String
  property :status, Enum[ :free, :occupied ], :default => :free
end

Then I create a new room like this

post '/new' do
  content_type :json
  @room = Room.new :guest => params[:guest],
                   :number => params[:number],
                   :status => params[:status]
  if @room.save
    { :number => @room.number, :guest => @room.guest, :status => @room.status }.to_json
  end
end

through this haml form

%form#new_message{:action => '/new', :method => 'post'}
        %p
          %input{:type => "text",      :id => "number", :name => "number"}
          %input{:type => "text",      :id => "guest",  :name => "guest"}
          %input{:type => "checkbox",  :id => "status", :name => "status", :value => "occupied"}
          %input{:type => "submit", :value => "post"}

When the box is checked the :status is "occupied" but when I leave it unchecked the object won't save. I thought it would work since it is defaulted to "free" but no...


回答1:


For whatever stupid reason, checkboxes do not get submitted if they are not clicked. This means they are not in the hash that hits your app. When you say :status => params[:status] you are really saying :status => nil. Since you have set a value, it checks that against your enum, and nil is not in your enum, so it fails validations. (based on how you are using this, doesn't it seem like it should be a boolean called either "occupied" or "available" ?)

Anyway, you could either explicitly set it to free, or not set it at all, and let the default take care of it. That is what I opted for when checking it, by moving it into a mass assignment. The code I used is below.

require 'rubygems'
require 'sinatra'
require 'haml'
require 'dm-core'
require 'dm-validations'
require 'dm-types'
require 'dm-migrations'
require 'sqlite3'


configure do
  class Room
    include DataMapper::Resource
    validates_uniqueness_of :number
    property :id, Serial
    property :number, Integer
    property :guest, String
    property :status, Enum[ :free, :occupied ], :default => :free
  end
  set :sessions , true
  DataMapper::Logger.new($stdout, :debug)
  DataMapper.setup( :default , "sqlite3://#{Dir.pwd}/development.sqlite3" )  
  DataMapper.finalize
  DataMapper.auto_upgrade!
end


get '/' do
  @rooms = Room.all
  haml :index
end

post '/new' do
  p params
  @room = Room.new params[:room]
  if @room.save
    session[:flash] = "room reserved"
    redirect '/'
  else
    session[:flash] = @room.errors.to_a
    redirect '/new'
  end
end

get '/new' do
  haml :new
end

__END__
@@layout
!!!
%html
  #flash
    = session[:flash].inspect
  = yield

@@new
%form#new_message{:action => '/new', :method => 'post' , :name => 'room' }
  %p
    %input{:type => "text",      :id => "number", :name => "room[number]"}
    %input{:type => "text",      :id => "guest",  :name => "room[guest]"}
    %input{:type => "checkbox",  :id => "status", :name => "room[status]", :value => "occupied"}
    %input{:type => "submit", :value => "post"}

@@index
%table
  - @rooms.each do |room|
    %tr
      %td= room.number
      %td= room.guest
      %td= room.status



回答2:


View the HTML source of your web-form! There should be a hidden field which sets the unchecked checkboxes to '0' as the default , in case nobody checks them...

see also: http://railscasts.com/episodes/17-habtm-checkboxes?autoplay=true (towards the end)



来源:https://stackoverflow.com/questions/3176367/how-do-i-work-with-checkboxes-with-datamapper-and-sinatra

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!