对HABTM关系中的对象使用collection_select视图助手

时间:2009-02-20 16:12:02

标签: ruby-on-rails

模型项目类别处于has_and_belongs_to_many关系中。以下部分内容用于不同视图,以显示包含所有可用类别的下拉菜单。下拉菜单下方列表中的项目将根据用户在下拉菜单中的选择显示。

除了其他类别,每个项目都有一个名为“Everything”的类别。它也是category-db-table中的第一个条目,因为它在将迁移加载到数据库时插入了。

现在没有错误,但无论我选择哪个类别,它都会重新加载显示“Everything”类别的页面。

知道我需要在下面提到的代码中进行哪些更改才能使其按照我想要的方式工作?谢谢你的帮助!

部分带下拉菜单和项目列表

<!-- category dropdown -->
<% form_for category_url(:id), :html => {:method => :get} do |f| %>
    <label>Categories</label>
     <%= f.collection_select(:category_ids , Category.find(:all), :id , :name) %>
     <%= f.submit "Show" %>
<% end %>

<!-- project list -->
<ul class="projectlist">
  <% @projects.each do |_project| %>
    <li>
      <%= link_to(_project.name, _project) %>
    </li>
  <% end %>
</ul>

在下拉菜单中选择ID为2的类别后退出输出

Processing ProjectsController#index (for 127.0.0.1 at 2009-02-20 17:26:10) [GET]
  Parameters: {"commit"=>"Show", "http://localhost:3000/categories/id"=>{"category_ids"=>"2"}}

类别模型

class Category < ActiveRecord::Base
  has_and_belongs_to_many :projects, :join_table => "categories_projects"
end

类别控制器

class CategoriesController < ApplicationController
  def show
    @projects = Category.find(params[:id]).projects.find(:all)

    respond_to do |format|
      format.html # show.html.erb
    end
  end
end

项目模型

class Project < ActiveRecord::Base
  has_and_belongs_to_many :categories, :join_table => "categories_projects"
end

项目控制器

class ProjectsController < ApplicationController
  def show
    @projects = Project.find(:all)
    @project = Project.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
    end
  end

  def index
    @projects = Project.find(:all)

    respond_to do |format|
      format.html # index.html.erb
    end
  end
end

'rake routes'输出的一部分

category GET    /categories/:id  {:controller=>"categories", :action=>"show"}

2 个答案:

答案 0 :(得分:0)

您正在传递一个名为:category_ids的参数,但您无法在任何地方访问该参数。

form_for category_url(:id)

这会将您的表单提交到路径/categories/1或您当前正在查看的任何ID。然后,您使用 :id来查找您的类别项目:

@projects = Category.find(params[:id]).projects.find(:all)

所以你只是再次展示相同的那些。因为它是一个表单,所以您使用:category_ids参数提交查询:

POST /categories/1?category_ids=2

您只需更改Category.find即可使用其他参数。但是,通常要查看类别2,您只需使用网址/categories/2,其中2是您的:id参数。您在该路径中有两个ID,您应该决定如何解决该问题。

一种方法是使用categories_path进行表单操作,并将collection_select:category_ids参数更改为:id

/categories?id=2  # from the form
/categories/2     # from a link

但如果您只是列出项目,我会将此逻辑移到项目控制器(索引操作)中,因此您的网址将如下所示:

/projects?category_id=2` # from the form
/categories/2/projects   # from a link

答案 1 :(得分:0)

谢谢安德鲁,但我这样解决了这个问题:

我摆脱了 collection_select ,更改为选择,添加了filter-action(在config / routes.rb中的相应路由),现在一切正常预期。

...我正在尝试在选择菜单上找到一个观察者,一旦用户更改了选择菜单中的选择,就会将其值提交给过滤器操作,但这是另一个故事。 ; - )

包含下拉菜单和项目列表的新部分

    <% form_tag(filter_category_path(:id), :method => :post, :class => 'categories') do %>
       <label>Categories</label>
       <%= select_tag(:category, options_for_select(Category.all.map {|category| [category.name, category.id]}, @category.id)) %>
       <%= submit_tag "Go" %>
     <% end %>

   <ul class="projects">
     <% @projects.each do |_project| %>
       <li>
         <%= link_to(_project.name, _project) %>
       </li>
     <% end %>
   </ul>

新类别控制器

class CategoriesController < ApplicationController
  def show
    @category = Category.find(params[:id])
    @projects = @category.projects.find(:all)

    respond_to do |format|
      format.html 
    end
  end

  def filter
    @category = Category.find(params[:category])
    @projects = @category.projects.find(:all)

    respond_to do |format|
      format.html
    end    
  end
end