New and Announcement search. Disabled impression.
This commit is contained in:
		
							parent
							
								
									033667f99b
								
							
						
					
					
						commit
						f9bdb4a327
					
				| 
						 | 
				
			
			@ -5,7 +5,8 @@ log/*.log
 | 
			
		|||
tmp/**/*
 | 
			
		||||
public/uploads/**/*
 | 
			
		||||
uploads/**/*
 | 
			
		||||
 | 
			
		||||
public/panel/**/*
 | 
			
		||||
public/index.html
 | 
			
		||||
.DS_Store
 | 
			
		||||
 | 
			
		||||
*.swp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								Gemfile
								
								
								
								
							
							
						
						
									
										8
									
								
								Gemfile
								
								
								
								
							| 
						 | 
				
			
			@ -41,9 +41,15 @@ gem 'rb-readline' if RUBY_PLATFORM.downcase.include?("linux")
 | 
			
		|||
 | 
			
		||||
gem "impressionist", :require => "impressionist", :path => "vendor/impressionist"
 | 
			
		||||
 | 
			
		||||
 gem "tire"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
gem 'redis','>= 2.1.1'
 | 
			
		||||
gem 'chinese_pinyin', '0.4.1'
 | 
			
		||||
# add rmmseg if you need search by segment words
 | 
			
		||||
gem 'rmmseg-cpp-huacnlee', '0.2.9'
 | 
			
		||||
gem 'redis-namespace','~> 1.0.2'
 | 
			
		||||
gem 'redis-search', '0.7.1'
 | 
			
		||||
 | 
			
		||||
# Gems used only for assets and not required
 | 
			
		||||
# in production environments by default.
 | 
			
		||||
group :assets do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										21
									
								
								Gemfile.lock
								
								
								
								
							
							
						
						
									
										21
									
								
								Gemfile.lock
								
								
								
								
							| 
						 | 
				
			
			@ -66,6 +66,7 @@ GEM
 | 
			
		|||
    carrierwave-mongoid (0.1.3)
 | 
			
		||||
      carrierwave (>= 0.5.6)
 | 
			
		||||
      mongoid (~> 2.1)
 | 
			
		||||
    chinese_pinyin (0.4.1)
 | 
			
		||||
    chronic (0.6.7)
 | 
			
		||||
    coffee-rails (3.1.1)
 | 
			
		||||
      coffee-script (>= 2.2.0)
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +97,6 @@ GEM
 | 
			
		|||
      railties (>= 3.0.0)
 | 
			
		||||
    fastercsv (1.5.4)
 | 
			
		||||
    haml (3.1.4)
 | 
			
		||||
    hashr (0.0.21)
 | 
			
		||||
    hike (1.2.1)
 | 
			
		||||
    hoe (2.16.1)
 | 
			
		||||
      rake (~> 0.8)
 | 
			
		||||
| 
						 | 
				
			
			@ -176,6 +176,10 @@ GEM
 | 
			
		|||
    redis (2.2.2)
 | 
			
		||||
    redis-namespace (1.0.3)
 | 
			
		||||
      redis (< 3.0.0)
 | 
			
		||||
    redis-search (0.7.1)
 | 
			
		||||
      chinese_pinyin (>= 0.3.0)
 | 
			
		||||
      redis (>= 2.1.1)
 | 
			
		||||
      redis-namespace (~> 1.0.2)
 | 
			
		||||
    resque (1.20.0)
 | 
			
		||||
      multi_json (~> 1.0)
 | 
			
		||||
      redis-namespace (~> 1.0.2)
 | 
			
		||||
| 
						 | 
				
			
			@ -187,8 +191,7 @@ GEM
 | 
			
		|||
      redis (>= 2.0.1)
 | 
			
		||||
      resque (>= 1.8.0)
 | 
			
		||||
      rufus-scheduler
 | 
			
		||||
    rest-client (1.6.7)
 | 
			
		||||
      mime-types (>= 1.16)
 | 
			
		||||
    rmmseg-cpp-huacnlee (0.2.9)
 | 
			
		||||
    rsolr (1.0.8)
 | 
			
		||||
      builder (>= 2.1.2)
 | 
			
		||||
    rspec (2.8.0)
 | 
			
		||||
| 
						 | 
				
			
			@ -261,12 +264,6 @@ GEM
 | 
			
		|||
    tilt (1.3.3)
 | 
			
		||||
    tinymce-rails (3.4.8)
 | 
			
		||||
      railties (>= 3.1)
 | 
			
		||||
    tire (0.4.2)
 | 
			
		||||
      activemodel (>= 3.0)
 | 
			
		||||
      hashr (~> 0.0.19)
 | 
			
		||||
      multi_json (~> 1.0)
 | 
			
		||||
      rake
 | 
			
		||||
      rest-client (~> 1.6)
 | 
			
		||||
    transaction-simple (1.4.0)
 | 
			
		||||
      hoe (>= 1.1.7)
 | 
			
		||||
    treetop (1.4.10)
 | 
			
		||||
| 
						 | 
				
			
			@ -299,6 +296,7 @@ DEPENDENCIES
 | 
			
		|||
  bson_ext
 | 
			
		||||
  carrierwave
 | 
			
		||||
  carrierwave-mongoid
 | 
			
		||||
  chinese_pinyin (= 0.4.1)
 | 
			
		||||
  coffee-rails
 | 
			
		||||
  database_cleaner
 | 
			
		||||
  delorean
 | 
			
		||||
| 
						 | 
				
			
			@ -322,9 +320,13 @@ DEPENDENCIES
 | 
			
		|||
  radius
 | 
			
		||||
  rails (>= 3.1.0, < 3.2.0)
 | 
			
		||||
  rake
 | 
			
		||||
  redis (>= 2.1.1)
 | 
			
		||||
  redis-namespace (~> 1.0.2)
 | 
			
		||||
  redis-search (= 0.7.1)
 | 
			
		||||
  resque
 | 
			
		||||
  resque-restriction
 | 
			
		||||
  resque-scheduler
 | 
			
		||||
  rmmseg-cpp-huacnlee (= 0.2.9)
 | 
			
		||||
  rspec (~> 2.0)
 | 
			
		||||
  rspec-rails (~> 2.0)
 | 
			
		||||
  ruby-debug19
 | 
			
		||||
| 
						 | 
				
			
			@ -337,6 +339,5 @@ DEPENDENCIES
 | 
			
		|||
  sprockets
 | 
			
		||||
  sunspot-rails-tester
 | 
			
		||||
  tinymce-rails
 | 
			
		||||
  tire
 | 
			
		||||
  uglifier
 | 
			
		||||
  watchr
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ class PagesController < ApplicationController
 | 
			
		|||
    #begin  
 | 
			
		||||
      @item = Item.first(:conditions => {:path => params[:page_name]})
 | 
			
		||||
      if @item && @item.is_published && (@item.enabled_for.nil? ? true : @item.enabled_for.include?(I18n.locale.to_s))
 | 
			
		||||
        impressionist(@item)
 | 
			
		||||
        # impressionist(@item)
 | 
			
		||||
        case @item._type
 | 
			
		||||
          when 'Page'    
 | 
			
		||||
            render_page
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
require "redis"
 | 
			
		||||
require "redis-namespace"
 | 
			
		||||
require "redis-search"
 | 
			
		||||
# don't forget change namespace
 | 
			
		||||
redis = Redis.new(:host => "127.0.0.1",:port => "6379")
 | 
			
		||||
# We suggest you use a special db in Redis, when you need to clear all data, you can use flushdb command to clear them.
 | 
			
		||||
redis.select(3)
 | 
			
		||||
# Give a special namespace as prefix for Redis key, when your have more than one project used redis-search, this config will make them work fine.
 | 
			
		||||
redis = Redis::Namespace.new("orbit_nccu:redis_search2", :redis => redis)
 | 
			
		||||
Redis::Search.configure do |config|
 | 
			
		||||
  config.redis = redis
 | 
			
		||||
  config.complete_max_length = 100
 | 
			
		||||
  config.pinyin_match = true
 | 
			
		||||
  # use rmmseg, true to disable it, it can save memroy
 | 
			
		||||
  config.disable_rmmseg = false
 | 
			
		||||
end
 | 
			
		||||
Bulletin.new
 | 
			
		||||
NewsBulletin.new
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
# encoding: UTF-8
 | 
			
		||||
namespace :matt_dev do
 | 
			
		||||
  desc 'Testing Searching'
 | 
			
		||||
  task :searching_01 => :environment do
 | 
			
		||||
     a= Redis::Search.query("Bulletin",'我',:conditions =>{:is_checked=>true,:is_hidden=>false})
 | 
			
		||||
    p a
 | 
			
		||||
    a= Redis::Search.query("NewsBulletin",'社科院',:conditions =>{:is_checked=>true,:is_hidden=>false})
 | 
			
		||||
    p a
 | 
			
		||||
    # p Pinyin.t('台灣不是中國的一部分')
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										885
									
								
								tmp/tire-dsl.rb
								
								
								
								
							
							
						
						
									
										885
									
								
								tmp/tire-dsl.rb
								
								
								
								
							| 
						 | 
				
			
			@ -1,885 +0,0 @@
 | 
			
		|||
# encoding: UTF-8
 | 
			
		||||
#
 | 
			
		||||
# **Tire** provides rich and comfortable Ruby API for the
 | 
			
		||||
# [_ElasticSearch_](http://www.elasticsearch.org/) search engine/database.
 | 
			
		||||
#
 | 
			
		||||
# _ElasticSearch_ is a scalable, distributed, cloud-ready, highly-available
 | 
			
		||||
# full-text search engine and database, communicating by JSON over RESTful HTTP,
 | 
			
		||||
# based on [Lucene](http://lucene.apache.org/), written in Java.
 | 
			
		||||
#
 | 
			
		||||
# <img src="http://github.com/favicon.ico" style="position:relative; top:2px">
 | 
			
		||||
# _Tire_ is open source, and you can download or clone the source code
 | 
			
		||||
# from <https://github.com/karmi/tire>.
 | 
			
		||||
#
 | 
			
		||||
# By following these instructions you should have the search running
 | 
			
		||||
# on a sane operation system in less then 10 minutes.
 | 
			
		||||
 | 
			
		||||
# Note, that this file can be executed directly:
 | 
			
		||||
#
 | 
			
		||||
#     ruby -I lib examples/tire-dsl.rb
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### Installation
 | 
			
		||||
 | 
			
		||||
# Install _Tire_ with _Rubygems_:
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
#     gem install tire
 | 
			
		||||
#
 | 
			
		||||
require 'rubygems'
 | 
			
		||||
require 'colorize'
 | 
			
		||||
 | 
			
		||||
# _Tire_ uses the [_multi_json_](https://github.com/intridea/multi_json) gem as a generic JSON library.
 | 
			
		||||
# We want to use the [_yajl-ruby_](https://github.com/brianmario/yajl-ruby) gem in its full on mode here.
 | 
			
		||||
#
 | 
			
		||||
require 'yajl/json_gem'
 | 
			
		||||
 | 
			
		||||
# Now, let's require the _Tire_ gem itself, and we're ready to go.
 | 
			
		||||
#
 | 
			
		||||
require 'tire'
 | 
			
		||||
 | 
			
		||||
#### Prerequisites
 | 
			
		||||
 | 
			
		||||
# We'll need a working and running _ElasticSearch_ server, of course. Thankfully, that's easy.
 | 
			
		||||
