Rails概括了使用模型的方法

时间:2013-08-13 14:33:13

标签: ruby-on-rails

我试图概括一些将由多个模型/视图/控制器使用的方法,但我没有运气。这是原始代码,只适用于1套名为Trucks。

查看

<h2>Trucks</h2>
  <%= form_tag trucks_path, :method => 'get' do %>
  <%= hidden_field_tag :direction, params[:direction] %>
  <%= hidden_field_tag :sort, params[:sort] %>
  <p>
    Search: 
    <%= text_field_tag :search %>
    by 
    <%= select_tag :search_column, options_for_select(Truck.translated_searchable_columns(['attribute1']), params[:search_column]) %>
    <%= submit_tag "Search" %>
  </p>
<% end %>

<!-- Display code goes here, but im not showing since its just a table -->

控制器

    def index
    @trucks = Truck.search(params[:search], params[:search_column]).order(sort_column(Truck, "truck_no") + " " + sort_direction)

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @trucks }
    end
  end

模型

  class Truck < ActiveRecord::Base
  attr_accessible :attribute1, :attribute2, :attribute3

  def self.search(keyword, column_name)
    if self.column_names.include?(column_name.to_s)
      where("trucks.#{column_name} LIKE ?", "%#{keyword}%")
    else
      scoped
    end
  end

  def self.searchable_columns(unwanted_columns)
    self.column_names.reject{ |column| unwanted_columns.include?(column) }
  end

  def self.translated_searchable_columns(unwanted_columns)
    columns = self.searchable_columns(unwanted_columns)
    result = columns.map{ |column| [Truck.human_attribute_name(column.to_sym), column] }
    result
  end
end

所有这一切顺利进行,现在我无法弄清楚我的生活如何将这些方法移动到lib并让它们一般化,以便让我们说预告片能够以相同的方法调用并传入其中信息并取得同样的结果。我想尽可能使代码DRY。谁能解释一下我需要做些什么才能实现这个目标? lib如何访问数据库?

1 个答案:

答案 0 :(得分:3)

您正在寻找的概念被称为“关注”。 Rails有一个便利模块,用于实现名为ActiveSupport::Concern的问题。以下是您可以提取模型方法的方法:

module Searchable
  extend ActiveSupport::Concern

  module ClassMethods
    def search(keyword, column_name)
      if column_names.include?(column_name.to_s)
        where("#{table_name}.#{column_name} LIKE ?", "%#{keyword}%")
      else
        scoped
      end
    end

    def searchable_columns(unwanted_columns)
      column_names.reject{ |column| unwanted_columns.include?(column) }
    end

    def translated_searchable_columns(unwanted_columns)
      columns = searchable_columns(unwanted_columns)
      columns.map{ |column| [human_attribute_name(column.to_sym), column] }
    end
  end
end

然后在你的模型中:

class Truck < ActiveRecord::Base
  include Searchable
  attr_accessible :attribute1, :attribute2, :attribute3
end

至于你应该在哪里存储Searchable模块,这取决于你 - 它必须是config.autoload_paths中包含的某个地方,就像模型或控制器一样。 Rails 4引入了一个约定,模型关注点存储在app/models/concerns中,控制器问题存储在app/controllers/concerns中,但除了默认自动加载之外,这些位置没有什么特别之处。