1

元の質問

私のアプリは「マシン」を扱います。マシンには仕様があり、多くの「スペック」と書かれています。これらの Spec にはそれぞれ、"Spec_Field" ("Weight"、"Height"、"Capacity" などのフィールド) への参照と値が含まれています。

Class Machine
  has_many :specs
  has_many :spec_fields, :through => :specs

Class Spec
  belongs_to :machine
  belongs_to :spec_field

私がやりたいことは、各マシンの #show アクションに検索機能を持たせることです。ユーザーは、一致させたい仕様をチェックします (「はい、長さ 50 が必要で、容量 500 は完璧です。幅は気にしない」)、「類似検索」をクリックすると、類似スペックを持つすべてのマシンが検索されます。

次のスクリーンキャストのような検索用のモデルが必要になると思います: http://railscasts.com/episodes/111-advanced-search-form-revised?autoplay=true

次に、マシンの #show アクションで、このマシンの Specs を確認し、それらを「検索」インスタンスに追加する必要があります。つまり、「仕様」も「検索」に属する必要があるということですか?

私の場合、すべてを整理する方法に頭を悩ませることはできません。どんな助けでも大歓迎です!

データベース スキーマ

マシン:

t.string   "title"
t.text     "description"
t.datetime "created_at",                      :null => false
t.datetime "updated_at",                      :null => false
t.string   "status"
t.integer  "category_id"
t.string   "manufacturer"
t.string   "model"
t.string   "serial"
t.string   "year"
t.string   "location"

仕様:

t.integer  "machine_id"
t.integer  "field_id"
t.text     "value"
t.float    "base_value"
t.integer  "unit_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false

仕様フィールド:

t.string  "label"
t.integer "base_units"

うまくいくように見える解決策

SQL「IN」と「SELECT」を使用する「With Spec」スコープを追加しました

 def self.with_spec(field_id,value)
    min_value = value.to_f * 0.8
    max_value = value.to_f * 1.2
    where("machines.id IN (SELECT machine_id FROM specs WHERE field_id = ? AND value > ? AND value < ?)",field_id,min_value,max_value)
  end
4

2 に答える 2

1

私は「フィルター スコープ」と呼んでいるものを構築します。適切な名前のキーを使用してハッシュを渡すと、結果セットが削減されます。渡されたものが nil または空白の場合、その条件は無視されます。

次に、すべてのフィルター検索を次のように組み合わせたクラス検索メソッドを定義します。

Class Spec
  belongs_to :machine
  belongs_to :spec_field

  # filter scopes 
  scope :with_machine,  lambda{|*term| where('machine_id = ?',term) if term.present? }
  scope :with_length,   lambda{|*term| where('length = ?',term)     if term.present? }
  scope :with_capacity, lambda{|*term| where('capacity = ?',term)   if term.present? }
  scope :with_width,    lambda{|*term| where('width = ?',term)      if term.present? }

  def self.filter_search(options)
    with_machine(  options[:machine]  ).
    with_length(   options[:length]   ).
    with_capacity( options[:capacity] ).
    with_width(    options[:width]    )
  end

end

必要なのは、適切な名前の入力を持つフォームを作成することだけです。

<%= text_field_tag 'search[machine]', @machine.id %>
<%= text_field_tag 'search[length]' %>
<%= text_field_tag 'search[capacity]' %>
<%= text_field_tag 'search[width]' %>
<%= submit_tag %>

そしてコントローラーで呼び出します:

@specs = Spec.filter_search(params[:search]).all

別の方法として、全文検索エンジンをセットアップし、ほぼ同じ方法で検索方法を構築することもできます。

于 2012-05-02T19:46:47.537 に答える
0

gem meta_searchが役立ち、コードを簡素化できると思います。

于 2012-05-02T21:19:32.280 に答える