( puts <<-"INSTALL" ; exit(1) ) unless (RestClient.get('http://localhost:9200') rescue false)
 | 
			
		||||
 | 
			
		||||
 [ERROR] You don’t appear to have ElasticSearch installed. Please install and launch it with the following commands:
 | 
			
		||||
 | 
			
		||||
 curl -k -L -o elasticsearch-0.19.0.tar.gz http://github.com/downloads/elasticsearch/elasticsearch/elasticsearch-0.19.0.tar.gz
 | 
			
		||||
 tar -zxvf elasticsearch-0.19.0.tar.gz
 | 
			
		||||
 ./elasticsearch-0.19.0/bin/elasticsearch -f
 | 
			
		||||
INSTALL
 | 
			
		||||
 | 
			
		||||
### Storing and indexing documents
 | 
			
		||||
 | 
			
		||||
# Let's initialize an index named “articles”.
 | 
			
		||||
#
 | 
			
		||||
Tire.index 'articles' do
 | 
			
		||||
  # To make sure it's fresh, let's delete any existing index with the same name.
 | 
			
		||||
  #
 | 
			
		||||
  delete
 | 
			
		||||
  # And then, let's create it.
 | 
			
		||||
  #
 | 
			
		||||
  create
 | 
			
		||||
 | 
			
		||||
  # We want to store and index some articles with `title`, `tags` and `published_on` properties.
 | 
			
		||||
  # Simple Hashes are OK. The default type is „document”.
 | 
			
		||||
  #
 | 
			
		||||
  store :title => '復興「校球」 政大男足決戰UFA足球聯賽',   :tags => ['足球'],           :published_on => '2011-01-01'
 | 
			
		||||
  store :title => '社科院舉辦碩博士班畢業生撥穗典禮',   :tags => ['博士班', '畢業'], :published_on => '2011-01-02'
 | 
			
		||||
 | 
			
		||||
  # We usually want to set a specific _type_ for the document in _ElasticSearch_.
 | 
			
		||||
  # Simply setting a `type` property is OK.
 | 
			
		||||
  #
 | 
			
		||||
  store :type => 'article',
 | 
			
		||||
        :title => '支持政大學子 羅家倫之女設立獎學金',
 | 
			
		||||
        :tags => ['獎學金'],
 | 
			
		||||
        :published_on => '2011-01-02'
 | 
			
		||||
 | 
			
		||||
  # We may want to wrap your data in a Ruby class, and use it when storing data.
 | 
			
		||||
  # The contract required of such a class is very simple.
 | 
			
		||||
  #
 | 
			
		||||
  class Article
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    attr_reader :title, :tags, :published_on
 | 
			
		||||
    def initialize(attributes={})
 | 
			
		||||
      @attributes =  attributes
 | 
			
		||||
      @attributes.each_pair { |name,value| instance_variable_set :"@#{name}", value }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # It must provide a `type`, `_type` or `document_type` method for propper mapping.
 | 
			
		||||
    #
 | 
			
		||||
    def type
 | 
			
		||||
      'article'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # And it must provide a `to_indexed_json` method for conversion to JSON.
 | 
			
		||||
    #
 | 
			
		||||
    def to_indexed_json
 | 
			
		||||
      @attributes.to_json
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Note: Since our class takes a Hash of attributes on initialization, we may even
 | 
			
		||||
  # wrap the results in instances of this class; we'll see how to do that further below.
 | 
			
		||||
  #
 | 
			
		||||
  article = Article.new :title => '親身感受臺灣特色 日本田野研究團政大學習',
 | 
			
		||||
                        :tags => ['臺灣特色', '日本'],
 | 
			
		||||
                        :published_on => '2011-01-03'
 | 
			
		||||
 | 
			
		||||
  # Let's store the `article`, now.
 | 
			
		||||
  #
 | 
			
		||||
  store article
 | 
			
		||||
 | 
			
		||||
  # And let's „force refresh“ the index, so we can query it immediately.
 | 
			
		||||
  #
 | 
			
		||||
  refresh
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# We may want to define a specific [mapping](http://www.elasticsearch.org/guide/reference/api/admin-indices-create-index.html)
 | 
			
		||||
# for the index.
 | 
			
		||||
 | 
			
		||||
