Rails - 如何使用form_tag搜索has_many_through关联?

时间:2016-05-11 20:42:45

标签: ruby-on-rails ruby

我正在创建一个搜索标签,用户可以在其中搜索具有特定类型的餐馆。我有3种型号:餐厅,类型和餐厅类型。由于一家餐馆可以有多种类型,我创建了一个RestaurantType关系表。

如何创建此类搜索标签?

我发现最接近这个问题的StackOverflow问题如下:novelty detection,但它并未涵盖我所需要的全部内容。也就是说,我对Rails还是一个新手,也许只需要一个更有指导性的答案。

restaurant.rb

has_many :types, :through => :restaurant_types

type.rb

has_many :restaurants, :through => :restaurant_types

restaurant_type.rb

belongs_to :restaurant
belongs_to :type

restaurants_controller.rb(索引操作)(我还按名称实施搜索,这是餐厅的属性)

@restaurants = Restaurant.joins(restaurant_type: :type).where 
    ("cast(type_id as text) LIKE ?", "%#{params[:type]}%")
@restaurants = @restaurants.where("restaurant_name LIKE ?", 
    "%#{params[:restaurant_name]}%").paginate(:page => params[:page], 
    :per_page => 8)

restaurants / index.html.erb (仅限搜索部分)

<%= form_tag(restaurants_path, :method => 'get') do %>
    <%= text_field_tag :restaurants_name, params[:restaurants_name], :placeholder => "Name" %>
    <%= select_tag :restaurant_type_id, options_for_select(Type.all.map{ |t| [t.type_name, t.id] }) %>
    <%= submit_tag "Search" %>
<% end %>

备注:

  1. 我添加了&#34; has_many ...:through =&gt; ...&#34;迁移后手动关联,并且在这种情况下不知道它们是否有效。
  2. 当我到达索引时出现以下错误:&#34;名为&#39; restaurant_type&#39;没有在餐厅&#34; 上找到,它指的是我索引页面的第三行。
  3. -

    看起来很麻烦,但解决了它

    restaurants_controller.rb

    def index
    
        @types = RestaurantType.where("type_id LIKE ?", "%#{params[:type_id]}%")
        array = []
        @types.each do |t|
            @restaurant = Restaurant.find(t.restaurant_id)
            array.push(@restaurant)
        end
        @restaurant = WillPaginate::Collection.create(1, 6, array.length) do |pager|
          pager.replace array
        end
    end
    

    restaurants / index.html.erb(form_tag的一部分)

    <%= select_tag :type_id, options_for_select(Type.all.map{ |t| [t.type_name, t.id] }) %>
    

    -

    另一种编辑 - 更好地与其他搜索参数结合使用

    if (params[:type_id].to_f > 0)
        array = []
        RestaurantType.where("type_id = #{ params[:type_id] } ").each do |t|
            array.push(t.school_id)
        end
        @restaurants = Restaurant.where("restaurant_name LIKE ? AND cast(city_id as text) LIKE ? AND id in (?)", "%#{ params[:restaurant_name] }%", 
           "%#{params[:city_id]}%", array).paginate(:page => params[:page], :per_page => 6)
    
    else
        @restaurants = Restaurant.where("restaurant_name LIKE ? AND cast(city_id as text) LIKE ?", "%#{params[:restaurant_name]}%", 
           "%#{params[:city_id]}%").paginate(:page => params[:page], :per_page => 6)
    end
    

2 个答案:

答案 0 :(得分:0)

我认为错误来自于restaurants_controller的加入:

@restaurants = Restaurant.joins(restaurant_type: :type).where("cast(type_id as text) LIKE ?", "%#{params[:type]}%")

您必须使用与模型中指定的完全相同的名称...在这种情况下,'restaurant_types'而不是'restaurant_type'。

但是,您已经在模型文件中创建了模型之间的关联,因此您不需要使用连接。你可以这样搜索:

@restaurants = Type.find(params[:restaurant_type_id]).restaurant.where('restaurant_name like ?', "%#{params[:restaurant_name]}%")

我会将type.rb中的关联更改为:

has_many :restaurants, :through => :restaurant_types

然后,从类型中查找餐馆的方法将是复数,更直观。

答案 1 :(得分:0)

我决定创建一个包含所选类型的所有餐厅的数组。该算法使用所选类型遍历每个对象(restaurant_type),将其推送到数组中,并在索引上对数组进行分页。

可能需要更长时间,但渐近分析表明T(n)乘以常数,这不是什么大不了的事。

感谢那位在这里回答分页数组的家伙:Paginating an Array in Ruby with Will_Paginate

<强> restaurants_controller.rb

def index

    @types = RestaurantType.where("type_id LIKE ?", "%#{params[:type_id]}%")
    array = []
    @types.each do |t|
        @restaurant = Restaurant.find(t.restaurant_id)
        array.push(@restaurant)
    end
    @restaurant = WillPaginate::Collection.create(1, 6, array.length) do |pager|
      pager.replace array
    end
end

restaurants / index.html.erb(form_tag的一部分)

<%= select_tag :type_id, options_for_select(Type.all.map{ |t| [t.type_name, t.id] }) %>

-

另一种编辑 - 更好地与其他搜索参数结合使用

if (params[:type_id].to_f > 0)
    array = []
    RestaurantType.where("type_id = #{ params[:type_id] } ").each do |t|
        array.push(t.school_id)
    end
    @restaurants = Restaurant.where("restaurant_name LIKE ? AND cast(city_id as text) LIKE ? AND id in (?)", "%#{ params[:restaurant_name] }%", 
       "%#{params[:city_id]}%", array).paginate(:page => params[:page], :per_page => 6)

else
    @restaurants = Restaurant.where("restaurant_name LIKE ? AND cast(city_id as text) LIKE ?", "%#{params[:restaurant_name]}%", 
       "%#{params[:city_id]}%").paginate(:page => params[:page], :per_page => 6)
end