问题
Right now in app/views/microposts/home.html.erb I have..
<% form_tag purchases_path, :method => 'get', :id => "products_search" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<% form_tag sales_path, :method => 'get', :id => "sales_search" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
and then in micropost.rb I have
scope :purchases, where(:kind => "purchase")
scope :sales, where(:kind => "sale")
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
and then finally in the microposts_controller.rb I have
def home
@microposts=Micropost.all
@purchases=@microposts.collect{ |m| m if m.kind == "purchase"}.compact
@sales=@microposts.collect{ |m| m if m.kind == "sale"}.compact
end
edit:
I also tried using
def home
@microposts=Micropost.all
@purchases=@microposts.purchases
@sales=@microposts.sales
end
instead but then it gives me the error undefined method `purchases' for #
Anways,
Right now with the .collect method I am getting an error saying undefined local variable or method `purchases_path' and it does the same for sales_path.
What I want is to have TWO search forms. In my micropost table I have a column called kind which can be either "purchase" or "sale". How can I change my code so that one search form searches through and displays results for only those microposts with the kind "purchase". And then the other searches through and displays results for only those microposts with the kind "sale"
回答1:
def home
@microposts = Micropost.all
@purchases = Micropost.search("purchase", params[:search])
@sales = Micropost.search("sale", params[:search])
end
def self.search(kind = nil, search = nil)
results = self.where(:kind => kind) if kind
results = self.where('name LIKE ?', "%#{search}%") if name
end
回答2:
Assuming Assuming '/microposts/home' if maped to MictropostsController#home app/views/microposts/home.html.erb
<%= form_tag('/microposts/home', :method => :get) do
<%= text_field_tag 'kind'%>
<%= submit_tag 'Search' %>
%>
/app/controllers/microposts_controller.rb
def home
kind = params[:kind]
if kind.present?
# if search parameter passed
@microposts = Micropost.where(:kind => kind)
else
# if search parameter not passed, list all micro post
@microposts = Micropost.all
end
end
回答3:
OK, so you have a sales_path and a purchases_path, so I'm going to assume they both lead to a controller with a sales and a purchases action
def sales
@search = params[:search]
@microposts = Micropost.search(@search).sales
end
def purchases
@search = params[:search]
@microposts = Micropost.search(@search).purchases
end
the Micropost.search
method will return a scope. So we'll call either #sales or #purhases on that scope which will append a condition onto the query.
UPDATE
It looks like you want to search for two different kinds of microposts from 1 form.
app/views/home/index.html.erb
<%= form_tag(root_path, :method => :get) do
<%= text_field_tag 'search'%>
<%= submit_tag 'Search' %>
%>
app/models/micropost.rb
scope :purchase_or_sale, where("kind IN ?", ["purchase", "sale"])
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
def purchase?
kind == "purchase"
end
def sale?
kind == "sale"
end
/app/controllers/home_controller.rb
def home
@microposts = Micropost.search(params[:search]).purchase_or_sale
@purchases = @microposts.select(&:purchase?)
@sales = @microposts.select(&:sale?)
end
UPDATE 2
OK, one more update.... Here's what I think you want now: 2 search forms, both the /microposts ... if I search on the sales form, it will show sales. if I search on the purchases form, it will search purchases.
your view:
<%= form_tag(microposts_path(kind: "purchases", :method => :get) do
<label for="search">Search Purchases:</label>
<%= text_field_tag 'search' %>
<%= submit_tag 'Search' %>
%>
<%= form_tag(microposts_path(kind: "sales", :method => :get) do
<label for="search">Search Sales:</label>
<%= text_field_tag 'search' %>
<%= submit_tag 'Search' %>
%>
Your controller:
def index
@microposts = Micropost.search(params[:search).for_kind(params[:kind])
end
Your model
def self.search(search_text)
if search_text
where('name LIKE ?', "%#{search_text}%")
else
scoped
end
end
scope :for_kind, lambda{|search_kind| where(kind: search_kind) }
回答4:
As per your comment on another response:
def home
@microposts = Micropost.scoped # so you can later apply any scope
if params[:purchases_search].present?
@microposts = @microposts.purchases.search(params[:purchases_search])
elsif params[:sales_search].present?
@microposts = @microposts.sales.search(params[:sales_search])
end
end
This assumes that the names of the two search fields are "purchases_search" and "sales_search".
回答5:
Why dont you split the microposts in two new models inheriting the micropost model?
class Micropost < ActiveRecord::Base
#do your general micropost magic here
end
Next:
class Purchase < Micropost
#do your purchase specific magic here
end
And:
class Sale < Micropost
#do your sale specific magic here
end
Your home action:
def home
@microposts = Micropost.all
@purchases = Purchase.all
@sales = Sale.all
end
If you need to search Purchases:
Purchase.where(:something => "great")
If you need to search Sales:
Sale.where(:something => "greater")
If you need to search both:
Micropost.where(:something => "the greatest")
** NOTE ** You need to add a column "type" to the microposts table for this to work, more information: Single table inheritance @ http://api.rubyonrails.org/classes/ActiveRecord/Base.html
来源:https://stackoverflow.com/questions/12575140/ror-how-can-i-search-only-microposts-with-a-specific-attribute