Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 174 lines (126 sloc) 5.526 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
IndexTank-Tanker Tutorial

This is a step-by-step tutorial to add Tanker to every single rails application.

>> git clone git@github.com:flaptor/rails3-tanker-tutorial.git
>> cd rails3-tanker-tutorial
>> rake db:migrate
>> rails server

go to http://localhost:3000/posts and add some posts to check that everything is going fine

Add tanker gems to Gemfile:
gem 'tanker'
gem 'json_pure', '1.4.6', :require => 'json'
gem 'will_paginate'


>> echo "Rails3TtDemo::Application.config.index_tank_url = 'PRIVATE API URL'" > config/initializers/tanker.rb

Add simple Tanker configuration to Post class

include Tanker # include Tanker's module
tankit 'rails_3_tanker_tutorial' do # set the name of the index that tanker will use for this class
  indexes :name # index the field 'name'
  indexes :title # index the field 'title'
  indexes :content # index the field 'content'
  indexes :timestamp do # index the field 'timestamp' with the creation timestamp
    Time.new.to_i
  end
  indexes :url do # index the field 'url' with the value "/posts/" + self.id.to_s
    "/posts/" + self.id.to_s
  end

end
after_save :update_tank_indexes # add hooks to save, update
after_destroy :delete_tank_indexes # and delete methods



>> rake tanker:clear_indexes # delete and create all indexes defined by tanker
>> rake tanker:reindex # add all the objects in your database to IndexTank


Add a search form and a controller method to handle it:

- Add this piece of code to apps/views/posts/index.html.erb
<%= form_tag(search_path, :method => "get", :id => "search_form") do %>
  <%= label_tag(:query, "Search for:") %>
  <%= text_field_tag(:query) %>
  <%= submit_tag("Search") %>
<% end %>

- Add this piece of code to apps/controllers/posts_controller.rb
def search
  @posts = Post.search_tank(params[:query])

  respond_to do |format|
    format.html { render :action => 'index' }
    format.xml { render :xml => @posts }
  end
end

Add realtime scoring functions:

- inside the 'tankit' block in app/models/post.rb, add the following code that declares one document variable and one scoring function

    variables do
      {
        0 => votes.nil? ? 0 : votes
      }
    end

    functions do
      {
        1 => "d[0]" # sort desc by votes
      }
    end

- add an action in apps/controllers/posts_controller.rb to update 'votes' variables

  # PUT /posts/:id/vote
  def vote
    post = Post.find(params[:id])
    post.votes = post.votes.nil? ? 1 : post.votes + 1
    post.save

    @posts = Post.all

    respond_to do |format|
      format.html { render :action => 'index' }
      format.xml { render :xml => @posts }
    end
  end

- add a route declaration in config/routes.rb
  match '/posts/:id/vote' => 'posts#vote'


- add a link in app/views/posts/index.html.erb to update 'votes' variable and
  a label to show current votes of each method

<%= link_to 'Vote up', :controller => "posts", :action => "vote", :id => post.id %>

<h4>by <%= post.name %> (<%= post.votes.nil? ? 0 : post.votes %>)</h4>

- In search action in apps/controllers/posts_controller.rb add a function option to tanker call

@posts = Post.search_tank(params[:query], :function => 1)

- finally, run a rake task to create functions in indextank

>> rake tanker:functions

Now search should show posts sorted by their votes.

** You can also filter documents by functions. function 2 will be "age".
   let's give the users the option to filter by that functions. remember that recently added documents age is 0.

- in app/models/post.rb add the function '2 => "age"' in the function declaration:
    functions do
      {
        1 => "d[0]", # sort desc by votes
        2 => "age" # sort desc by votes
      }
    end

- change the search action in apps/controllers/posts_controller.rb to handle new parameters

  def search
    query = params[:query].nil? ? "" : params[:query] + '*'

    from_unit = params[:from_unit].nil? ? 1 : params[:from_unit].to_i
    from = params[:from].nil? || params[:from] == ""? "*" : params[:from].to_i * from_unit
    to_unit = params[:to_unit].nil? ? 1 : params[:to_unit].to_i
    to = params[:to].nil? || params[:to] == "" ? "*" : params[:to].to_i * to_unit

    if from != "*" or to != "*"
      @posts = Post.search_tank(query, :function => 1,
        :filter_functions => {2 => [[from, to]]})
    else
      @posts = Post.search_tank(query, :function => 1)
    end

    respond_to do |format|
      format.html { render :action => 'index' }
      format.xml { render :xml => @posts }
    end
  end

- add some inputs inside the search form in app/views/posts/index.html.erb

  <div id="adv_search">
  <%= label_tag(:from, "Age from:") %>
  <%= text_field_tag(:from, nil, :style => 'width:50px;') %>
  <select id="from_unit" name="from_unit">
    <option value="86400">Days</option>
    <option value="3600">Hour</option>
    <option value="60">Min</option>
    <option value="1">Sec</option>
  </select>
  <%= label_tag(:to, "to:") %>
  <%= text_field_tag(:to, nil, :style => 'width:50px;') %>
  <select id="to_unit" name="to_unit">
    <option value="86400">Days</option>
    <option value="3600">Hour</option>
    <option value="60">Min</option>
    <option value="1">Sec</option>
  </select>
  </div>


Now you could filter your post by age.

Something went wrong with that request. Please try again.