How can I implement sunspot search when it's nested - ruby-on-rails

How can I extend my search?
I'd like to search User at users_controllers#index when user pressed search button.
Now I have 3 models.
User > User_profile > Prefecture
User_profile has these column such as user_id, and prefecture_id.
In Prefecture model, it has its id, and name (Exp: California, New York)
Now I have setup models/user.rb like this. If I want to add prefecture search, what should I add to this? User should be able to type in California, and it hits search.
searchable do
text :user_profile_nickname do
user_profile.nickname
end
text :user_profile_introduction do
user_profile.introduction
end
text :tag_list do
tag_list
end
end

Each user will be stored as a document in Solr and you need to give the prefacture information to the user document in order for it to be searchable.
Try:
searchable do
text :user_profile_nickname do
user_profile.nickname
end
text :user_profile_introduction do
user_profile.introduction
end
text :tag_list do
tag_list
end
string :prefacture do
user_profile.prefacture.name
end
end
I would use string instead of text since you don't need to apply text processing such as stemming on the prefacture. And with Sunspot I don't think it's possible to build facets on text fields.

Related

How to add a panel on index page in ActiveAdmin when index section has no result?

I'm using the ruby gem ActiveAdmin. On the index page, I want to show a few panels in addition to the index listing of records.
I have code like the following:
ActiveAdmin.register City do
belongs_to :country
index do
column :name
column :population
column :elevation
panel 'Languages in Country' do
ul do
country.languages.each do |language|
li language
end
end
end
end
end
The idea is when I go to http://localhost:8000/admin/countries/3/cities, I'll show a list of cities of the country, and below this table, I'll show the country's languages in a separate panel.
The problem I'm having is that when a country has no cities, the language panel is also NOT shown (even though it has languages).
How do I show the language panel when a country has no city data?
Thanks
Subclass and override ActiveAdmin::Views::IndexList, something like:
class IndexListWithCountryPanel < ActiveAdmin::Views::IndexList
def build(index_classes)
if current_filter_search_empty?
panel 'Languages in Country' do ... end
else
index_classes.each do |index_class|
build_index_list(index_class)
end
end
end
Register the customized index page with:
index as: IndexListWithCountryPanel do
... # as before
end
It would be more DRY to always display the panel in IndexListWithCountryPanel and not the index block. Have you considered adding the country languages to the sidebar instead? Disclaimer: this is based on my reading of the code and docs, I have not done this myself.

Create a custom string filter in ActiveAdmin that defaults to Contains and doesn't show a string filter choice drop down - Formtastic & Ransack

