【问题标题】:Rails - How to use form_tag to search has_many_through associations?Rails - 如何使用 form_tag 搜索 has_many_through 关联?
【发布时间】:2016-05-11 20:42:44
【问题描述】:

我正在创建一个搜索选项卡,用户可以在其中搜索特定类型的餐厅。我有 3 个模型:Restaurant、Type 和 RestaurantType。由于一个餐厅可以有多种类型,我创建了一个 RestaurantType 关系表。

如何创建这样的搜索标签?

我发现最接近此问题的 StackOverflow 问题如下:ActiveRecord query through multiple joins,但它并没有涵盖我需要的所有内容。也就是说,我对 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(索引操作)(我也在实现按名称搜索,这是 Restaurant 的一个属性)

@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. 我在迁移后手动添加了“has_many ... :through => ...”关联,不知道在这种情况下它们是否算数。
  2. 当我到达索引时,我收到以下错误:“Association named 'restaurant_type' was not found on Restaurant”,它指的是我索引页面中的第三行。

-

看起来很糟糕,但解决了

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

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    我认为错误来自于 restaurant_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
    

    那么从一个类型中查找餐馆的方法将是复数,并且更直观。

    【讨论】:

    • "找不到带有 'id'="的类型
    【解决方案2】:

    我决定创建一个包含所选类型的所有餐厅的数组。该算法会遍历每个具有所选类型的对象 (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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-16
      • 1970-01-01
      • 1970-01-01
      • 2020-02-28
      • 1970-01-01
      • 2017-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多