将值从视图传递到Controller而不使用查询字符串

时间:2015-03-15 14:41:20

标签: ruby-on-rails ruby ruby-on-rails-4

我正在使用index方法列出所有学生。现在我在索引中添加一个text_field_tag的搜索。我的功能正常,但搜索值在网址中显示为查询字符串。我不想要这个。

我的观看代码:

<p>
  <%= form_tag students_path, :method => 'get' do %>
    Find by name: <%= text_field_tag :search %>
    <%= submit_tag  "Search", :name => nil %>
  <% end %>
</p>

我的控制器代码是

  def index
    searchString = params[:search]
    if searchString
      @students = Student.where("LastName like ?", "%#{searchString}%").paginate(:page => params[:page])
    else
    @students = Student.paginate(:page => params[:page])
    end
  end

我目前的网址如下所示:

http://localhost:3000/students?utf8=%E2%9C%93&search=A

我只需要/students。请建议最佳做法

1 个答案:

答案 0 :(得分:3)

您需要使用POST请求而不是GET。为了实现这一目标,请更改您的form_tag

<%= form_tag students_path, :method => 'get' do %>

<%= form_tag students_path, :method => 'post' do %>

可能出现什么问题......

正如@carlosramireziii所提到的,回答这个问题,需要更多的工作(他是绝对正确的!),所以 - 有更新

<强> 1。自定义路线

如果您要自行配置路由,则继续执行此操作的方法之一是添加路由,以便正确接受您的请求。看一下 config / routes.rb

Rails.application.routes.draw do
  match '/students', controller: :students, action: :index, via: [:get, :post]

  # other definitions
end

这样的定义将为您创建以下路线:

students GET|POST /students(.:format)     students#index

这会使您的新POST请求很好地落入students#index,从而产生预期结果。 然而,如果您通过resources定义路线,则不是那么容易改变。这导致我们......

<强> 2。修改标准resources路线

如果学生的路线定义如下:

Rails.application.routes.draw do
  resources :students

  # other definitions
end

注册了以下路线:

    students GET    /students(.:format)          students#index
             POST   /students(.:format)          students#create
 new_student GET    /students/new(.:format)      students#new
edit_student GET    /students/:id/edit(.:format) students#edit
     student GET    /students/:id(.:format)      students#show
             PATCH  /students/:id(.:format)      students#update
             PUT    /students/:id(.:format)      students#update
             DELETE /students/:id(.:format)      students#destroy

这表明POST请求属于students#create。为了使其有效,您需要将create操作更改为:

class StudentsController < ApplicationController
  # code omitted

  def create
    if params.include?('search')
      @students = Student.where("LastName like ?", "%#{searchString}%").paginate(:page => params[:page])
      render :index
    else
      # your current code from create action
    end
  end
end

虽然这样可行但是不推荐这样做。 create动作现在做了两件事,这被认为是一种糟糕的模式(至少是难闻的气味),并且容易出错。

那么,我们能做什么?

search正确的方式

<强> 1。自定义search路线

定义自定义collection route

Rails.application.routes.draw do
  resources :students do
    collection do
      post :search
    end
  end

  # other definitions
end

注册以下路线:

search_students POST   /students/search(.:format)   students#search
       students GET    /students(.:format)          students#index
                POST   /students(.:format)          students#create
    new_student GET    /students/new(.:format)      students#new
   edit_student GET    /students/:id/edit(.:format) students#edit
        student GET    /students/:id(.:format)      students#show
                PATCH  /students/:id(.:format)      students#update
                PUT    /students/:id(.:format)      students#update
                DELETE /students/:id(.:format)      students#destroy

您需要更改form_tag,如下所示:

<%= form_tag search_students_path, :method => 'post' do %>

并将search操作添加到StudentsController

class StudentsController < ApplicationController
  # code omitted

  def search
    @students = Student.where("LastName like ?", "%#{searchString}%").paginate(:page => params[:page])
    # If you don't want to create separate template for `search`,
    # you can try  to reuse your `index` template with
    # render :index
  end
end

<强> 2。将students#index与在网址

中传递的参数一起使用

这种方法更多是REST-y,它可以将整个URL传递给其他人,因此另一个人能够看到完全相同的过滤结果,这对params来说是不可能的。隐藏在POST请求中。

我希望我已经涵盖了所有可能性。如果您有任何问题 - 我非常乐意回答!

祝你好运!