使用:范围显示结果而不添加新操作

时间:2011-10-27 04:06:23

标签: ruby-on-rails view controller scope

我希望在我的rails 3.1 app中使用:scope,并且需要一些关于如何正确实现它们的方向。我知道你在模型中编写逻辑(以提取你需要的数据),但我的问题出现在接下来的步骤中。

例如:我有一块“信息”。每个“片段”都有一个主题和观众等。我想使用范围来显示给定主题或受众的所有“信息”,而无需在我的控制器中编写新操作。

基本上,我不确定如何在不在控制器中创建新操作然后仅使用典型的link_to链接到这些视图。我想使用我写的范围。

我正在寻找正确(最合适)的方法来完成这项工作。

提前感谢您提供任何帮助。

2 个答案:

答案 0 :(得分:1)

你甚至不需要这个范围。看看:

Piece.includes([:topic, :audience]).where(['`topics`.name = ?', 'Politics'])

使用Rails 3& Arel,大多数范围都是完全没必要的。

在视图中使用它而不创建新的控制器操作时,您可以使用传递给索引操作的参数来设置一些条件,以确定如何容纳请求。


例如:(这是粗略未经测试的示例,但 应该工作)

应用/控制器/ pieces_controller.rb:

class PieceController < ApplicationController

  def index
    case params[:find_by]
      when 'topic_name'
        @pieces = Piece.includes([:topic, :audience]).where(['`topics`.name = ?', params[:topic_name])
      when 'topic_id'
        @pieces = Piece.includes([:topic, :audience]).where(['`topics`.id = ?', params[:topic_id])
      else
        @pieces = Piece.all
    end

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @addressees }
    end
  end

  # ...
end

应用/视图/片/ index.html.erb:

<%= link_to 'Politics Pieces', :controller => 'pieces', :find_by => 'topic_name', :topic_name => 'Politics' %>

使用选择框和javascript的另一个例子:

应用/视图/片/ index.html.erb:

<%= select 'find_by', 'topic', find_by_topic_select_options %>

app / helpers / pieces_helper.rb:(在此处移动了link_to以获取可读性)

module PieceHelper
  def find_by_topic_select_options
    Topic.all.collect do |topic|
      url = url_for :controller => 'pieces', :find_by => 'topic_id', :topic_id => topic.id
      [topic.name, url]
    end
  end
end

公开/ Javascript角/ application.js中:

window.onload = (function (ev) {
  var find_by_topic_select = document.getElementById('find_by_topic');
  find_by_topic_select.onchange = (function (e) {
    var selected = this.options[this.selectedIndex];
    window.location = selected.value;
  });
});

而且,一个脚注,你没有link_to一个关联或数据结构。您链接到调用操作(呈现视图)的URL或路由,该操作适当地显示您的数据结构。我希望这能为你解决问题。

答案 1 :(得分:0)

我将如何做到这一点:

piece.rb

def self.scope_by_topic(topic_name)
  topic_name.present? ? includes(:topic).where(topic: {name: topic_name}) : self.scoped
end

def self.scope_by_audience(audience_name)
  topic_name.present? ? includes(:audience).where(audience: {name: audience_name}) : self.scoped
end

关于我在此使用的scoped方法: http://api.rubyonrails.org/classes/ActiveRecord/NamedScope/ClassMethods.html#method-i-scoped

在你pieces_controller.rb

def index
  @pieces = Piece.scope_by_topic(params[:topic_scope])
                 .scope_by_audience(params[:audience_scope]).all
  # render view here
end

在您看来,您可以使用以下帮助程序:

link_to "My piece of information", pieces_path(topic_scope: 'A topic', audience_scope: 'An audience')

网址如下:

http://www.example.com/pieces?topic_scope=A+topic&aucience_scope=An+audience