first, thank you for your help and support. after setup a simple search using scenic and textacular. i´ve tried to combine the results with a simple combination on the search controller. the search works very well but, if i search for tag, i got the
undefined method `username' for #Tag:0x0000
as i find out many solutions come with concatenating the query and the models are associated.
so in this case, the models are not associated. so someone can give a tip to how to combine separated models attrs in one query?
the model:
class Search < ApplicationRecord
extend Textacular
belongs_to :searchable, polymorphic: true
attr_accessor :query
def results
if @query.present?
self.class.search(@query).preload(:searchable).to_a.map!(&:searchable).uniq
else
Search.none
end
end
end
controller:
class SearchController < ApplicationController
respond_to :html
def index
@users = User.search(params[:search])
@tags = Tag.search(params[:search])
@search_results = @users + @tags
if params[:search].present?
@search_results = Search.new(query: params[:search]).results
else
@users = User.all
end
end
end
the view:
<div>
<% @search_results.each do |r| %>
<%= r.username %>
<%= r.name %>
<% end %>
</div>
In controller you have
@users = User.search(params[:search])
@tags = Tag.search(params[:search])
@search_results = @users + @tags
So, @users
are members of User
class and @tags
are member of Tag
class.
You are calling username
attribute on @search_results
, so you are doing it on @tags
.
The easy fix is to use two each cycle in view, one for @users
and one for @tags
.
<% @users.each do |user| %>
<%= user.username %>
<% end %>
And
<% @tags.each do |tag| %>
<%= tag.name %>
<% end %>
Another fix I think should work is to alias an attribute of Tag or User like here .
In your controller action, you are first assigning values to @users
and @search_results
and then simply overriding either one of them without using it. So, i moved the statements a bit to remove any unused assignment of values:
class SearchController < ApplicationController
def index
if params[:search].present?
@search_results = Search.new(query: params[:search]).results
else
@users = User.all
end
# Are you sure you still need to set `@users` and `@tags`? Reason: `@search_results` above would already be set if `params[:search]` was present.
@users ||= User.search(params[:search]) # Assigns only if @users is not previously set
@tags = Tag.search(params[:search])
@search_results ||= @users + @tags
end
end
Further improvement can be made if you are using only @search_results
in your view and NOT @users
and @tags
:
class SearchController < ApplicationController
def index
@search_results = if params[:search].present?
Search.new(query: params[:search]).results
else
User.all + Tag.all
end
end
end
And finally in your view:
<div>
<% @search_results.each do |r| %>
<% if r.respond_to?(:name) %>
<%= r.name %>
<% elsif r.respond_to?(:username) %>
<%= r.username %>
<% end %>
<% end %>
</div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.