The default string filter in ActiveAdmin has a select the options of:
Contains
Equals
Starts with
Ends with
This shows a dropdown next to the string search where you are able to choose these options.
My requirement is to have the filter to use contains search condition BUT not show the drop down/select to do this. So it will just have an input box for search, with no select to choose contains.
I originally achieved this by creating a partial, but that was problematic as it was then unable to work with the other filters that ActiveAdmin provides. Here is an image of the partial:
My current thinking is to create a custom filter that does this.
So below is the standard code for the string filter in ActiveAdmin. How could this be modified to default to contains and not show the drop down? I've tried removing the filter options but that doesn't work. Any ideas?
ActiveAdmin uses Ransack and Formtastic
module ActiveAdmin
module Inputs
class FilterStringInput < ::Formtastic::Inputs::StringInput
include FilterBase
include FilterBase::SearchMethodSelect
filter :contains, :equals, :starts_with, :ends_with
# If the filter method includes a search condition, build a normal string search field.
# Else, build a search field with a companion dropdown to choose a search condition from.
def to_html
if seems_searchable?
input_wrapping do
label_html <<
builder.text_field(method, input_html_options)
end
else
super # SearchMethodSelect#to_html
end
end
end
end
end
To remove the need for a predicate drop down, you can use the Ransack's string-based query interface. For example, if you have an ActiveRecord User class with an attribute name and you want a containing filter on it, you could do something like:
ActiveAdmin.register User do
filter :name_cont, label: 'User name'
end
This will generate:
And it will search for Users containing the introduced input in its name
From your question I can conclude, that you are looking for to have a filter, that searches by :contains, and not having a drop down for other options (:equals, :starts_with, :ends_with).
If I do understand you right, you can simple use this (and not having to monkeypatch the ActiveAdmin):
filter :attribute_name, as: :string, label: 'Your custom label, if default doesn't fit'
As a bonus I can suggest you nice gem ('chosen-rails' I've discovered it today), which allows you to do autocomplete on filter (originally it is used to autocomplete the associated model in new/edit form, but I've easily adjusted it for my needs).
So for filters it is as easy as:
filter :title, as: :select, collection: -> {ClientApplication.all.map{|s| s.title}.uniq}, input_html: { class: 'chosen-input' } #or as you've shown before, using pluck :)
The only disadvantage, is that it works only if your string starts with the same letters, as the searched thing, e.g. if name is "Hello", it will hint you when you type "H", "He" and so on, but won't if you type "el", "llo" etc.
EDIT
Ok, The only thing you need to adjust the filtering of ActiveAdmin to your need is to change (comment the line responsible for adding dropdown) the to_html method in module [SearchMethodSelect][2]:
module Inputs
module FilterBase
module SearchMethodSelect
#other methods
def to_html
input_wrapping do
label_html << # your label
#select_html << # THIS LINE -- the dropdown that holds the available search methods
input_html # your input field
end
end
#other methods
end
end
end
I've test it out, and it still works as :contains, check it out :)

ActiveScaffold search a join table?

I have general field search in ActiveScaffold working. I'm not sure how to do this more complex searching.
I have two tables, Account and User, and I want to search emails and get back a list of matching accounts. The email field is in User, and Account has_many :users.
I am having trouble thinking through how the query should happen. Ideally I'd like to do something like this:
Account.where(email: 'search_term').all
or
User.where(email: 'search_term').includes(:account).all
If you want to search for data from one table and return results from(including) another, just add those foreign columns as virtual columns:
in User controller:
active_scaffold :user do |conf|
conf.search.columns << :email
conf.list.columns << :account
#...
end
That's it, no queries :)
if account column results appears code like <#23423.. it's because Active Scaffold can't tell how to describe that class records, so you tell it how you want in the model:
class Account << ActiveRecord::Base
....
def to_label
"cod: #{account_number}"
end

Ruby Sunspot Keyword search with IDs

Simple question:
I've got two models: Show and Contact. What I'd like to do is search for either a Show#id or a Contact#name. So my models are set up as follows:
class Show < ActiveRecord::Base
searchable do
text :id
end
end
class Contact < ActiveRecord::Base
searchable do
text :name
end
end
Then I run searches as follows:
Sunspot.search(Contact, Show) do
keywords(MY_QUERY)
end
This works great for finding Contacts by their name, but never works with the Show#id field. Can anyone explain why this is?
Joe
The id field is an integer, so you should have integer :id in the model. You need to specify the correct type of database column. Check out the example at http://sunspot.github.com/.

Displaying a column of associated names in ActiveAdmin

I have two models, Listing and Invitation, associated with has_and_belongs_to_many. I am looking at invitations through ActiveAdmin and would like to display the names of the associated listings. I attempt this with the following code:
ActiveAdmin.register Invitation do
index do
column("Listings") { |invitation| invitation.listings.each do |listing|
listing.name
end
}
default_actions
end
end
But nothing shows up. How can I get this to work?
I am assuming that you want a single column with all the listings names of the invitation. Please try the following
column 'listing' do |invitation|
invitation.listings.collect(&:name).join(', ')
end
You might want to customize this later on and add a includes(:listings) to increase db retrieval performance.

Resources