在不丢失数据的情况下重新显示 Sinatra 应用程序中的表单

Redisplay a form in a Sinatra application without loosing the data

我正在尝试在验证失败后重新显示表单而不丢失数据。

型号:

class Book < Sequel::Model
    plugin :validation_helpers
    
    def validate
        super
        validates_presence [:title], message: 'Title is required'
    end

end

create.erb:

...
<%= erb :'partials/flash' %>
...

<form method="post" action="/books/create">
    <input name="book[title]" type="text" value="<%= @book.title %>" />
    <textarea name="book[description]"><%= @book.description%></textarea>
    ...
</form>
...

flash.erb:

<% flash.map do |f| %>

<div class="alert alert-<%= f[0] %> alert-dismissible fade show" role="alert">
    <%= f[1] %>
    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
        <span aria-hidden="true">&times;</span>
    </button>
</div>

<% end %>

BooksController:

# display a table of books
get '/' do
    @books = Book.all
    erb :'books/index'
end

# display CREATE form
get '/create' do
    @book = Book.new
    erb :'books/create'
end

# process CREATE form
post '/create' do

    begin

        @book = Book.create(params[:book])

        flash[:success] = "Book created."
        redirect to("/") # /books/

    rescue Sequel::ValidationFailed => e

        flash[:danger] = @book.errors
        redirect to "/create" # redisplay the form

    end

end

虽然这有效,但在表单中输入的数据丢失了。

使用最新条目重新显示表单的推荐方法是什么?

** 编辑 ** 添加了 Flash 模板

  • 不是在 post 救援部分中重定向,而是再次呈现创建表单模板,这将访问书籍实例和与之相关的错误
  • 在表单渲染后使用 books 实例显示创建表单模板中的错误如果你想使用 flash 那么你需要从 @book.errors 对象实例中获取错误消息或提取消息。

为了完整起见,最终代码:

控制器:

post '/create' do

    begin

        @book = Book.new(params[:book])
        @book.save

        flash[:success] = "Book created."
        redirect to("/")

    rescue Sequel::ValidationFailed => e
        erb :'books/create'

    rescue => e
        flash[:danger] = e.message
        erb :'books/create'

    end

end

表格(使用Bootstrap):

<form method="post" action="/books/create">
  <div class="form-group">
    <label for="inputTitle">Title</label>
    <input id="inputTitle" name="book[title]" type="text" class="form-control <%= 'is-invalid' if @book.errors[:title] %>" placeholder="Title" value="<%= @book.title %>">
    <%= erb :'partials/validation_errors', locals: {field: :title, errors: @book.errors} %>
  </div>
  ...
</form>

validation_errors.erb:

<% if locals[:errors].has_key?(locals[:field]) %>
<div class="invalid-feedback">
    <ul>
        <% locals[:errors][locals[:field]].each do |error| %>
        <li><%= error %></li>
        <% end %>
    </ul>
</div>
<% end %>