I am attempting to implement Thinking Sphinx 2.0.10 which from my understanding is compatible with Rails 3. I am very new to programming using Ruby on Rails. I have gone through quite a few articles on StackOverflow but could not find a solution to my problem.
I installed the gem without the :require parameter using in my Gemfile.
gem 'thinking-sphinx', '2.0.10'
I have a working Rails application that displays a list that I would like to add a search to.
Here is my code for defining the indexes in my model file.
define_index do
indexes :email, :sortable => true
indexes :name, :sortable => true
indexes microposts.content, :as => :micropost_content
end
Here is the Rails code in my controller file. The commented out line is the original code that is working. I have a default for will_paginate I think in the application controller for 15 records per page.
def index
#users = User.search params[:search], :per_page => 15
# #users = User.paginate(page: params[:page])
end
Here is the search box that I added to my index page.
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
Here is my rSpec code. This is the original code that I was using before I attempted to implement Thinking Sphinx.
describe "index" do
let(:user) { FactoryGirl.create(:user) }
before(:each) do
sign_in user
visit users_path
end
it { should have_selector('title', text: 'All users') }
describe "pagination" do
before(:all) { 15.times { FactoryGirl.create(:user) } }
after(:all) { User.delete_all }
let(:first_page) { User.paginate(page: 1) }
let(:second_page) { User.paginate(page: 2) }
it { should have_link('Next') }
it { should have_link('2') }
it { should_not have_link('delete') }
it "should list each user" do
User.all[0..2].each do |user|
page.should have_selector('li', text: user.name)
end
end
it "should list the first page of users" do
first_page.each do |user|
page.should have_selector('li', text: user.name)
end
end
it "should not list the second page of users" do
second_page.each do |user|
page.should_not have_selector('li', text: user.name)
end
end
describe "as an admin user" do
let(:admin) { FactoryGirl.create(:admin) }
before do
sign_in admin
visit users_path
end
it { should have_link('delete', href: user_path(User.first)) }
it "should be able to delete another user" do
expect { click_link('delete') }.to change(User, :count).by(-1)
end
it { should_not have_link('delete', href: user_path(admin)) }
end
end
end
When I run my rSpec test I get the following error:
Failure/Error: visit users_path
ActionView::Template::Error:
getaddrinfo: nodename nor servname provided, or not known
The page displays just fine. When I enter text in the search box and click the button nothing happens which is no surprise to me.
I am able to run Sphinx on the terminal. The searches work fine. I just do not know enough to debug this problem with Thinking Sphinx. I have searched many pages on this website and many others the past few days but none of them are dealing with this issue. Any help would be appreciated.
Did you initialize the sphinx database?
Usually you just need to do something like:
rake ts:rebuild
This should automatically run rake ts:conf for you and rebuild your indexes.
You could also use rake ts:in to update the indexes.
A simple way to test if this is working is to run the rails console (rails c) and try manually searching your users (User.search).
If you get any results, the indexes are available and you can troubleshoot your views/controllers next ;)
Related
I have installed recaptcha according to the gem instructions, however when I view the sign_up page (using Devise), the catcha doesn't appear until I refresh the page.
Looking through other comments, the recommendation is to disable turbolinks (which I am using) by changing the sign_in link to:
<%= link_to "Sign up", new_registration_path, "data-no-turbolink" => true %><br />
I have tried this, but I still don't get the captcha until I do a page refresh.
Relevant code:
Views/devise/registrations/new.html.erb
................
<%= recaptcha_tags %>
................
/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def create
if !verify_recaptcha
flash.delete :recaptcha_error
build_resource
resource.valid?
resource.errors.add(:base, "There was an error with the recaptcha code below. Please re-enter the code.")
clean_up_passwords(resource)
respond_with_navigational(resource) { render_with_scope :new }
else
flash.delete :recaptcha_error
super
end
end
def clean_up_passwords(*args)
# Delete or comment out this method to prevent the password fields from
# repopulating after a failed registration
end
end
Issue was that I needed to still include "class:" in the link:
<%= link_to "Sign up", new_user_registration_path, "data-no-turbolink" => true, class: "btn btn-primary btn-med" %>
Just try in controller this code
def create
if resource.valid? && !verify_recaptcha
clean_up_passwords(resource)
flash.delete :recaptcha_error
elsif !resource.valid? && verify_recaptcha
clean_up_passwords resource
respond_with resource
elsif !resource.valid? && !verify_recaptcha
flash.now[:alert] = "Recaptcha error"
flash.delete :recaptcha_error
clean_up_passwords resource
respond_with resource
end
end
And in your Views/devise/registrations/new.html.erb
<%= recaptcha_tags display: {theme: 'red', tabindex: 5}, ssl: false, noscript: false %>
While going through the Learn Rails book written by Michael Hartl, I'm stumped on one of the exercises.
Learn Rails by Example by Michael Hartl
"Add tests for micropost pagination"
My incorrect test, placed in the 'describe "for signed-in users" do' is as follow:
describe "pagination" do
before(:all) do
30.times { FactoryGirl.create(:micropost, user: user) }
end
after(:all) { user.feed.delete_all }
page.should have_selector('div.pagination') }
it "should list each micropost" do
user.feed.paginate(page: 1).each do |user|
page.should have_selector('li', text: user.name)
end
end
end
The test shows as passed no matter if I do page.should or page.should_not.
Any 'hint/help' would be appreciated
While browsing through some of the repos I found the answer to my question - I needed to visit the root_path again, after creating the additional microposts.
describe "pagination" do
it "should paginate the feed" do
30.times { FactoryGirl.create(:micropost, user: user, content: "Consectetur adipiscing elit") }
visit root_path
page.should have_selector("div.pagination")
end
end
I think you should put an after all filter to do the clean-up to the mass insertions of the microposts; as your implementation stands (unless you do it in another part of your test code not shown here) it does not delete the created microposts.
This can be easily done through the following code:
describe "pagination" do
after(:all) { user.microposts.delete_all unless user.microposts.nil? }
it "should paginate the feed" do
40.times { FactoryGirl.create(:micropost, user: user) }
visit root_path
page.should have_selector('div.pagination')
end
end
I'm working on a training app which is an Ogame-Like game (https://github.com/arnlen/ogame-like).
I'm using rspec (with Capybara) in order to test my app.
I'm stacked for several hours because rspec is complaining for an error which *I can't reproduce * by myself with my browser.
Here is my rspec code :
describe 'Planet pages' do
let(:user){FactoryGirl.create(:user)}
before {sign_in user}
subject {page}
describe "new planet page" do
before {visit new_planet_path}
describe "with valid information" do
before do
visit new_planet_path
fill_in "Name", with: "MyPlanet"
click_button "Validate"
end
# This test doesn't pass
it {should have_selector('h1', text: "Planet")}
end
end
end
The failure :
1) Planet pages new planet page with valid information
Failure/Error: it {should have_selector('h1', text: "Planet")}
expected css "h1" with text "Planet" to return something
# ./spec/requests/planet_pages_spec.rb:34:in `block (4 levels) in <top (required)>'
Here is the involved code.
My function "sign_in" used by rspec (location : spec/support/utilities.rb)
def sign_in(user)
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
My UsersController
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :show, :edit, :update, :destroy]
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
redirect_to new_planet_path
else
render 'new'
end
[...]
My PlanetsController
class PlanetsController < ApplicationController
before_filter :signed_in_user
def index
#planets = current_user.planets
end
def new
#planet = Planet.new
end
def create
#planet = Planet.new(name: params[:planet][:name],
coordinates: generate_coordinates,
metal_ressource: 1000,
user_id: current_user.id)
if #planet.save
flash[:success] = "Welcome on your first planet!"
redirect_to action: 'index'
else
flash[:error] = "Error naming your planet"
render 'new'
end
end
end
And My Planet Index view
<% #planets.each do |planet| %>
<h1>Planet : <%= planet.name %></h1>
<p><%= "Coordinates : #{planet.coordinates}" %></p>
<% end %>
I tried to user the Capybara method "save_and_open_page", but rspec raised an error "undefined method"
I also tried step by step debugging by iterations on my spec file, and it revealed that the error occurs right after the "click_button 'Validate'". For an unknown reason, rspec seems not to be able to reach the planets_path ("index" action from PlanetsController).
I'm out, if anybody has an idea, I take it !
EDIT : SOLVED - Found the problem!
Using the "save_and_open_page" method from Capybara, I figured out what was going on: the planet created by rspec didn't have any coordinates, which was not allowed by the model.
How to debug with the wonderful "save_and_open_page" method
Add this to your gemfile : "gem 'launchy'"
Install it : bundle install
Put the command "save_and_open_page" wherever you want
Hope it could help. :)
Capybara also has a save_page method, which is easier to use as it does not seem to need the "launchy" gem. The pages are saved in tmp/capybara. In the rspec tests, be sure to use save_page inside before, it, or some other block. It will not work as a separate command. Example:
before { visit signup_path; save_page }
I'd like to write my usual RSpec/Capybara request specs to test search functionality using Sunspot and Solr. I've been digging around but can't find how to get this working. I have the sunspot_test gem installed and have verified that the Products created do exist. The issue seems to be with the indexing, maybe? What am I missing?
require 'spec_helper'
describe "search" do
context "when searching by name/description" do
let!(:super_mario_bros_3) { Factory(:product, :name => 'Super Mario Bros. 3') }
let!(:legend_of_zelda) { Factory(:product, :name => 'Legend of Zelda') }
before { Product.reindex; Sunspot.commit }
it "should only find games matching the search text", :js => true, :search => true do
# search_for fills in and submits the search form
search_for("Super")
# This yields an empty array
p Product.search { keyword "super" }.results
# These fail
page.should have_content super_mario_bros_3.name
page.should have_no_content legend_of_zelda.name
end
end
end
You're probably making the same mistake that I did. See the answer to my post here - Sunspot and RSpec fail. The commit doesn't seem to be working
Any test which uses Sunspot should be as follows....
describe "search", :search => true do
and make sure you have the following in your spec_helper.rb
require 'sunspot_test/rspec'
Having some trouble with some nested resources routing. What I'm trying to do is link to a user's profile page for editing purposes. In my view it is written as:
<%= link_to "Edit Profile", edit_user_profile_path(current_user) %>
Which errors out with:
No route matches {:action=>"edit", :controller=>"profiles", :user_id=>#<User id: 1, email: "EDITEDOUT", hashed_password: "EDITEDOUT", created_at: "2011-01-20 18:30:44", updated_at: "2011-01-20 18:30:44">}
In my routes.rb file, it looks like so:
resources :users do
resources :profiles, :controller => "profiles"
end
I checked my Rake routes, and it gave me this as a valid option:
edit_user_profile GET /users/:user_id/profiles/:id/edit(.:format) {:action=>"edit", :controller=>"profiles"}
Which I am able to manually navigate to. For good measures, here's proof of my controller:
class ProfilesController < ApplicationController
def edit
#user = current_user
#profile = current_user.profile
end
def update
#user = current_user
#profile = current_user.profile
respond_to do |format|
if #profile.update_attributes(params[:profile])
format.html { redirect_to(orders_path, :notice => "Your profile has been updated.") }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #profile.errors, :status => :unprocessable_entity }
end
end
end
end
Anyway, I've been having some problem tracking this down. Any pointers would help. For my DB design Profiles belong to Users in a one-to-one relationship. I'm hoping it's just something newbish I'm not noticing a new set of eyes might help.
If you look closely at your route, you'll see that it expects both a :user_id and an :id. The latter, in this case, refers to the user profile.
In order to tell Rails that you want that particular profile, you'll have to specify both the user and the profile in your link, like this:
edit_user_profile_path(current_user, #profile)
Now, Rails will use the first argument (current_user) for the :user_id part of the route, and the second argument (#profile) for the :id.