Tire.index 'articles' do
 | 
			
		||||
  # To do so, let's just pass a Hash containing the specified mapping to the `Index#create` method.
 | 
			
		||||
  #
 | 
			
		||||
  create :mappings => {
 | 
			
		||||
 | 
			
		||||
    # Let's specify for which _type_ of documents this mapping should be used:
 | 
			
		||||
    # „article”, in our case.
 | 
			
		||||
    #
 | 
			
		||||
    :article => {
 | 
			
		||||
      :properties => {
 | 
			
		||||
 | 
			
		||||
        # Let's specify the type of the field, whether it should be analyzed, ...
 | 
			
		||||
        #
 | 
			
		||||
        :id       => { :type => 'string', :index => 'not_analyzed', :include_in_all => false },
 | 
			
		||||
 | 
			
		||||
        # ... set the boost or analyzer settings for the field, etc. The _ElasticSearch_ guide
 | 
			
		||||
        # has [more information](http://elasticsearch.org/guide/reference/mapping/index.html).
 | 
			
		||||
        # Don't forget, that proper mapping is key to efficient and effective search.
 | 
			
		||||
        # But don't fret about getting the mapping right the first time, you won't.
 | 
			
		||||
        # In most cases, the default, dynamic mapping is just fine for prototyping.
 | 
			
		||||
        #
 | 
			
		||||
        :title    => { :type => 'string', :analyzer => 'cjk', :boost => 2.0             },
 | 
			
		||||
        :tags     => { :type => 'string', :analyzer => 'keyword'                             },
 | 
			
		||||
        :content  => { :type => 'string', :analyzer => 'cjk'                               }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
#### Bulk Indexing
 | 
			
		||||
 | 
			
		||||
# Of course, we may have large amounts of data, and adding them to the index one by one really isn't the best idea.
 | 
			
		||||
# We can use _ElasticSearch's_ [bulk API](http://www.elasticsearch.org/guide/reference/api/bulk.html)
 | 
			
		||||
# for importing the data.
 | 
			
		||||
 | 
			
		||||
# So, for demonstration purposes, let's suppose we have a simple collection of hashes to store.
 | 
			
		||||
#
 | 
			
		||||
articles = [
 | 
			
		||||
 | 
			
		||||
  # Notice that such objects must have an `id` property!
 | 
			
		||||
  #
 | 
			
		||||
  { :id => '1', :type => 'article', :title => '復興「校球」 政大男足決戰UFA足球聯賽',   :tags => ['足球'],           :published_on => '2011-01-01' },
 | 
			
		||||
 | 
			
		||||
  # And, of course, they should contain the `type` property for the mapping to work!
 | 
			
		||||
  #
 | 
			
		||||
  { :id => '2', :type => 'article', :title => '社科院舉辦碩博士班畢業生撥穗典禮',   :tags => ['博士班', '畢業','社科院'], :published_on => '2011-01-02' },
 | 
			
		||||
  { :id => '3', :type => 'article', :title => '支持政大學子 羅家倫之女設立獎學金', :tags => ['獎學金'],           :published_on => '2011-01-02' },
 | 
			
		||||
  { :id => '4', :type => 'article', :title => '親身感受臺灣特色 日本田野研究團政大學習',  :tags => ['臺灣特色', '日本'],    :published_on => '2011-01-03' }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
# We can just push them into the index in one go.
 | 
			
		||||
#
 | 
			
		||||
Tire.index 'articles' do
 | 
			
		||||
  import articles
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Of course, we can easily manipulate the documents before storing them in the index.
 | 
			
		||||
#
 | 
			
		||||
Tire.index 'articles' do
 | 
			
		||||
  delete
 | 
			
		||||
 | 
			
		||||
  # ... by passing a block to the `import` method. The collection will
 | 
			
		||||
  # be available in the block argument.
 | 
			
		||||
  #
 | 
			
		||||
  import articles do |documents|
 | 
			
		||||
 | 
			
		||||
    # We will capitalize every _title_ and return the manipulated collection
 | 
			
		||||
    # back to the `import` method.
 | 
			
		||||
    #
 | 
			
		||||
    documents.map { |document| document.update(:title => document[:title].capitalize) }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  refresh
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
### Searching
 | 
			
		||||
 | 
			
		||||
# With the documents indexed and stored in the _ElasticSearch_ database, we can search them, finally.
 | 
			
		||||
#
 | 
			
		||||
# _Tire_ exposes the search interface via simple domain-specific language.
 | 
			
		||||
 | 
			
		||||
#### Simple Query String Searches
 | 
			
		||||
 | 
			
		||||
# We can do simple searches, like searching for articles containing “One” in their title.
 | 
			
		||||
#
 | 
			
		||||
s = Tire.search('news_bulletins') do
 | 
			
		||||
  query do
 | 
			
		||||
    string "title:政大"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# The results:
 | 
			
		||||
#     * One [tags: ruby]
 | 
			
		||||
#
 | 
			
		||||
s.results.each do |document|
 | 
			
		||||
  puts "Test1==============================Has results: #{s.results.count}".yellow
 | 
			
		||||
  puts "* #{ document.title } [tags: ]"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Or, we can search for articles published between January, 1st and January, 2nd.
 | 
			
		||||
#
 | 
			
		||||
puts "Test2==Or, we can search for articles published between January, 1st and January, 2nd.=Has results: #{s.results.count}".yellow
 | 
			
		||||
s = Tire.search('articles') do
 | 
			
		||||
  query do
 | 
			
		||||
    string "published_on:[2011-01-01 TO 2011-01-02]"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# The results:
 | 
			
		||||
#     * One [published: 2011-01-01]
 | 
			
		||||
#     * Two [published: 2011-01-02]
 | 
			
		||||
#     * Three [published: 2011-01-02]
 | 
			
		||||
#
 | 
			
		||||
s.results.each do |document|
 | 
			
		||||
  puts "* #{ document.title } [published: #{document.published_on}]"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Notice, that we can access local variables from the _enclosing scope_.
 | 
			
		||||
# (Of course, we may write the blocks in shorter notation.)
 | 
			
		||||
 | 
			
		||||
# We will define the query in a local variable named `q`...
 | 
			
		||||
#
 | 
			
		||||
q = "title:T*"
 | 
			
		||||
# ... and we can use it inside the `query` block.
 | 
			
		||||
#
 | 
			
		||||
s = Tire.search('articles') { query { string q } }
 | 
			
		||||
 | 
			
		||||
# The results:
 | 
			
		||||
#     * Two [tags: ruby, python]
 | 
			
		||||
#     * Three [tags: java]
 | 
			
		||||
#
 | 
			
		||||
puts "Test3==and we can use it inside the `query` block..[ #{q} ]=Has results: #{s.results.count}".yellow
 | 
			
		||||
s.results.each do |document|
 | 
			
		||||
  puts "* #{ document.title } [tags:]"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Often, we need to access variables or methods defined in the _outer scope_.
 | 
			
		||||
# To do that, we have to use a slight variation of the DSL.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# Let's assume we have a plain Ruby class, named `Article`.
 | 
			
		||||
#
 | 
			
		||||
class Article
 | 
			
		||||
 | 
			
		||||
  # We will define the query in a class method...
 | 
			
		||||
  #
 | 
			
		||||
  def self.q
 | 
			
		||||
    "title:T*"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # ... and wrap the _Tire_ search method in another one.
 | 
			
		||||
  def self.search
 | 
			
		||||
 | 
			
		||||
    # Notice how we pass the `search` object around as a block argument.
 | 
			
		||||
    #
 | 
			
		||||
    Tire.search('articles') do |search|
 | 
			
		||||
 | 
			
		||||
      # And we pass the query object in a similar matter.
 | 
			
		||||
      #
 | 
			
		||||
      search.query do |query|
 | 
			
		||||
 | 
			
		||||
        # Which means we can access the `q` class method.
 | 
			
		||||
        #
 | 
			
		||||
        query.string self.q
 | 
			
		||||
      end
 | 
			
		||||
    end.results
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# We may use any valid [Lucene query syntax](http://lucene.apache.org/java/3_0_3/queryparsersyntax.html)
 | 
			
		||||
# for the `query_string` queries.
 | 
			
		||||
 | 
			
		||||
# For debugging our queries, we can display the JSON which is being sent to _ElasticSearch_.
 | 
			
		||||
#
 | 
			
		||||
#     {"query":{"query_string":{"query":"title:T*"}}}
 | 
			
		||||
#
 | 
			
		||||
puts "", "Query:", "-"*80
 | 
			
		||||
puts s.to_json.green
 | 
			
		||||
 | 
			
		||||
# Or better yet, we may display a complete `curl` command to recreate the request in terminal,
 | 
			
		||||
# so we can see the naked response, tweak request parameters and meditate on problems.
 | 
			
		||||
#
 | 
			
		||||
#     curl -X POST "http://localhost:9200/articles/_search?pretty=true" \
 | 
			
		||||
#          -d '{"query":{"query_string":{"query":"title:T*"}}}'
 | 
			
		||||
#
 | 
			
		||||
puts "", "Try the query in Curl:", "-"*80
 | 
			
		||||
puts s.to_curl.green
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Logging
 | 
			
		||||
 | 
			
		||||
# For debugging more complex situations, we can enable logging, so requests and responses
 | 
			
		||||
# will be logged using this `curl`-friendly format.
 | 
			
		||||
 | 
			
		||||
Tire.configure do
 | 
			
		||||
 | 
			
		||||
  # By default, at the _info_ level, only the `curl`-format of request and
 | 
			
		||||
  # basic information about the response will be logged:
 | 
			
		||||
  #
 | 
			
		||||
  #     # 2011-04-24 11:34:01:150 [CREATE] ("articles")
 | 
			
		||||
  #     #
 | 
			
		||||
  #     curl -X POST "http://localhost:9200/articles"
 | 
			
		||||
  #
 | 
			
		||||
  #     # 2011-04-24 11:34:01:152 [200]
 | 
			
		||||
  #
 | 
			
		||||
  logger 'elasticsearch.log'
 | 
			
		||||
 | 
			
		||||
  # For debugging, we can switch to the _debug_ level, which will log the complete JSON responses.
 | 
			
		||||
  #
 | 
			
		||||
  # That's very convenient if we want to post a recreation of some problem or solution
 | 
			
		||||
  # to the mailing list, IRC channel, etc.
 | 
			
		||||
  #
 | 
			
		||||
  logger 'elasticsearch.log', :level => 'debug'
 | 
			
		||||
 | 
			
		||||
  # Note that we can pass any [`IO`](http://www.ruby-doc.org/core/classes/IO.html)-compatible Ruby object as a logging device.
 | 
			
		||||
  #
 | 
			
		||||
  logger STDERR
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
### Configuration
 | 
			
		||||
 | 
			
		||||
# As we have just seen with logging, we can configure various parts of _Tire_.
 | 
			
		||||
#
 | 
			
		||||
Tire.configure do
 | 
			
		||||
 | 
			
		||||
  # First of all, we can configure the URL for _ElasticSearch_.
 | 
			
		||||
  #
 | 
			
		||||
  url "http://search.example.com"
 | 
			
		||||
 | 
			
		||||
  # Second, we may want to wrap the result items in our own class, for instance
 | 
			
		||||
  # the `Article` class set above.
 | 
			
		||||
  #
 | 
			
		||||
  wrapper Article
 | 
			
		||||
 | 
			
		||||
  # Finally, we can reset one or all configuration settings to their defaults.
 | 
			
		||||
  #
 | 
			
		||||
  reset :url
 | 
			
		||||
  reset
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Complex Searching
 | 
			
		||||
 | 
			
		||||
# Query strings are convenient for simple searches, but we may want to define our queries more expressively,
 | 
			
		||||
# using the _ElasticSearch_ [Query DSL](http://www.elasticsearch.org/guide/reference/query-dsl/index.html).
 | 
			
		||||
#
 | 
			
		||||
s = Tire.search('articles') do
 | 
			
		||||
 | 
			
		||||
  # Let's suppose we want to search for articles with specific _tags_, in our case “ruby” _or_ “python”.
 | 
			
		||||
  #
 | 
			
		||||
  query do
 | 
			
		||||
 | 
			
		||||
    # That's a great excuse to use a [_terms_](http://elasticsearch.org/guide/reference/query-dsl/terms-query.html)
 | 
			
		||||
    # query.
 | 
			
		||||
    #
 | 
			
		||||
    terms :tags, ['ruby', 'python']
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# The search, as expected, returns three articles, all tagged “ruby” — among other tags:
 | 
			
		||||
#
 | 
			
		||||
#     * Two [tags: ruby, python]
 | 
			
		||||
#     * One [tags: ruby]
 | 
			
		||||
#     * Four [tags: ruby, php]
 | 
			
		||||
#
 | 
			
		||||
puts "Test4==The search, as expected, returns three articles, all tagged “STHs” — among other tags.Has results: #{s.results.count}".yellow
 | 
			
		||||
s.results.each do |document|
 | 
			
		||||
  puts "* #{ document.title } [tags: ]"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# What if we wanted to search for articles tagged both “ruby” _and_ “python”?
 | 
			
		||||
#
 | 
			
		||||
s = Tire.search('articles') do
 | 
			
		||||
  query do
 | 
			
		||||
 | 
			
		||||
    # That's a great excuse to specify `minimum_match` for the query.
 | 
			
		||||
    #
 | 
			
		||||
    terms :tags, ['ruby', 'python'], :minimum_match => 2
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# The search, as expected, returns one article, tagged with _both_ “ruby” and “python”:
 | 
			
		||||
#
 | 
			
		||||
#     * Two [tags: ruby, python]
 | 
			
		||||
#
 | 
			
		||||
puts "Test5==The search, as expected, returns one article, tagged with _both_ 'ruby' and 'python'.Has results: #{s.results.count}".yellow
 | 
			
		||||
s.results.each do |document|
 | 
			
		||||
  puts "* #{ document.title } [tags: ]"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
#### Boolean Queries
 | 
			
		||||
 | 
			
		||||
# Quite often, we need complex queries with boolean logic.
 | 
			
		||||
# Instead of composing long query strings such as `tags:ruby OR tags:java AND NOT tags:python`,
 | 
			
		||||
# we can use the [_bool_](http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html)
 | 
			
		||||
# query.
 | 
			
		||||
 | 
			
		||||
s = Tire.search('news_bulletins') do
 | 
			
		||||
  query do
 | 
			
		||||
 | 
			
		||||
    # In _Tire_, we can build `bool` queries declaratively, as usual.
 | 
			
		||||
    boolean do
 | 
			
		||||
 | 
			
		||||
      # Let's define a `should` (`OR`) query for _ruby_,
 | 
			
		||||
      #
 | 
			
		||||
      should   { string 'title:政大' }
 | 
			
		||||
 | 
			
		||||
      # as well as for _java_,
 | 
			
		||||
      must_not   { string 'title:復興' }
 | 
			
		||||
 | 
			
		||||
      # while defining a `must_not` (`AND NOT`) query for _python_.
 | 
			
		||||
      # must_not { string 'tags:python' }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# The search returns these documents:
 | 
			
		||||
#
 | 
			
		||||
#     * One [tags: ruby]
 | 
			
		||||
#     * Three [tags: java]
 | 
			
		||||
#     * Four [tags: ruby, php]
 | 
			
		||||
puts "Test6==Boolean Queries.Has results: #{s.results.count}".yellow
 | 
			
		||||
s.results.each do |document|
 | 
			
		||||
  puts "* #{ document.title } [tags: ]"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
puts "Test7== mix and reuse Boolean Queries: #{s.results.count}".yellow
 | 
			
		||||
# The best thing about `boolean` queries is that we can very easily save these partial queries as Ruby blocks,
 | 
			
		||||
# to mix and reuse them later, since we can call the `boolean` method multiple times.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# Let's define the query for the _tags_ property,
 | 
			
		||||
#
 | 
			
		||||
tags_query = lambda do |boolean|
 | 
			
		||||
  boolean.should { string 'tags:ruby' }
 | 
			
		||||
  boolean.should { string 'tags:java' }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# ... and a query for the _published_on_ property.
 | 
			
		||||
published_on_query = lambda do |boolean|
 | 
			
		||||
  boolean.must   { string 'published_on:[2011-01-01 TO 2011-01-02]' }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Now, we can use the `tags_query` on its own.
 | 
			
		||||
#
 | 
			
		||||
Tire.search('articles') { query { boolean &tags_query } }
 | 
			
		||||
 | 
			
		||||
# Or, we can combine it with the `published_on` query.
 | 
			
		||||
#
 | 
			
		||||
Tire.search('articles') do
 | 
			
		||||
  query do
 | 
			
		||||
    boolean &tags_query
 | 
			
		||||
    boolean &published_on_query
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# _ElasticSearch_ supports many types of [queries](http://www.elasticsearch.org/guide/reference/query-dsl/).
 | 
			
		||||
#
 | 
			
		||||
# Eventually, _Tire_ will support all of them. So far, only these are supported:
 | 
			
		||||
#
 | 
			
		||||
# * [string](http://www.elasticsearch.org/guide/reference/query-dsl/query-string-query.html)
 | 
			
		||||
# * [text](http://www.elasticsearch.org/guide/reference/query-dsl/text-query.html)
 | 
			
		||||
# * [term](http://elasticsearch.org/guide/reference/query-dsl/term-query.html)
 | 
			
		||||
# * [terms](http://elasticsearch.org/guide/reference/query-dsl/terms-query.html)
 | 
			
		||||
# * [bool](http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html)
 | 
			
		||||
# * [custom_score](http://www.elasticsearch.org/guide/reference/query-dsl/custom-score-query.html)
 | 
			
		||||
# * [fuzzy](http://www.elasticsearch.org/guide/reference/query-dsl/fuzzy-query.html)
 | 
			
		||||
# * [all](http://www.elasticsearch.org/guide/reference/query-dsl/match-all-query.html)
 | 
			
		||||
# * [ids](http://www.elasticsearch.org/guide/reference/query-dsl/ids-query.html)
 | 
			
		||||
 | 
			
		||||
puts "Topic#### Faceted Search ==> SKIP".yellow
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# # _ElasticSearch_ makes it trivial to retrieve complex aggregated data from our index/database,
 | 
			
		||||
# # so called [_facets_](http://www.elasticsearch.org/guide/reference/api/search/facets/index.html).
 | 
			
		||||
 | 
			
		||||
# # Let's say we want to display article counts for every tag in the database.
 | 
			
		||||
# # For that, we'll use a _terms_ facet.
 | 
			
		||||
 | 
			
		||||
# #
 | 
			
		||||
# s = Tire.search 'articles' do
 | 
			
		||||
 | 
			
		||||
#   # We will search for articles whose title begins with letter “T”,
 | 
			
		||||
#   #
 | 
			
		||||
#   query { string 'title:T*' }
 | 
			
		||||
 | 
			
		||||
#   # and retrieve the counts “bucketed” by `tags`.
 | 
			
		||||
#   #
 | 
			
		||||
#   facet 'tags' do
 | 
			
		||||
#     terms :tags
 | 
			
		||||
#   end
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # As we see, our query has found two articles, and if you recall our articles from above,
 | 
			
		||||
# # _Two_ is tagged with “ruby” and “python”, while _Three_ is tagged with “java”.
 | 
			
		||||
# #
 | 
			
		||||
# #     Found 2 articles: Three, Two
 | 
			
		||||
# #
 | 
			
		||||
# # The counts shouldn't surprise us:
 | 
			
		||||
# #
 | 
			
		||||
# #     Counts by tag:
 | 
			
		||||
# #     -------------------------
 | 
			
		||||
# #     ruby       1
 | 
			
		||||
# #     python     1
 | 
			
		||||
# #     java       1
 | 
			
		||||
# #
 | 
			
		||||
# puts "Found #{s.results.count} articles: #{s.results.map(&:title).join(', ')}"
 | 
			
		||||
# puts "Counts by tag:", "-"*25
 | 
			
		||||
# s.results.facets['tags']['terms'].each do |f|
 | 
			
		||||
#   puts "#{f['term'].ljust(10)} #{f['count']}"
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # These counts are based on the scope of our current query.
 | 
			
		||||
# # What if we wanted to display aggregated counts by `tags` across the whole database?
 | 
			
		||||
 | 
			
		||||
# #
 | 
			
		||||
# s = Tire.search 'articles' do
 | 
			
		||||
 | 
			
		||||
#   # Let's repeat the search for “T”...
 | 
			
		||||
#   #
 | 
			
		||||
#   query { string 'title:T*' }
 | 
			
		||||
 | 
			
		||||
#   facet 'global-tags', :global => true do
 | 
			
		||||
 | 
			
		||||
#     # ...but set the `global` scope for the facet in this case.
 | 
			
		||||
#     #
 | 
			
		||||
#     terms :tags
 | 
			
		||||
#   end
 | 
			
		||||
 | 
			
		||||
#   # We can even _combine_ facets scoped to the current query
 | 
			
		||||
#   # with globally scoped facets — we'll just use a different name.
 | 
			
		||||
#   #
 | 
			
		||||
#   facet 'current-tags' do
 | 
			
		||||
#     terms :tags
 | 
			
		||||
#   end
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # Aggregated results for the current query are the same as previously:
 | 
			
		||||
# #
 | 
			
		||||
# #     Current query facets:
 | 
			
		||||
# #     -------------------------
 | 
			
		||||
# #     ruby       1
 | 
			
		||||
# #     python     1
 | 
			
		||||
# #     java       1
 | 
			
		||||
# #
 | 
			
		||||
# puts "Current query facets:", "-"*25
 | 
			
		||||
# s.results.facets['current-tags']['terms'].each do |f|
 | 
			
		||||
#   puts "#{f['term'].ljust(10)} #{f['count']}"
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # On the other hand, aggregated results for the global scope include also
 | 
			
		||||
# # tags for articles not matched by the query, such as “java” or “php”:
 | 
			
		||||
# #
 | 
			
		||||
# #     Global facets:
 | 
			
		||||
# #     -------------------------
 | 
			
		||||
# #     ruby       3
 | 
			
		||||
# #     python     1
 | 
			
		||||
# #     php        1
 | 
			
		||||
# #     java       1
 | 
			
		||||
# #
 | 
			
		||||
# puts "Global facets:", "-"*25
 | 
			
		||||
# s.results.facets['global-tags']['terms'].each do |f|
 | 
			
		||||
#   puts "#{f['term'].ljust(10)} #{f['count']}"
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # _ElasticSearch_ supports many advanced types of facets, such as those for computing statistics or geographical distance.
 | 
			
		||||
# #
 | 
			
		||||
# # Eventually, _Tire_ will support all of them. So far, only these are supported:
 | 
			
		||||
# #
 | 
			
		||||
# # * [terms](http://www.elasticsearch.org/guide/reference/api/search/facets/terms-facet.html)
 | 
			
		||||
# # * [date](http://www.elasticsearch.org/guide/reference/api/search/facets/date-histogram-facet.html)
 | 
			
		||||
# # * [range](http://www.elasticsearch.org/guide/reference/api/search/facets/range-facet.html)
 | 
			
		||||
# # * [histogram](http://www.elasticsearch.org/guide/reference/api/search/facets/histogram-facet.html)
 | 
			
		||||
# # * [statistical](http://www.elasticsearch.org/guide/reference/api/search/facets/statistical-facet.html)
 | 
			
		||||
# # * [terms_stats](http://www.elasticsearch.org/guide/reference/api/search/facets/terms-stats-facet.html)
 | 
			
		||||
# # * [query](http://www.elasticsearch.org/guide/reference/api/search/facets/query-facet.html)
 | 
			
		||||
 | 
			
		||||
# # We have seen that _ElasticSearch_ facets enable us to fetch complex aggregations from our data.
 | 
			
		||||
# #
 | 
			
		||||
# # They are frequently used for another feature, „faceted navigation“.
 | 
			
		||||
# # We can be combine query and facets with
 | 
			
		||||
# # [filters](http://elasticsearch.org/guide/reference/api/search/filter.html),
 | 
			
		||||
# # so the returned documents are restricted by certain criteria — for example to a specific category —,
 | 
			
		||||
# # but the aggregation calculations are still based on the original query.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# #### Filtered Search
 | 
			
		||||
 | 
			
		||||
# # So, let's make our search a bit more complex. Let's search for articles whose titles begin
 | 
			
		||||
# # with letter “T”, again, but filter the results, so only the articles tagged “ruby”
 | 
			
		||||
# # are returned.
 | 
			
		||||
# #
 | 
			
		||||
# s = Tire.search 'articles' do
 | 
			
		||||
 | 
			
		||||
#   # We will use just the same **query** as before.
 | 
			
		||||
#   #
 | 
			
		||||
#   query { string 'title:T*' }
 | 
			
		||||
 | 
			
		||||
#   # But we will add a _terms_ **filter** based on tags.
 | 
			
		||||
#   #
 | 
			
		||||
#   filter :terms, :tags => ['ruby']
 | 
			
		||||
 | 
			
		||||
#   # And, of course, our facet definition.
 | 
			
		||||
#   #
 | 
			
		||||
#   facet('tags') { terms :tags }
 | 
			
		||||
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # We see that only the article _Two_ (tagged “ruby” and “python”) is returned,
 | 
			
		||||
# # _not_ the article _Three_ (tagged “java”):
 | 
			
		||||
# #
 | 
			
		||||
# #     * Two [tags: ruby, python]
 | 
			
		||||
# #
 | 
			
		||||
# s.results.each do |document|
 | 
			
		||||
#   puts "* #{ document.title } [tags: ]"
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # The _count_ for article _Three_'s tags, “java”, on the other hand, _is_ in fact included:
 | 
			
		||||
# #
 | 
			
		||||
# #     Counts by tag:
 | 
			
		||||
# #     -------------------------
 | 
			
		||||
# #     ruby       1
 | 
			
		||||
# #     python     1
 | 
			
		||||
# #     java       1
 | 
			
		||||
# #
 | 
			
		||||
# puts "Counts by tag:", "-"*25
 | 
			
		||||
# s.results.facets['tags']['terms'].each do |f|
 | 
			
		||||
#   puts "#{f['term'].ljust(10)} #{f['count']}"
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# #### Sorting
 | 
			
		||||
 | 
			
		||||
# # By default, the results are sorted according to their relevancy.
 | 
			
		||||
# #
 | 
			
		||||
# s = Tire.search('articles') { query { string 'tags:ruby' } }
 | 
			
		||||
 | 
			
		||||
# s.results.each do |document|
 | 
			
		||||
#   puts "* #{ document.title } " +
 | 
			
		||||
#        "[tags: ; " +
 | 
			
		||||
 | 
			
		||||
#        # The score is available as the `_score` property.
 | 
			
		||||
#        #
 | 
			
		||||
#        "score: #{document._score}]"
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # The results:
 | 
			
		||||
# #
 | 
			
		||||
# #     * One [tags: ruby; score: 0.30685282]
 | 
			
		||||
# #     * Four [tags: ruby, php; score: 0.19178301]
 | 
			
		||||
# #     * Two [tags: ruby, python; score: 0.19178301]
 | 
			
		||||
 | 
			
		||||
# # But, what if we want to sort the results based on some other criteria,
 | 
			
		||||
# # such as published date or product price? We can do that.
 | 
			
		||||
# #
 | 
			
		||||
# s = Tire.search 'articles' do
 | 
			
		||||
 | 
			
		||||
#   # We will search for articles tagged “ruby”, again, ...
 | 
			
		||||
#   #
 | 
			
		||||
#   query { string 'tags:ruby' }
 | 
			
		||||
 | 
			
		||||
#    # ... but will sort them by their `title`, in descending order.
 | 
			
		||||
#    #
 | 
			
		||||
#   sort { by :title, 'desc' }
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # The results:
 | 
			
		||||
# #
 | 
			
		||||
# #     * Two
 | 
			
		||||
# #     * One
 | 
			
		||||
# #     * Four
 | 
			
		||||
# #
 | 
			
		||||
# s.results.each do |document|
 | 
			
		||||
#   puts "* #{ document.title }"
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # Of course, it's possible to combine more fields in the sorting definition.
 | 
			
		||||
 | 
			
		||||
# s = Tire.search 'articles' do
 | 
			
		||||
 | 
			
		||||
#   # We will just get all articles in this case.
 | 
			
		||||
#   #
 | 
			
		||||
#   query { all }
 | 
			
		||||
 | 
			
		||||
#   sort do
 | 
			
		||||
 | 
			
		||||
#     # We will sort the results by their `published_on` property in _ascending_ order (the default),
 | 
			
		||||
#     #
 | 
			
		||||
#     by :published_on
 | 
			
		||||
 | 
			
		||||
#     # and by their `title` property, in _descending_ order.
 | 
			
		||||
#     #
 | 
			
		||||
#     by :title, 'desc'
 | 
			
		||||
#   end
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # The results:
 | 
			
		||||
# #     * One         (Published on: 2011-01-01)
 | 
			
		||||
# #     * Two         (Published on: 2011-01-02)
 | 
			
		||||
# #     * Three       (Published on: 2011-01-02)
 | 
			
		||||
# #     * Four        (Published on: 2011-01-03)
 | 
			
		||||
# #
 | 
			
		||||
# s.results.each do |document|
 | 
			
		||||
#   puts "* #{ document.title.ljust(10) }  (Published on: #{ document.published_on })"
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# #### Highlighting
 | 
			
		||||
 | 
			
		||||
# # Often, we want to highlight the snippets matching our query in the displayed results.
 | 
			
		||||
# # _ElasticSearch_ provides rich
 | 
			
		||||
# # [highlighting](http://www.elasticsearch.org/guide/reference/api/search/highlighting.html)
 | 
			
		||||
# # features, and _Tire_ makes them trivial to use.
 | 
			
		||||
# #
 | 
			
		||||
# s = Tire.search 'articles' do
 | 
			
		||||
 | 
			
		||||
#   # Let's search for documents containing word “Two” in their titles,
 | 
			
		||||
#   query { string 'title:Two' }
 | 
			
		||||
 | 
			
		||||
#    # and instruct _ElasticSearch_ to highlight relevant snippets.
 | 
			
		||||
#    #
 | 
			
		||||
#   highlight :title
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # The results:
 | 
			
		||||
# #     Title: Two; Highlighted: <em>Two</em>
 | 
			
		||||
# #
 | 
			
		||||
# s.results.each do |document|
 | 
			
		||||
#   puts "Title: #{ document.title }; Highlighted: #{document.highlight.title}"
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # We can configure many options for highlighting, such as:
 | 
			
		||||
# #
 | 
			
		||||
# s = Tire.search 'articles' do
 | 
			
		||||
#   query { string 'title:Two' }
 | 
			
		||||
 | 
			
		||||
#   # • specify the fields to highlight
 | 
			
		||||
#   #
 | 
			
		||||
#   highlight :title, :body
 | 
			
		||||
 | 
			
		||||
#   # • specify their individual options
 | 
			
		||||
#   #
 | 
			
		||||
#   highlight :title, :body => { :number_of_fragments => 0 }
 | 
			
		||||
 | 
			
		||||
#   # • or specify global highlighting options, such as the wrapper tag
 | 
			
		||||
#   #
 | 
			
		||||
#   highlight :title, :body, :options => { :tag => '<strong class="highlight">' }
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# #### Percolation
 | 
			
		||||
 | 
			
		||||
# # _ElasticSearch_ comes with one very interesting, and rather unique feature:
 | 
			
		||||
# # [_percolation_](http://www.elasticsearch.org/guide/reference/api/percolate.html).
 | 
			
		||||
 | 
			
		||||
# # It works in a „reverse search“ manner to regular search workflow of adding
 | 
			
		||||
# # documents to the index and then querying them.
 | 
			
		||||
# # Percolation allows us to register a query, and ask if a specific document
 | 
			
		||||
# # matches it, either on demand, or immediately as the document is being indexed.
 | 
			
		||||
 | 
			
		||||
# # Let's review an example for an index named _weather_.
 | 
			
		||||
# # We will register three queries for percolation against this index.
 | 
			
		||||
# #
 | 
			
		||||
# index = Tire.index('weather') do
 | 
			
		||||
#   delete
 | 
			
		||||
#   create
 | 
			
		||||
 | 
			
		||||
#   # First, a query named _warning_,
 | 
			
		||||
#   #
 | 
			
		||||
#   register_percolator_query('warning', :tags => ['warning']) { string 'warning OR severe OR extreme' }
 | 
			
		||||
 | 
			
		||||
#   # a query named _tsunami_,
 | 
			
		||||
#   #
 | 
			
		||||
#   register_percolator_query('tsunami', :tags => ['tsunami']) { string 'tsunami' }
 | 
			
		||||
 | 
			
		||||
#   # and a query named _floods_.
 | 
			
		||||
#   #
 | 
			
		||||
#   register_percolator_query('floods',  :tags => ['floods'])  { string 'flood*' }
 | 
			
		||||
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
# # Notice, that we have added a _tags_ field to the query document, because it behaves
 | 
			
		||||
# # just like any other document in _ElasticSearch_.
 | 
			
		||||
 | 
			
		||||
# # We will refresh the `_percolator` index for immediate access.
 | 
			
		||||
# #
 | 
			
		||||
# Tire.index('_percolator').refresh
 | 
			
		||||
 | 
			
		||||
# # Now, let's _percolate_ a document containing some trigger words against all registered queries.
 | 
			
		||||
# #
 | 
			
		||||
# matches = index.percolate(:message => '[Warning] Extreme flooding expected after tsunami wave.')
 | 
			
		||||
 | 
			
		||||
# # The result will contain, unsurprisingly, names of all the three registered queries:
 | 
			
		||||
# #
 | 
			
		||||
# #     Matching queries: ["floods", "tsunami", "warning"]
 | 
			
		||||
# #
 | 
			
		||||
# puts "Matching queries: " + matches.inspect
 | 
			
		||||
 | 
			
		||||
# # We can filter the executed queries with a regular _ElasticSearch_ query passed as a block to
 | 
			
		||||
# # the `percolate` method.
 | 
			
		||||
# #
 | 
			
		||||
# matches = index.percolate(:message => '[Warning] Extreme flooding expected after tsunami wave.') do
 | 
			
		||||
#             # Let's use a _terms_ query against the `tags` field.
 | 
			
		||||
#             term :tags, 'tsunami'
 | 
			
		||||
#           end
 | 
			
		||||
 | 
			
		||||
# # In this case, the result will contain only the name of the “tsunami” query.
 | 
			
		||||
# #
 | 
			
		||||
# #     Matching queries: ["tsunami"]
 | 
			
		||||
# #
 | 
			
		||||
# puts "Matching queries: " + matches.inspect
 | 
			
		||||
 | 
			
		||||
# # What if we percolate another document, without the “tsunami” trigger word?
 | 
			
		||||
# #
 | 
			
		||||
# matches = index.percolate(:message => '[Warning] Extreme temperatures expected.') { term :tags, 'tsunami' }
 | 
			
		||||
 | 
			
		||||
# # As expected, we will get an empty array:
 | 
			
		||||
# #
 | 
			
		||||
# #     Matching queries: []
 | 
			
		||||
# #
 | 
			
		||||
# puts "Matching queries: " + matches.inspect
 | 
			
		||||
 | 
			
		||||
# # Well, that's of course immensely useful for real-time search systems. But, there's more.
 | 
			
		||||
# # We can _percolate_ a document _at the same time_ it is being stored in the index,
 | 
			
		||||
# # getting back a list of matching queries.
 | 
			
		||||
 | 
			
		||||
# # Let's store a document with some trigger words in the index, and mark it for percolation.
 | 
			
		||||
# #
 | 
			
		||||
# response = index.store :message => '[Warning] Severe floods expected after tsunami wave.', :percolate => true
 | 
			
		||||
 | 
			
		||||
# # We will get the names of all matching queries in response.
 | 
			
		||||
# #
 | 
			
		||||
# #     Matching queries: ["floods", "tsunami", "warning"]
 | 
			
		||||
# #
 | 
			
		||||
# puts "Matching queries: " + response['matches'].inspect
 | 
			
		||||
 | 
			
		||||
# # As with the _percolate_ example, we can filter the executed queries.
 | 
			
		||||
# #
 | 
			
		||||
# response = index.store :message => '[Warning] Severe floods expected after tsunami wave.',
 | 
			
		||||
#                        # Let's use a simple string query for the “tsunami” tag.
 | 
			
		||||
#                        :percolate => 'tags:tsunami'
 | 
			
		||||
 | 
			
		||||
# # Unsurprisingly, the response will contain just the name of the “tsunami” query.
 | 
			
		||||
# #
 | 
			
		||||
# #     Matching queries: ["tsunami"]
 | 
			
		||||
# #
 | 
			
		||||
# puts "Matching queries: " + response['matches'].inspect
 | 
			
		||||
 | 
			
		||||
# ### ActiveModel Integration
 | 
			
		||||
 | 
			
		||||
# # As you can see, [_Tire_](https://github.com/karmi/tire) supports the
 | 
			
		||||
# # main features of _ElasticSearch_ in Ruby.
 | 
			
		||||
# #
 | 
			
		||||
# # It allows you to create and delete indices, add documents, search them, retrieve the facets, highlight the results,
 | 
			
		||||
# # and comes with a usable logging facility.
 | 
			
		||||
# #
 | 
			
		||||
# # Of course, the holy grail of any search library is easy, painless integration with your Ruby classes, and,
 | 
			
		||||
# # most importantly, with ActiveRecord/ActiveModel classes.
 | 
			
		||||
# #
 | 
			
		||||
# # Please, check out the [README](https://github.com/karmi/tire/tree/master#readme) file for instructions
 | 
			
		||||
# # how to include _Tire_-based search in your models..
 | 
			
		||||
# #
 | 
			
		||||
# # Send any feedback via Github issues, or ask questions in the [#elasticsearch](irc://irc.freenode.net/#elasticsearch) IRC channel.
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +9,13 @@ class Panel::Announcement::FrontEnd::BulletinsController < OrbitWidgetController
 | 
			
		|||
  # GET /bulletins.xml
 | 
			
		||||
  
 | 
			
		||||
  def index
 | 
			
		||||
  
 | 
			
		||||
    if  !params[:search_query].blank?
 | 
			
		||||
      search_cond =  {:is_checked=>true,:is_hidden=>false}
 | 
			
		||||
      search_cond.merge!({:bulletin_category_id => "#{params[:category_id]}" }) if  !params[:category_id].blank?
 | 
			
		||||
      search = Redis::Search.query("Bulletin", params[:search_query], :conditions =>search_cond)
 | 
			
		||||
      search_result = search.collect{|t| t["id"]}
 | 
			
		||||
      @news_bulletins = Bulletin.all.can_display.any_in(_id:search_result).page( params[:page_main]).per(10)
 | 
			
		||||
    else
 | 
			
		||||
      date_now = Time.now
 | 
			
		||||
      if !params[:category_id].blank?
 | 
			
		||||
        @bulletins = Bulletin.all.can_display.where(:bulletin_category_id => params[:category_id]).any_of( {deadline: nil,:postdate.lte => date_now} , {:deadline.gte => date_now,:postdate.lte => date_now} ).desc( :is_top, :postdate).page( params[:page_main]).per(10)
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +27,7 @@ class Panel::Announcement::FrontEnd::BulletinsController < OrbitWidgetController
 | 
			
		|||
      else
 | 
			
		||||
        @bulletins = Bulletin.all.can_display.any_of( {deadline: nil,:postdate.lte => date_now} , {:deadline.gte => date_now,:postdate.lte => date_now} ).desc( :is_top, :postdate).page( params[:page_main]).per(10)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
	  
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,9 @@ class Panel::Announcement::Widget::BulletinsController < OrbitWidgetController
 | 
			
		|||
    get_categorys
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  def bulletins_search_block
 | 
			
		||||
    
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  protected
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,10 @@
 | 
			
		|||
# encoding: utf-8
 | 
			
		||||
 | 
			
		||||
# require "impressionist"
 | 
			
		||||
class Bulletin
 | 
			
		||||
  include Mongoid::Document
 | 
			
		||||
  include Mongoid::Timestamps
 | 
			
		||||
  include Mongoid::MultiParameterAttributes
 | 
			
		||||
  include Redis::Search
 | 
			
		||||
  include Impressionist::Impressionable
 | 
			
		||||
 | 
			
		||||
  BelongsToCategory =  :bulletin_category
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +14,7 @@ class Bulletin
 | 
			
		|||
 | 
			
		||||
  scope :searchable,where(:is_checked=>true,:is_hidden=>false,:is_pending=>false)
 | 
			
		||||
 | 
			
		||||
  is_impressionable :counter_cache => { :column_name => :view_count }
 | 
			
		||||
  # is_impressionable :counter_cache => { :column_name => :view_count }
 | 
			
		||||
 | 
			
		||||
  has_one :title, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy
 | 
			
		||||
  has_one :subtitle, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +63,29 @@ class Bulletin
 | 
			
		|||
  after_save :save_bulletin_links
 | 
			
		||||
  after_save :save_bulletin_files
 | 
			
		||||
 | 
			
		||||
 redis_search_index(:title_field => :s_title,
 | 
			
		||||
                      :alias_field =>:s_title_en ,
 | 
			
		||||
                     :score_field => :view_count,
 | 
			
		||||
                     :condition_fields => [:is_checked,:is_hidden,:bulletin_category_id],
 | 
			
		||||
                     :ext_fields => [])
 | 
			
		||||
#  def gen_title_for_search
 | 
			
		||||
#   # [s_title,s_title_en,s_text_en,s_text_zh_tw].join(' ')
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
 def s_title
 | 
			
		||||
   self.title.zh_tw
 | 
			
		||||
 end
 | 
			
		||||
 | 
			
		||||
 def s_title_en
 | 
			
		||||
   self.title.en
 | 
			
		||||
 end
 | 
			
		||||
 | 
			
		||||
 # def s_text_en
 | 
			
		||||
 #  Nokogiri::HTML(self.text.en).text
 | 
			
		||||
 # end
 | 
			
		||||
 # def s_text_zh_tw
 | 
			
		||||
 #  Nokogiri::HTML(self.text.zh_tw).text
 | 
			
		||||
 # end
 | 
			
		||||
 | 
			
		||||
# scope :currently_available, lambda { |category, limit|
 | 
			
		||||
#     # limit ||= 5
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
<%= form_tag panel_announcement_front_end_bulletins_path, method: :get do %>
 | 
			
		||||
  <p>
 | 
			
		||||
    <%= text_field_tag :search_query, params[:search_query] %>
 | 
			
		||||
    <%= submit_tag "Search", name: nil %>
 | 
			
		||||
  </p>
 | 
			
		||||
<% end %>
 | 
			
		||||
| 
						 | 
				
			
			@ -44,6 +44,7 @@ Rails.application.routes.draw do
 | 
			
		|||
        match "reload_bulletins" => "bulletins#reload_bulletins"
 | 
			
		||||
        match "reload_web_links" => "bulletins#reload_web_links"
 | 
			
		||||
        match "bulletins_side_bar" => "bulletins#bulletins_side_bar"
 | 
			
		||||
        match "bulletins_search_block" => "bulletins#bulletins_search_block"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,21 +10,10 @@ class Panel::News::FrontEnd::NewsBulletinsController < OrbitWidgetController
 | 
			
		|||
  
 | 
			
		||||
  def index
 | 
			
		||||
    if !params[:search_query].blank?
 | 
			
		||||
      search_query =params[:search_query].gsub(/"/,"").split(" ")
 | 
			
		||||
 | 
			
		||||
        words_query = lambda do |boolean|
 | 
			
		||||
          search_query.each do |word|
 | 
			
		||||
            boolean.should   { string "title:#{word}" }
 | 
			
		||||
             #boolean.should   { string "sub_title:#{word}" }
 | 
			
		||||
             #boolean.should   { string "text:#{word}" }
 | 
			
		||||
           end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
      search_result=Tire.search('news_bulletins') do
 | 
			
		||||
         query {boolean &words_query  } 
 | 
			
		||||
         #raise to_curl
 | 
			
		||||
      end.results.collect{|t| t.id}
 | 
			
		||||
 | 
			
		||||
      search_cond =  {:is_checked=>true,:is_hidden=>false}
 | 
			
		||||
      search_cond.merge!({:news_bulletin_category_id => "#{params[:category_id]}" }) if  !params[:category_id].blank?
 | 
			
		||||
      search = Redis::Search.query("NewsBulletin", params[:search_query], :conditions =>search_cond)
 | 
			
		||||
      search_result = search.collect{|t| t["id"]}
 | 
			
		||||
      @news_bulletins = NewsBulletin.all.can_display.any_in(_id:search_result).page( params[:page_main]).per(10)
 | 
			
		||||
    else
 | 
			
		||||
        date_now = Time.now
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +39,7 @@ class Panel::News::FrontEnd::NewsBulletinsController < OrbitWidgetController
 | 
			
		|||
    else
 | 
			
		||||
      @news_bulletin = NewsBulletin.all.can_display.where(_id: params[:id]).first
 | 
			
		||||
      unless @news_bulletin.disable?
 | 
			
		||||
        impressionist(@news_bulletin)
 | 
			
		||||
        # impressionist(@news_bulletin)
 | 
			
		||||
        get_categorys
 | 
			
		||||
      else
 | 
			
		||||
        render :nothing => true, :status => 403 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,8 +47,9 @@ caches_page :home_banner
 | 
			
		|||
    get_categorys
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # def news_bulletins_search_block
 | 
			
		||||
  # end
 | 
			
		||||
  def news_bulletins_search_block
 | 
			
		||||
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def home_banner
 | 
			
		||||
    if !params[:category_id].blank?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ class NewsBulletin
 | 
			
		|||
  include Mongoid::Document
 | 
			
		||||
  include Mongoid::Timestamps
 | 
			
		||||
  include Mongoid::MultiParameterAttributes  
 | 
			
		||||
  include Redis::Search
 | 
			
		||||
  include Impressionist::Impressionable
 | 
			
		||||
 | 
			
		||||
  BelongsToCategory =  :news_bulletin_category
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +17,7 @@ class NewsBulletin
 | 
			
		|||
 | 
			
		||||
  scope :searchable,where(:is_checked=>true,:is_hidden=>false,:is_pending=>false)
 | 
			
		||||
 | 
			
		||||
  is_impressionable :counter_cache => { :column_name => :view_count }
 | 
			
		||||
  # is_impressionable :counter_cache => { :column_name => :view_count }
 | 
			
		||||
 | 
			
		||||
  has_one :title, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy
 | 
			
		||||
  has_one :subtitle, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy
 | 
			
		||||
| 
						 | 
				
			
			@ -89,32 +90,29 @@ class NewsBulletin
 | 
			
		|||
    "news_bulletin"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def to_indexed_json       
 | 
			
		||||
      titles = title.zh_tw #+ title.en
 | 
			
		||||
      sub_titles = subtitle.zh_tw #+ subtitle.en
 | 
			
		||||
      texts = text.zh_tw #+ text.en
 | 
			
		||||
      {
 | 
			
		||||
        :_id => _id,
 | 
			
		||||
        :title =>  Nokogiri::HTML(titles).text,
 | 
			
		||||
        :sub_title => Nokogiri::HTML(sub_titles).text,
 | 
			
		||||
        :text => Nokogiri::HTML(texts).text
 | 
			
		||||
      }.to_json
 | 
			
		||||
 redis_search_index(:title_field => :s_title,
 | 
			
		||||
                      :alias_field =>  :s_title_en,
 | 
			
		||||
                     :score_field => :view_count,
 | 
			
		||||
                     :condition_fields => [:is_checked,:is_hidden,:news_bulletin_category_id],
 | 
			
		||||
                     :ext_fields =>[])
 | 
			
		||||
#  def gen_title_for_search
 | 
			
		||||
#   # [s_title,s_title_en,s_text_en,s_text_zh_tw].join(' ')
 | 
			
		||||
# end
 | 
			
		||||
 | 
			
		||||
 def s_title
 | 
			
		||||
   #self.title.zh_tw
 | 
			
		||||
 end
 | 
			
		||||
 | 
			
		||||
  def self.search( search = nil, category_id = nil )
 | 
			
		||||
    if category_id.to_s.size > 0 and search.to_s.size > 0
 | 
			
		||||
      key = /#{search}/
 | 
			
		||||
      find(:all, :conditions => {title: key, news_bulletin_category_id: category_id}).desc( :is_top, :postdate )
 | 
			
		||||
    elsif category_id.to_s.size > 0 and search.to_s.size < 1
 | 
			
		||||
      find(:all, :conditions => {news_bulletin_category_id: category_id}).desc( :is_top, :postdate )
 | 
			
		||||
    elsif search.to_s.size > 0 and category_id.to_s.size < 1
 | 
			
		||||
      key = /#{search}/
 | 
			
		||||
      find(:all, :conditions => {title: key}).desc( :is_top, :postdate )
 | 
			
		||||
    else
 | 
			
		||||
      find(:all).desc( :is_top, :postdate)
 | 
			
		||||
    end
 | 
			
		||||
 def s_title_en
 | 
			
		||||
   #self.title.en
 | 
			
		||||
 end
 | 
			
		||||
 | 
			
		||||
 # def s_text_en
 | 
			
		||||
 #  Nokogiri::HTML(self.text.en).text
 | 
			
		||||
 # end
 | 
			
		||||
 # def s_text_zh_tw
 | 
			
		||||
 #  Nokogiri::HTML(self.text.zh_tw).text
 | 
			
		||||
 # end
 | 
			
		||||
 | 
			
		||||
  def self.widget_datas( category_id = nil )
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
<%= form_tag panel_news_front_end_news_bulletins_path, method: :get do %>
 | 
			
		||||
  <p>
 | 
			
		||||
    <%= text_field_tag :search_query, params[:search_query] %>
 | 
			
		||||
    <%= hidden_field_tag :category_id, params[:category_id] %>
 | 
			
		||||
    <%= submit_tag "Search", name: nil %>
 | 
			
		||||
  </p>
 | 
			
		||||
<% end %>
 | 
			
		||||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ platforms :jruby do
 | 
			
		|||
end
 | 
			
		||||
 | 
			
		||||
platforms :ruby, :mswin, :mingw do
 | 
			
		||||
  # gem 'sqlite3'
 | 
			
		||||
  gem 'sqlite3'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
gemspec
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,22 +29,17 @@ module Impressionist
 | 
			
		|||
    end
 | 
			
		||||
 | 
			
		||||
    def impressionist_count(options={})
 | 
			
		||||
      # options.reverse_merge!(:filter=>:request_hash, :start_date=>nil, :end_date=>Time.now)
 | 
			
		||||
      # imps = options[:start_date].blank? ? impressions : impressions.where("created_at>=? and created_at<=?",options[:start_date],options[:end_date])
 | 
			
		||||
      # options[:filter] == :all ? imps.count : imps.count(options[:filter], :distinct => true)
 | 
			
		||||
      options.reverse_merge!(:filter => :request_hash, :start_date => nil, :end_date => Time.now)
 | 
			
		||||
      imps = options[:start_date].blank? ? impressions : impressions.where(:created_at.gte => options[:start_date], :created_at.lte => options[:end_date])
 | 
			
		||||
      options[:filter] == :all ? imps.count : imps.distinct(options[:filter]).count
 | 
			
		||||
      options.reverse_merge!(:filter=>:request_hash, :start_date=>nil, :end_date=>Time.now)
 | 
			
		||||
      imps = options[:start_date].blank? ? impressions : impressions.where("created_at>=? and created_at<=?",options[:start_date],options[:end_date])
 | 
			
		||||
      options[:filter] == :all ? imps.count : imps.count(options[:filter], :distinct => true)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def update_impressionist_counter_cache
 | 
			
		||||
      # cache_options = self.class.impressionist_counter_cache_options
 | 
			
		||||
      # column_name = cache_options[:column_name].to_sym
 | 
			
		||||
      # count = cache_options[:unique] ? impressionist_count(:filter => :ip_address) : impressionist_count
 | 
			
		||||
      # update_attribute(column_name, count)
 | 
			
		||||
      cache_options = self.class.impressionist_counter_cache_options
 | 
			
		||||
      column_name = cache_options[:column_name].to_sym
 | 
			
		||||
      update_attribute(column_name, self.send(cache_options[:column_name]) + 1)
 | 
			
		||||
      count = cache_options[:unique] ? impressionist_count(:filter => :ip_address) : impressionist_count
 | 
			
		||||
      old_count = send(column_name) || 0
 | 
			
		||||
      self.class.update_counters(id, column_name => (count - old_count))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # OLD METHODS - DEPRECATE IN V0.5
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ module Impressionist
 | 
			
		|||
      def copy_config_file
 | 
			
		||||
        template 'impression.rb', 'config/initializers/impression.rb'
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
# Use this hook to configure impressionist parameters
 | 
			
		||||
Impressionist.setup do |config|
 | 
			
		||||
  # Define ORM. Could be :active_record (default) and :mongo_mapper
 | 
			
		||||
  # Define ORM. Could be :active_record (default), :mongo_mapper or :mongoid
 | 
			
		||||
  # config.orm = :active_record
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								vendor/impressionist/lib/impressionist/controllers/mongoid/impressionist_controller.rb
								
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										10
									
								
								vendor/impressionist/lib/impressionist/controllers/mongoid/impressionist_controller.rb
								
								
								
									vendored
								
								
									Normal file
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
ImpressionistController::InstanceMethods.send(:define_method, :direct_create_statement) do |query_params={}|
 | 
			
		||||
	# creates a statment hash that contains default values for creating an impression.
 | 
			
		||||
	# if :impressionable_id is a valid ObjectId then convert it into one
 | 
			
		||||
	base = (defined? Moped) ? Moped::BSON : BSON
 | 
			
		||||
	query_params.reverse_merge!(
 | 
			
		||||
		:impressionable_type => controller_name.singularize.camelize,
 | 
			
		||||
		:impressionable_id=> !base::ObjectId.legal?(params[:id]) ? params[:id] : base::ObjectId.from_string(params[:id])
 | 
			
		||||
	)
 | 
			
		||||
	associative_create_statement(query_params)
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ module Impressionist
 | 
			
		|||
  class Engine < Rails::Engine
 | 
			
		||||
    initializer 'impressionist.model' do |app|
 | 
			
		||||
      require "#{root}/app/models/impressionist/impressionable.rb"
 | 
			
		||||
      if Impressionist.orm == :active_record
 | 
			
		||||
      if Impressionist.orm == :active_record && defined? ActiveRecord
 | 
			
		||||
        require "impressionist/models/active_record/impression.rb"
 | 
			
		||||
        require "impressionist/models/active_record/impressionist/impressionable.rb"
 | 
			
		||||
        ActiveRecord::Base.send(:include, Impressionist::Impressionable)
 | 
			
		||||
| 
						 | 
				
			
			@ -14,13 +14,16 @@ module Impressionist
 | 
			
		|||
        require "impressionist/models/mongo_mapper/impressionist/impressionable.rb"
 | 
			
		||||
        MongoMapper::Document.plugin Impressionist::Impressionable
 | 
			
		||||
      elsif Impressionist.orm == :mongoid
 | 
			
		||||
        require "impressionist/models/mongoid/impression.rb"
 | 
			
		||||
        require "impressionist/models/mongoid/impressionist/impressionable.rb"
 | 
			
		||||
        # Mongoid::Document Impressionist::Impressionable
 | 
			
		||||
        require 'impressionist/models/mongoid/impression.rb'
 | 
			
		||||
        require 'impressionist/models/mongoid/impressionist/impressionable.rb'
 | 
			
		||||
        Mongoid::Document.send(:include, Impressionist::Impressionable)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    initializer 'impressionist.controller' do
 | 
			
		||||
      if Impressionist.orm == :mongoid
 | 
			
		||||
          require 'impressionist/controllers/mongoid/impressionist_controller.rb'
 | 
			
		||||
      end
 | 
			
		||||
      ActiveSupport.on_load(:action_controller) do
 | 
			
		||||
        include ImpressionistController::InstanceMethods
 | 
			
		||||
        extend ImpressionistController::ClassMethods
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,8 +2,12 @@ class Impression
 | 
			
		|||
  include Mongoid::Document
 | 
			
		||||
  include Mongoid::Timestamps
 | 
			
		||||
 | 
			
		||||
  field :impressionable_type
 | 
			
		||||
  field :impressionable_id
 | 
			
		||||
  attr_accessible :impressionable_type, :impressionable_field, :impressionable_id, :user_id,
 | 
			
		||||
  :controller_name, :action_name, :view_name, :request_hash, :ip_address,
 | 
			
		||||
  :session_hash, :message, :referrer
 | 
			
		||||
 | 
			
		||||
  belongs_to :impressionable, polymorphic: true
 | 
			
		||||
 | 
			
		||||
  field :user_id
 | 
			
		||||
  field :controller_name
 | 
			
		||||
  field :action_name
 | 
			
		||||
| 
						 | 
				
			
			@ -14,26 +18,15 @@ class Impression
 | 
			
		|||
  field :message
 | 
			
		||||
  field :referrer
 | 
			
		||||
 | 
			
		||||
  belongs_to :impressionable, :polymorphic => true
 | 
			
		||||
 | 
			
		||||
  after_save :update_impressions_counter_cache
 | 
			
		||||
 | 
			
		||||
  def self.impressionist_count(options={})
 | 
			
		||||
    options.reverse_merge!(:filter => :request_hash, :start_date => nil, :end_date => Time.now)
 | 
			
		||||
    imps = options[:start_date].blank? ? impressions : impressions.where(:created_at.gte => options[:start_date], :created_at.lte => options[:end_date])
 | 
			
		||||
    options[:filter] == :all ? imps.count : imps.distinct(options[:filter]).count
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def update_impressions_counter_cache
 | 
			
		||||
    if self.referrer
 | 
			
		||||
      impressionable_class = self.impressionable_type.constantize
 | 
			
		||||
  set_callback(:create, :after) do |doc|
 | 
			
		||||
    unless impressionable_id.nil?
 | 
			
		||||
      impressionable_class = doc.impressionable_type.constantize
 | 
			
		||||
 | 
			
		||||
      if impressionable_class.impressionist_counter_cache_options
 | 
			
		||||
        resouce = impressionable_class.find(self.impressionable_id)
 | 
			
		||||
        resouce.try(:update_impressionist_counter_cache)
 | 
			
		||||
        resource = impressionable_class.find(doc.impressionable_id)
 | 
			
		||||
        resource.try(:update_impressionist_counter_cache)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,9 +4,49 @@ module Impressionist
 | 
			
		|||
 | 
			
		||||
    module ClassMethods
 | 
			
		||||
      def is_impressionable(options={})
 | 
			
		||||
        has_many :impressions, :as => :impressionable, :dependent => :destroy
 | 
			
		||||
      	has_many :impressions, as: :impressionable, dependent: :destroy
 | 
			
		||||
        	@impressionist_cache_options = options[:counter_cache]
 | 
			
		||||
        	if !@impressionist_cache_options.nil?
 | 
			
		||||
        		opts = impressionist_counter_cache_options
 | 
			
		||||
        		field opts[:column_name], type: Integer
 | 
			
		||||
        	end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def impressionist_counter_cache_options
 | 
			
		||||
        if @impressionist_cache_options
 | 
			
		||||
          options = { :column_name => :impressions_count, :unique => false }
 | 
			
		||||
          options.merge!(@impressionist_cache_options) if @impressionist_cache_options.is_a?(Hash)
 | 
			
		||||
          options
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def impressionist_counter_caching?
 | 
			
		||||
        impressionist_counter_cache_options.present?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def counter_caching?
 | 
			
		||||
        ::ActiveSupport::Deprecation.warn("#counter_caching? is deprecated; please use #impressionist_counter_caching? instead")
 | 
			
		||||
        impressionist_counter_caching?
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def impressionable?
 | 
			
		||||
      true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def impressionist_count(options={})
 | 
			
		||||
      options.reverse_merge!(:filter=>:request_hash, :start_date=>nil, :end_date=>Time.now)
 | 
			
		||||
      imps = options[:start_date].blank? ? impressions : impressions.between(created_at: options[:start_date]..options[:end_date])
 | 
			
		||||
      options[:filter] == :all ? imps.count : imps.where(options[:filter].ne => nil).count
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def update_impressionist_counter_cache
 | 
			
		||||
      cache_options = self.class.impressionist_counter_cache_options
 | 
			
		||||
      column_name = cache_options[:column_name].to_sym
 | 
			
		||||
      count = cache_options[:unique] ? impressionist_count(:filter => :ip_address) : impressionist_count
 | 
			
		||||
      old_count = send(column_name) || 0
 | 
			
		||||
      self.inc(column_name, (count - old_count))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +38,13 @@ describe Impression do
 | 
			
		|||
         @widget.reload
 | 
			
		||||
       }.should change(@widget, :impressions_count).from(0).to(1)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "should not update the timestamp on the impressable" do
 | 
			
		||||
      lambda {
 | 
			
		||||
         @widget.impressions.create(:request_hash => 'abcd1234')
 | 
			
		||||
         @widget.reload
 | 
			
		||||
       }.should_not change(@widget, :updated_at)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +0,0 @@
 | 
			
		|||
README.rdoc
 | 
			
		||||
lib/**/*.rb
 | 
			
		||||
bin/*
 | 
			
		||||
features/**/*.feature
 | 
			
		||||
LICENSE
 | 
			
		||||
| 
						 | 
				
			
			@ -1,20 +0,0 @@
 | 
			
		|||
Copyright (c) 2009 jugyo
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining
 | 
			
		||||
a copy of this software and associated documentation files (the
 | 
			
		||||
"Software"), to deal in the Software without restriction, including
 | 
			
		||||
without limitation the rights to use, copy, modify, merge, publish,
 | 
			
		||||
distribute, sublicense, and/or sell copies of the Software, and to
 | 
			
		||||
permit persons to whom the Software is furnished to do so, subject to
 | 
			
		||||
the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be
 | 
			
		||||
included in all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 | 
			
		||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 | 
			
		||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | 
			
		||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
| 
						 | 
				
			
			@ -1,53 +0,0 @@
 | 
			
		|||
sunspot_mongoid
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
A Sunspot wrapper for Mongoid.
 | 
			
		||||
 | 
			
		||||
Install
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
    gem install sunspot_mongoid
 | 
			
		||||
 | 
			
		||||
Examples
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
    class Post
 | 
			
		||||
      include Mongoid::Document
 | 
			
		||||
      field :title
 | 
			
		||||
 | 
			
		||||
      include Sunspot::Mongoid
 | 
			
		||||
      searchable do
 | 
			
		||||
        text :title
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
For Rails3
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
### as gem:
 | 
			
		||||
 | 
			
		||||
add a gem to Gemfile as following,
 | 
			
		||||
 | 
			
		||||
    gem 'sunspot_mongoid'
 | 
			
		||||
 | 
			
		||||
### as plugin:
 | 
			
		||||
 | 
			
		||||
add gems to Gemfile as following,
 | 
			
		||||
 | 
			
		||||
    gem 'sunspot'
 | 
			
		||||
    gem 'sunspot_rails'
 | 
			
		||||
 | 
			
		||||
and install sunspot_mongoid as rails plugin,
 | 
			
		||||
 | 
			
		||||
    rails plugin install git://github.com/jugyo/sunspot_mongoid.git
 | 
			
		||||
 | 
			
		||||
Links
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
* [sunspot](http://github.com/outoftime/sunspot)
 | 
			
		||||
* [sunspot_rails](http://github.com/outoftime/sunspot/tree/master/sunspot_rails/)
 | 
			
		||||
 | 
			
		||||
Copyright
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2010 jugyo. See LICENSE for details.
 | 
			
		||||
| 
						 | 
				
			
			@ -1,57 +0,0 @@
 | 
			
		|||
require 'rubygems'
 | 
			
		||||
require 'rake'
 | 
			
		||||
 | 
			
		||||
begin
 | 
			
		||||
  require 'jeweler'
 | 
			
		||||
  Jeweler::Tasks.new do |gem|
 | 
			
		||||
    gem.name = "sunspot_mongoid"
 | 
			
		||||
    gem.summary = %Q{A Sunspot wrapper for Mongoid.}
 | 
			
		||||
    gem.description = %Q{A Sunspot wrapper for Mongoid that is like sunspot_rails.}
 | 
			
		||||
    gem.email = "jugyo.org@gmail.com"
 | 
			
		||||
    gem.homepage = "http://github.com/jugyo/sunspot_mongoid"
 | 
			
		||||
    gem.authors = ["jugyo"]
 | 
			
		||||
    gem.add_runtime_dependency "mongoid", ">= 0"
 | 
			
		||||
    gem.add_runtime_dependency "sunspot", ">= 1.1.0"
 | 
			
		||||
    gem.add_runtime_dependency "sunspot_rails", ">= 1.1.0"
 | 
			
		||||
    gem.add_development_dependency "shoulda", ">= 0"
 | 
			
		||||
    gem.add_development_dependency "rr", ">= 0"
 | 
			
		||||
    # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
 | 
			
		||||
  end
 | 
			
		||||
  Jeweler::GemcutterTasks.new
 | 
			
		||||
rescue LoadError
 | 
			
		||||
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
require 'rake/testtask'
 | 
			
		||||
Rake::TestTask.new(:test) do |test|
 | 
			
		||||
  test.libs << 'lib' << 'test'
 | 
			
		||||
  test.pattern = 'test/**/test_*.rb'
 | 
			
		||||
  test.verbose = true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
begin
 | 
			
		||||
  require 'rcov/rcovtask'
 | 
			
		||||
  Rcov::RcovTask.new do |test|
 | 
			
		||||
    test.libs << 'test'
 | 
			
		||||
    test.pattern = 'test/**/test_*.rb'
 | 
			
		||||
    test.verbose = true
 | 
			
		||||
  end
 | 
			
		||||
rescue LoadError
 | 
			
		||||
  task :rcov do
 | 
			
		||||
    abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
task :test => :check_dependencies
 | 
			
		||||
 | 
			
		||||
task :default => :test
 | 
			
		||||
 | 
			
		||||
require 'rake/rdoctask'
 | 
			
		||||
Rake::RDocTask.new do |rdoc|
 | 
			
		||||
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
 | 
			
		||||
 | 
			
		||||
  rdoc.rdoc_dir = 'rdoc'
 | 
			
		||||
  rdoc.title = "sunspot_mongoid #{version}"
 | 
			
		||||
  rdoc.rdoc_files.include('README*')
 | 
			
		||||
  rdoc.rdoc_files.include('lib/**/*.rb')
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1 +0,0 @@
 | 
			
		|||
0.4.1
 | 
			
		||||
| 
						 | 
				
			
			@ -1,36 +0,0 @@
 | 
			
		|||
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
 | 
			
		||||
require 'sunspot_mongoid'
 | 
			
		||||
 | 
			
		||||
Mongoid.configure do |config|
 | 
			
		||||
  config.master = Mongo::Connection.new.db('sunspot-mongoid-test')
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# model
 | 
			
		||||
class Post
 | 
			
		||||
  include Mongoid::Document
 | 
			
		||||
  field :title
 | 
			
		||||
 | 
			
		||||
  include Sunspot::Mongoid
 | 
			
		||||
  searchable do
 | 
			
		||||
    text :title
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# remove old indexes
 | 
			
		||||
Post.destroy_all
 | 
			
		||||
 | 
			
		||||
# indexing
 | 
			
		||||
Post.create(:title => 'foo')
 | 
			
		||||
Post.create(:title => 'foo bar')
 | 
			
		||||
Post.create(:title => 'bar baz')
 | 
			
		||||
 | 
			
		||||
# commit
 | 
			
		||||
Sunspot.commit
 | 
			
		||||
 | 
			
		||||
# search
 | 
			
		||||
search = Post.search do
 | 
			
		||||
  keywords 'foo'
 | 
			
		||||
end
 | 
			
		||||
search.each_hit_with_result do |hit, post|
 | 
			
		||||
  p post
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1 +0,0 @@
 | 
			
		|||
require 'sunspot_mongoid'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,49 +0,0 @@
 | 
			
		|||
require 'sunspot'
 | 
			
		||||
require 'mongoid'
 | 
			
		||||
require 'sunspot/rails'
 | 
			
		||||
 | 
			
		||||
# == Examples:
 | 
			
		||||
#
 | 
			
		||||
# class Post
 | 
			
		||||
#   include Mongoid::Document
 | 
			
		||||
#   field :title
 | 
			
		||||
# 
 | 
			
		||||
#   include Sunspot::Mongoid
 | 
			
		||||
#   searchable do
 | 
			
		||||
#     text :title
 | 
			
		||||
#   end
 | 
			
		||||
# end
 | 
			
		||||
#
 | 
			
		||||
module Sunspot
 | 
			
		||||
  module Mongoid
 | 
			
		||||
    def self.included(base)
 | 
			
		||||
      base.class_eval do
 | 
			
		||||
        extend Sunspot::Rails::Searchable::ActsAsMethods
 | 
			
		||||
        Sunspot::Adapters::DataAccessor.register(DataAccessor, base)
 | 
			
		||||
        Sunspot::Adapters::InstanceAdapter.register(InstanceAdapter, base)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class InstanceAdapter < Sunspot::Adapters::InstanceAdapter
 | 
			
		||||
      def id
 | 
			
		||||
        @instance.id
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class DataAccessor < Sunspot::Adapters::DataAccessor
 | 
			
		||||
      def load(id)
 | 
			
		||||
        criteria(id).first
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def load_all(ids)
 | 
			
		||||
        criteria(ids)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def criteria(id)
 | 
			
		||||
        @clazz.criteria.id(id)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1 +0,0 @@
 | 
			
		|||
require 'sunspot/mongoid'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,67 +0,0 @@
 | 
			
		|||
# Generated by jeweler
 | 
			
		||||
# DO NOT EDIT THIS FILE DIRECTLY
 | 
			
		||||
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
 | 
			
		||||
# -*- encoding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
Gem::Specification.new do |s|
 | 
			
		||||
  s.name = %q{sunspot_mongoid}
 | 
			
		||||
  s.version = "0.4.1"
 | 
			
		||||
 | 
			
		||||
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
 | 
			
		||||
  s.authors = ["jugyo"]
 | 
			
		||||
  s.date = %q{2011-03-04}
 | 
			
		||||
  s.description = %q{A Sunspot wrapper for Mongoid that is like sunspot_rails.}
 | 
			
		||||
  s.email = %q{jugyo.org@gmail.com}
 | 
			
		||||
  s.extra_rdoc_files = [
 | 
			
		||||
    "LICENSE",
 | 
			
		||||
    "README.md"
 | 
			
		||||
  ]
 | 
			
		||||
  s.files = [
 | 
			
		||||
    ".document",
 | 
			
		||||
    "LICENSE",
 | 
			
		||||
    "README.md",
 | 
			
		||||
    "Rakefile",
 | 
			
		||||
    "VERSION",
 | 
			
		||||
    "examples/example.rb",
 | 
			
		||||
    "init.rb",
 | 
			
		||||
    "lib/sunspot/mongoid.rb",
 | 
			
		||||
    "lib/sunspot_mongoid.rb",
 | 
			
		||||
    "sunspot_mongoid.gemspec",
 | 
			
		||||
    "test/helper.rb",
 | 
			
		||||
    "test/test_sunspot_mongoid.rb"
 | 
			
		||||
  ]
 | 
			
		||||
  s.homepage = %q{http://github.com/jugyo/sunspot_mongoid}
 | 
			
		||||
  s.require_paths = ["lib"]
 | 
			
		||||
  s.rubygems_version = %q{1.6.0}
 | 
			
		||||
  s.summary = %q{A Sunspot wrapper for Mongoid.}
 | 
			
		||||
  s.test_files = [
 | 
			
		||||
    "examples/example.rb",
 | 
			
		||||
    "test/helper.rb",
 | 
			
		||||
    "test/test_sunspot_mongoid.rb"
 | 
			
		||||
  ]
 | 
			
		||||
 | 
			
		||||
  if s.respond_to? :specification_version then
 | 
			
		||||
    s.specification_version = 3
 | 
			
		||||
 | 
			
		||||
    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
 | 
			
		||||
      s.add_runtime_dependency(%q<mongoid>, [">= 0"])
 | 
			
		||||
      s.add_runtime_dependency(%q<sunspot>, [">= 1.1.0"])
 | 
			
		||||
      s.add_runtime_dependency(%q<sunspot_rails>, [">= 1.1.0"])
 | 
			
		||||
      s.add_development_dependency(%q<shoulda>, [">= 0"])
 | 
			
		||||
      s.add_development_dependency(%q<rr>, [">= 0"])
 | 
			
		||||
    else
 | 
			
		||||
      s.add_dependency(%q<mongoid>, [">= 0"])
 | 
			
		||||
      s.add_dependency(%q<sunspot>, [">= 1.1.0"])
 | 
			
		||||
      s.add_dependency(%q<sunspot_rails>, [">= 1.1.0"])
 | 
			
		||||
      s.add_dependency(%q<shoulda>, [">= 0"])
 | 
			
		||||
      s.add_dependency(%q<rr>, [">= 0"])
 | 
			
		||||
    end
 | 
			
		||||
  else
 | 
			
		||||
    s.add_dependency(%q<mongoid>, [">= 0"])
 | 
			
		||||
    s.add_dependency(%q<sunspot>, [">= 1.1.0"])
 | 
			
		||||
    s.add_dependency(%q<sunspot_rails>, [">= 1.1.0"])
 | 
			
		||||
    s.add_dependency(%q<shoulda>, [">= 0"])
 | 
			
		||||
    s.add_dependency(%q<rr>, [">= 0"])
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,12 +0,0 @@
 | 
			
		|||
require 'rubygems'
 | 
			
		||||
require 'test/unit'
 | 
			
		||||
require 'shoulda'
 | 
			
		||||
require 'rr'
 | 
			
		||||
 | 
			
		||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
 | 
			
		||||
$LOAD_PATH.unshift(File.dirname(__FILE__))
 | 
			
		||||
require 'sunspot_mongoid'
 | 
			
		||||
 | 
			
		||||
class Test::Unit::TestCase
 | 
			
		||||
  include RR::Adapters::TestUnit
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1,51 +0,0 @@
 | 
			
		|||
require 'helper'
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# NOTE: I think tests are too few...
 | 
			
		||||
#
 | 
			
		||||
class TestSunspotMongoid < Test::Unit::TestCase
 | 
			
		||||
  class Foo
 | 
			
		||||
    include Mongoid::Document
 | 
			
		||||
    field :title
 | 
			
		||||
 | 
			
		||||
    include Sunspot::Mongoid
 | 
			
		||||
    searchable do
 | 
			
		||||
      text :title
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class Bar
 | 
			
		||||
    include Mongoid::Document
 | 
			
		||||
    field :title
 | 
			
		||||
 | 
			
		||||
    include Sunspot::Mongoid
 | 
			
		||||
    searchable(:auto_index => false, :auto_remove => false) do
 | 
			
		||||
      text :title
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  context 'default' do
 | 
			
		||||
    should 'sunspot_options is specified' do
 | 
			
		||||
      assert Foo.sunspot_options == {:include => []}
 | 
			
		||||
      assert Bar.sunspot_options == {:auto_index=>false, :auto_remove=>false, :include=>[]}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    should 'be called Sunspot.setup when call Foo.searchable' do
 | 
			
		||||
      mock(Sunspot).setup(Foo)
 | 
			
		||||
      Foo.searchable
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    should 'get as text_fields from Sunspot::Setup' do
 | 
			
		||||
      text_field = Sunspot::Setup.for(Foo).all_text_fields.first
 | 
			
		||||
      assert text_field.type == Sunspot::Type::TextType.instance
 | 
			
		||||
      assert text_field.name == :title
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    should 'search' do
 | 
			
		||||
      options = {}
 | 
			
		||||
      mock.proxy(Foo).solr_execute_search(options)
 | 
			
		||||
      mock(Sunspot).new_search(Foo) { mock(Object.new).execute }
 | 
			
		||||
      Foo.search(options)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
		Reference in New Issue