Sunspot returning empty results - ruby-on-rails

I am using Sunspot for search and my queries aren't returning any results. I am using an API to do the search.
Here is some relevant code:
class App < ActiveRecord::Base
searchable do
text :name, :boost => 5
text :description
end
end
Controller:
module Api
module V1
class AppsController < ApiBaseController
respond_to :json
class App < ::App
end
def index
#search = App.search do
fulltext params[:search]
end
#apps = #search.results
respond_with #apps
end
end
end
end
The URL I normally use to access the index method in the AppsController without searching is http://0.0.0.0:3000/api/apps
When trying to search, I use http://0.0.0.0:3000/api/apps?search=test
Is my search URL correct or should it be something like http://0.0.0.0:3000/api/apps?name=test
I've tried many different URL formats and they all return an empty result even though there is data in my db. I have also reindexed many times and it shows that 6 items were indexed, which is correct. Any ideas as to what is going on?
EDIT: it works fine when searching from the web app without using the api. It just returns empty when calling from the API url

i would try to remove the ::App subclassing in your controller. my guess is it messes up sunspots or activerecords inference mechanisms regarding the table <-> class naming conventions.

Related

How to handle pagination with Pundit?

I've just started using the Pundit gem for authorisation in a Rails 4 app.
Everything's going fine but I can get my head around how pagination will work in the index action.
My controller's index action looks like:
def index
#records = policy_scope(Record)
end
The Scope class within my RecordPolicy then goes:
class Scope < Struct.new(:user, :scope)
def resolve
if user.has_role? :admin
# get all records
else
# get user specific records
end
end
end
This all works fine. I'd like to know how I would handle pagination though. Naturally this involves passing in a page parameter etc and I'm not sure how to do this without subsclassing the Scope class.
The policy_scope(Record) method returns an ActiveRecord::Relation object, then you can chain the pagination method, depending on which gem you use (will_paginate, kaminari).
def index
#records = policy_scope(Record).paginate(params[:page])
end
For googlers. The answer above is technically correct, but with most recent versions of Kaminari (mine is 0.17), the method to chain is page(params[:page])

What is the correct way to access an instance variable in a model method from another controller?

I created some scaffolding to manage audio clips which are going to be organized by index:
rails generate scaffold Clips name:string
I uploaded all the clips to my file server, and added them to the db using the auto generated rails control panel.
Now, I need to be able to access them, so I added a url method to the model:
class Clip < ActiveRecord::Base
def self.url
"http://example.file_server.com/audio-clips/#{#id}.mp3"
end
end
Now, in the controller than runs the site itself, calling this method looks like it outputs everything but the id....
class TwilioController < ApplicationController
def index
Twilio::TwiML::Response.new do |r|
#response = r.play Clip.where(name: "root").url
end
render :xml => #response
end
end
Outputs:
<Response>
<play>http://example.file_server.com/audio-clips/.mp3</play>
</Response>
How can I get this thing to insert the id into the URL string?
A few things, one, you defined url as self.url, which makes it a class level method. I'm guessing you didn't want to do that.
Also, don't use id as an instance variable, use its generated accessor method:
class Clip < ActiveRecord::Base
def url
"http://example.file_server.com/audio-clips/#{id}.mp3"
end
end
Also, you are calling url right after the where call, which returns a relation. You'll want to do something like:
Twilio::TwiML::Response.new do |r|
#response = r.play Clip.where(name: "root").first.url
end
But that depends more on what you are doing. If you expect there to be several results, you'll have to handle it differently. Also beware it may return no results...

Rails 3 respond_with returning associations

I have a simple Rails 3.2 controller which is consumed as an API with JSON:
module Api
module V1
class ReportsController < Api::V1::ApplicationController
def index
respond_with Report.where(name: params[:name])
end
end
end
end
(there is no code is the parent controllers)
When I consume this method, I'm getting all reports back, as expected, but I'm also getting all the associations. I don't see why this is and want to stop it.
Why am I getting the associations?
As #rmagnum2002 eluded to, I found active_model_serializers bundled into the app, and someone had created a serializer for that model without me noticing it.

ruby on rails implement a search form that searches multiple relations

I've implemented a simple search form (according to the "simple form" screencast) that searches the "illnesses" table in my DB.
Now I want the same search box to search both the "illnesses" table and the "symptoms" table.
My code currently looks like this:
main_page\index.html.erb:
<b>Illnesses</b>
<%= form_tag illnesses_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %><br/>
<%= submit_tag "Illnesses", :name => nil %><br/>
</p>
illnesses_controller.rb:
class IllnessesController < ApplicationController
def index
#illnesses = Illness.search(params[:search])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #illnesses }
end
...
end
illness.rb:
class Illness < ActiveRecord::Base
...
def self.search(search)
if search
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
Could you please guide me how to implement this extension?
I'm a beginner (obviously) and I don't really know what should be the "form_tag" action, where should I implement it and which class should implement the extended search...
Thanks,
Li
Hmm, to just easily set off presuming you have a Symptom class similar to the Illness class(btw it would be most clean if you refactored the search functionality into a module and then include this module in both classes) then you can do:
class IllnessesController < ApplicationController
def index
#results = Illness.search(params[:search]) + Symptom.search(params[:search])
...
end
end
But maybe you would like to refactor the name of the controller, because now it is not anymore Illness specific. Also notice that we are here using two search queries instead of one so it is not optimal, but saves you the pain of sending a pure SQL query for two types of models at the same time.
Okay for the module. If you are not familiar with modules they might seem a little weird but they are little more than a piece of code that can be shared across classes to keep things DRY which is our case too. You can imagine including the module as taking the code from the module and evaluating it (courtesy of interpreted languages) in the context of the class which has the same result as if the module code was hard coded into the class itself. So the module looks like:
module Search
def self.search(token)
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
end
end
And now any class, if it implements the find method(ActiveRecord API) can happily include this module and enjoy the search functionality like this:
require 'path/to/search'
class Foo < ActiveRecord::Base
include Search
end
That's it. Now if you need to tweak your search code, you change it in one place and it propagates to all the includers. You can also create modules inside modules which is sometimes used like this:
require 'active_support/concern'
module Search
extend ActiveSupport::Concern
included do
#Stuff that gets done when the module is included (new validations, callbacks etc.)
end
module ClassMethods
#Here you define stuff without the self. prefix
end
module InstanceMethods
#Instance methods here
end
end
But some of it is convention that is defined in ActiveSupport::Concern so not everything will probably work in pure ruby. I encourage you to experiment with these things, they make ruby real fun. Oh, extend is very much like include, only, as I understand it, it kind of evaluates on the class level. So all instance methods of the included module would become class methods of the includer module if you follow me. Have fun!

How to use Lucene/Solr in rails 4?

My project is about an online Mobile Shopping site.
I created search controller,and I use WHERE LIKE to do that:
def create
#result = Phone.where(['name LIKE ?', "%#{get}%" ])
render :index
end
private
def get
params[:keyword]
end
Now I want to exchange to Full-text-search.So have some gem to do that ? And how to code to searching by full-text-search ?
You can use elastic-search-rails gem for implementing full text search in your Rails application.
In your app/models/phone.rb:
require 'elasticsearch/model'
class Phone < ActiveRecord::Base
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
end
Phone.import
Then, in your controller:
#result = Phone.search('foobar').records
Here is a good tutorial on Getting Started with Elasticsearch on Rails that would help you. Another good SitePoint article that will help you get going is Full-Text Search in Rails with ElasticSearch.

Resources