簡體   English   中英

將ActiveRecord作用域作為filter_by字符串傳遞

[英]Passing in an ActiveRecord scope as a filter_by string

我的模型中有幾個范圍需要在管理面板中進行過濾。

periodical.rb

class Periodical < ActiveRecord::Base
  scope :archived_newspaper, where("category = 'Newspaper'").where("archived = ?", true)
  scope :current_magazine, where("category = 'Magazine'").where("archived = ?", false)
end

index.html.erb

Filter by: <a href="?filter_by=archived_newspaper">Archived Newspapers</a>
  <a href="?filter_by=current_magazine">Current Magazines</a>

如果有其他典型的東西,如分頁,搜索,排序等,你會如何實現控制器?

class PeriodicalController < ApplicationController
  def index
    @periodicals = Periodical.page(params[:page])
    @periodicals = @periodicals.order(params[:sort_by]) if !params[:sort_by].blank?
    # Scope here
  end
end

我不確定這是否是最佳解決方案,因為它肯定存在安全問題,但你可以這樣做:

class PeriodicalController < ApplicationController
  def index
    @periodicals = Periodical.page(params[:page])
    @periodicals = @periodicals.order(params[:sort_by]) unless params[:sort_by].blank?

    if params[:filter_by] and Periodical.respond_to?(params[:filter_by].to_sym)
      begin
        new_scope = Periodical.send(params[:filter_by].to_sym)
        new_scope = nil unless new_scope.is_a?(ActiveRecord::Relation)
      rescue ArgumentError
        new_scope = nil
      end
      @periodicals.merge(new_scope)
    end
  end
end

編輯:一些替代品:

1)將參數過濾到允許范圍列表(更好地保護Periodical模型免受編輯請求中的參數的人的攻擊):

filter_by = params[:filter_by].to_sym
if [:archived_magazine, :current_magazine].include?(filter_by)
  new_scope = Periodical.send(params[:filter_by].to_sym)
  @periodicals.merge(new_scope)  
end

2)使用案例/開關並對范圍進行硬編碼(更好的安全性,但不是很干)

new_scope = case params[:filter_by]
  when "archived_magazine"
    Periodical.archived_magazine
  when "current_magazine"
    Periodical.current_magazine
  else 
    nil
end
@periodicals.merge(new_scope)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM