How to paginate, sort and search a table with Ajax and Rails (JQuery Style with will_paginate plugin)

Hey Everyone,

Today I decided to try and paginate, sort and search my account index using “Jrails” and “will_paginate” plugin. I took my ques from an article posted @ http://dev.nozav.org/rails_ajax_table.html#sec8. I changed it up a bit and switched out the prototype library with JQuery using the “Jrails” plugin to drop in JQuery. I also opted to use the “will_paginate” plugin rather than the classic_pagination plugin.

Screenshot1

Screenshot2



Resources:

script/plugin install git://github.com/futuresinc/jrails.git
script/plugin install git://github.com/mislav/will_paginate.git
Graphics for spinner.gif

I will try and keep this short and sweet, if you have questions please post a comment. I will do my best to answer them.

APPLICATION LAYOUT

Note: I had a problem when trying to use the observe_field due to the fact I have other js libraries loading. I would get an error “delayedObserver is not a function”. You need to make sure your other libraries don’t interfere with jrails loading. If you’re having this problem, remove everything else until you get it to work, and add back each js library one at a time. Just my experience.

VIEW (list.html.erb)

PARTIAL (_items_list.html.erb)

CONTROLLER METHOD

HELPER METHODS

DIFFERENCES

The major difference between the original article and this one is the fact that I had to replace the prototype syntax for jquery syntax in the controllers, helpers, and views. This mainly revolved around changing the following

Prototype: Element.show(’spinner’)

Jquery version: $(’#spinner’).show()

This applies to the hide element as well. I also used the will_paginate plugin

NEXT STEP FOR ME…

My next step I hope to accomplish today is add a drop down list so the user can choose which field they want to filter by. Once I add this, I will post my code. If I don’t add it, or come up with something different, I will post that.

Thanks!

Chris

Feel free to post comments. If you have a better way to do this, or feel I did something wrong I would love to hear.



ADDING SELECT TO CHOOSE SEARCH CRITERIA

This morning I tackled adding a select box so the user can choose which field they would like to search on. This wasn’t too difficult, but it caused me to use the “observe_form” helper rather than the “observe_field”. Here’s my code…

CONTROLLER METHOD

VIEW

PARTIAL

Note: This didn’t change

As always I’m open to comments or suggestions. I populated my database with 200K records and the search completed on each field in less than 3 seconds. I was really surprised and happy with the results. Let me know what you think.

Chris

9 Comments

observe_field (watch check_box_tag so select_tag can be disabled on click)

Hey Everyone,

This past week I had a scenerio where I needed to “disable” a rails select_tag if a check box on my form was clicked. To make this worse, the select boxes were dynamically created through an array so the id’s were created dynamically too. That shouldn’t make any difference in this little tutorial however.

In the title of my post is mention “observe_field”. This is how I preferred to implement this solution due to the fact I’m not a Javascript programmer, but this isn’t the path I took.  I ended up using straight JS to complete this, and it was “REALLY” easy. I should mention that I’m using JRAILS to replace prototype with JQuery. I tested this on both however and it worked fine. Here’s what I did…

In my view I had two items (The checkbox and the selectbox)

<%= check_box_tag ‘lock_settings_option’, ‘1′, @checked, :id => ‘lock_settings’, :onchange => “Change()”%>

<%= select_tag( “fields[#{c}]“, options_for_select(@fields, @default.to_i), :id => “field#{c}”, :disabled => @moption, :include_blank => ‘true’, :class => ‘field_options’) %>

To get this to work I added the following Javascript to the bottom of my view (keep in mind I had these two items in a form, that’s the reason you see “mapped_fields_form” in the example. It’s also important to understand that my id’s were assigned dynamically. The area on my select_tag that says “:id => “field#{c}” is where it assigns “field1, field2, field3 etc”.

NOTE: I had to replace the < with [ in this blog post so it would display properly.
[script language="javascript"]
function Change()
{
if (document.map_fields_form.lock_settings.checked == true)
{
document.map_fields_form.field1.disabled = true;
document.map_fields_form.field2.disabled = true;
document.map_fields_form.field3.disabled = true;
document.map_fields_form.field4.disabled = true;
document.map_fields_form.field5.disabled = true;
document.map_fields_form.field6.disabled = true;
}
else
{
document.map_fields_form.field1.disabled = false;
document.map_fields_form.field2.disabled = false;
document.map_fields_form.field3.disabled = false;
document.map_fields_form.field4.disabled = false;
document.map_fields_form.field5.disabled = false;
document.map_fields_form.field6.disabled = false;
}
}
[/script]

In my controller I placed the following so the checkbox and the select box would load with the proper choice. In my case if a certain field was empty then I wanted the fields to be “enabled”, but if it wasn’t then I wanted them to be disabled.

get_preferences = Preference.find(:first)

if get_preferences.handheld_mapping.empty?

@moption = false
@checked = false
else
@moption = true
@checked = true

end

I hope this helps someone down the road. I had hard time finding a solution that would work. If someone knows how this could be implemented using observe_field I’m all ears. In addition, if you have a comment, please post it.

Thanks!

Chris

1 Comment

Sphinx + Mac + Postgresql = unknown type ‘pgsql’; skipping

Hey Everyone,

I’m posting this blog article due to the fact I had this problem and never found a solution online. With the help of Pat Allen and the ThinkingSphinx google group I was able to find a solution. My problem had nothing to do with not compiling using (–with-pgsql) it was far more obscure. I’m using ThinkingSphinx as a search tool in my Ruby on Rails application. This was my first Mac and when it came to indexing sphinx I would get the following error…

using config file ‘/Users/Chris/obilling/config/
development.sphinx.conf’…
indexing index ‘account_core’…
ERROR: source ‘account_core_0′: unknown type ‘pgsql’; skipping.
ERROR: index ‘account_core’: no valid sources configured; skipping.
distributed index ‘account’ can not be directly indexed; skipping.

The problem was initially created due to the fact I had tried to install sphinx using macports (sudo port install sphinx). After the macport install things weren’t working properly so I did a manual install using the following resource as a guide (). All of the articles I found said the problem was the fact I didn’t compile using ./configure –with-pgsql –without-mysql. This wasn’t the case as you can see in the resource I provided, I did compile it with pgsql support and the ./configure supported that. It all looked fine. I spent the next week working with Pat Allen and the ThinkingSphinx google group to come up with the solution.

I’m not sure if every step here is required, but I will outline the steps I followed…

First I checked to see if “searchd” was located in the opt/local/bin/ folder or in the /usr/local/bin folder.

From the terminal…

which searchd

My output showed opt/local/bin/ which indicated it was still using the macports install.

I then went about renaming these files…

cd /opt/local/bin/
sudo mv searchd searchdold
sudo mv indexer indexerold

I then uninstalled the macports install…

sudo port uninstall sphinx

and finally… I re-installed sphinx and the proper libraries manually using the following resource…
Installing Sphinx with Postgres on Leopard

Many thanks to Maxim Chernya @ Medium exposure for writing a great article on the installation process.

1 Comment

RAILS + ThinkingSphinx + 2 Models = Search Results for both

Hey everyone,

This is my first Ruby on Rails article, and I’m excited to contribute something to the community (I hope). I decided to write this article due to the fact I had a heck of a time finding this information myself. I’m not claiming to know everything here, just everything I know. I am open for suggestions, and comments. I am simply trying to help someone avoid all the hassle I had as a noob with “ThinkingSphinx/Rails”. Here’s what it’s all about.

(PS, I’m using PostgreSQL for my database, but that shouldn’t matter with this example)

Lets say you need the ability to search at least 2 models in your project and have ThinkingSphinx (TS) return your search results with information from both models. In my case I have an Account model with account information, and then a whole seperate Name model with the name information that is associated with each account.

Example…

account.rb

class Account < ActiveRecord::Base

has_many :names, :dependent => :destroy

# Thinking Sphinx Search Indexes

define_index do

indexes s_account, :sortable => true

indexes s_account_no

indexes names.name, :as => :account_name

end

name.rb

class Name < ActiveRecord::Base

belongs_to :account

# Thinking Sphinx Search Indexes

define_index do

indexes account.s_account, :sortable => true

indexes account.s_account_no

indexes name, :as => :account_name

end


A misconception I had when I started was the fact that I had to setup my search criteria in either my “Accounts” controller or my “Name” controller. This in fact isn’t true. After a bunch of trial and error and misunderstanding I found out that you can setup your search criteria in a seperate controller and model. I  called mine “Results”.   So to keep everything simple I will outline my rails files below, and try to provide some insight as to why I did it that way. The truth of the matter is however…. I did it this way because it worked.  I would love comments from anyone that feels they have a better way.

I already outlined my model files above, so here’s the rest of the info…

ROUTES FILE (I added the following line)

map.resources :results, :collection => {:search => :get}

APPLICATION TEMPLATE

viewslayoutsapplication.html.erb

<% form_tag search_results_path, :method => :get do %>

<div id=”search”>

<%= text_field_tag :search, params[:search], :class => ‘text’ %>

<%= submit_tag ‘Search’, :class => ‘button’ %>

</div>


CONTROLLERS:

accounts_controller

I did nothing to this controller to make it work.

names_controller

again, I did nothing to this controller

results_controller (I created this specifically for searching)

class ResultsController < ApplicationController

def search

@results = ThinkingSphinx::Search.search(params[:search],

:classes => [Account,Name])

respond_to do |format|

format.html #calls the search.html.erb (viewsresultssearch.html.erb)

end

end

end


VIEW FILES

viewsresultssearch.html.erb

<%- @results.each do |result| -%>

<% if result.class == Account %>

<br><%= render :partial => ‘accounts/results’, :locals => {:account => result } %><br>

<% elsif result.class == Name %>

<%= render :partial => ‘names/results’, :locals => {:name => result } %><br><br>

<% end %>

<%- end -%>

<%= will_paginate @results %>

viewsaccounts_results.html.erb

Account: <%= link_to account.s_account_no, edit_account_path(account) %>

viewsnames_results.html.erb

Name: <%=name.name%>

When I was trying to find this information it didn’t make sense to me that I had to render a partial per model. After I set it up, and was able to see the results it seemed to work great. I just got it all setup, and I’m sure I will do some tweaking, but I was eager to post this blog before I got too lazy, or decided I wasn’t qualified yet to post anything about ThinkingSphinx. I’m not representing myself as qualified in this area I simply want to add one more resource for someone else to look at. If you have a better idea, or would like to add a comment, please do so.

1 Comment