diff --git a/.gitignore b/.gitignore index b57fdb65..572d342f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,8 @@ log/*.log tmp/**/* public/uploads/**/* uploads/**/* - +public/panel/**/* +public/index.html .DS_Store *.swp diff --git a/Gemfile b/Gemfile index d400b8b6..094192a1 100644 --- a/Gemfile +++ b/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 diff --git a/Gemfile.lock b/Gemfile.lock index abfe1fe1..d0e8d857 100644 --- a/Gemfile.lock +++ b/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 diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 392ffe3d..6b365042 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -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 diff --git a/config/initializers/redis_search.rb b/config/initializers/redis_search.rb new file mode 100644 index 00000000..5fe14cf3 --- /dev/null +++ b/config/initializers/redis_search.rb @@ -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 \ No newline at end of file diff --git a/dump.rdb b/dump.rdb index 0e889cae..9ee1d38b 100644 Binary files a/dump.rdb and b/dump.rdb differ diff --git a/lib/tasks/matt_dev.rake b/lib/tasks/matt_dev.rake new file mode 100644 index 00000000..c19ef3b0 --- /dev/null +++ b/lib/tasks/matt_dev.rake @@ -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 diff --git a/tmp/elasticsearch.log b/tmp/elasticsearch.log deleted file mode 100644 index e69de29b..00000000 diff --git a/tmp/tire-dsl.rb b/tmp/tire-dsl.rb deleted file mode 100644 index 5b8117ba..00000000 --- a/tmp/tire-dsl.rb +++ /dev/null @@ -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. -# -# -# _Tire_ is open source, and you can download or clone the source code -# from . -# -# 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: Two -# # -# 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 => '' } -# 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. \ No newline at end of file diff --git a/vendor/built_in_modules/announcement/app/controllers/panel/announcement/front_end/bulletins_controller.rb b/vendor/built_in_modules/announcement/app/controllers/panel/announcement/front_end/bulletins_controller.rb index 25529f96..ba8b949c 100644 --- a/vendor/built_in_modules/announcement/app/controllers/panel/announcement/front_end/bulletins_controller.rb +++ b/vendor/built_in_modules/announcement/app/controllers/panel/announcement/front_end/bulletins_controller.rb @@ -9,17 +9,24 @@ class Panel::Announcement::FrontEnd::BulletinsController < OrbitWidgetController # GET /bulletins.xml def index - - 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) - @current_category = BulletinCategory.from_id(params[:category_id]) rescue nil - elsif !params[:tag_id].blank? - @tag = AnnouncementTag.find(params[:tag_id]) rescue nil - @tag = AnnouncementTag.where(key: params[:tag_id])[0] unless @tag - @bulletins = @tag.bulletins.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) + 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 - @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) + 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) + @current_category = BulletinCategory.from_id(params[:category_id]) rescue nil + elsif !params[:tag_id].blank? + @tag = AnnouncementTag.find(params[:tag_id]) rescue nil + @tag = AnnouncementTag.where(key: params[:tag_id])[0] unless @tag + @bulletins = @tag.bulletins.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) + 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 diff --git a/vendor/built_in_modules/announcement/app/controllers/panel/announcement/widget/bulletins_controller.rb b/vendor/built_in_modules/announcement/app/controllers/panel/announcement/widget/bulletins_controller.rb index a37bef73..07870ae5 100644 --- a/vendor/built_in_modules/announcement/app/controllers/panel/announcement/widget/bulletins_controller.rb +++ b/vendor/built_in_modules/announcement/app/controllers/panel/announcement/widget/bulletins_controller.rb @@ -47,6 +47,9 @@ class Panel::Announcement::Widget::BulletinsController < OrbitWidgetController get_categorys end + def bulletins_search_block + + end protected diff --git a/vendor/built_in_modules/announcement/app/models/bulletin.rb b/vendor/built_in_modules/announcement/app/models/bulletin.rb index a6b0e55f..904cc7d9 100644 --- a/vendor/built_in_modules/announcement/app/models/bulletin.rb +++ b/vendor/built_in_modules/announcement/app/models/bulletin.rb @@ -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 diff --git a/vendor/built_in_modules/announcement/app/views/panel/announcement/widget/bulletins/bulletins_search_block.html.erb b/vendor/built_in_modules/announcement/app/views/panel/announcement/widget/bulletins/bulletins_search_block.html.erb new file mode 100644 index 00000000..31e04d03 --- /dev/null +++ b/vendor/built_in_modules/announcement/app/views/panel/announcement/widget/bulletins/bulletins_search_block.html.erb @@ -0,0 +1,6 @@ +<%= form_tag panel_announcement_front_end_bulletins_path, method: :get do %> +

+ <%= text_field_tag :search_query, params[:search_query] %> + <%= submit_tag "Search", name: nil %> +

+<% end %> \ No newline at end of file diff --git a/vendor/built_in_modules/announcement/config/routes.rb b/vendor/built_in_modules/announcement/config/routes.rb index a9f1c496..ce6c5ec3 100644 --- a/vendor/built_in_modules/announcement/config/routes.rb +++ b/vendor/built_in_modules/announcement/config/routes.rb @@ -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 diff --git a/vendor/built_in_modules/news/app/controllers/panel/news/front_end/news_bulletins_controller.rb b/vendor/built_in_modules/news/app/controllers/panel/news/front_end/news_bulletins_controller.rb index e43e90d1..540f33b2 100644 --- a/vendor/built_in_modules/news/app/controllers/panel/news/front_end/news_bulletins_controller.rb +++ b/vendor/built_in_modules/news/app/controllers/panel/news/front_end/news_bulletins_controller.rb @@ -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 diff --git a/vendor/built_in_modules/news/app/controllers/panel/news/widget/news_bulletins_controller.rb b/vendor/built_in_modules/news/app/controllers/panel/news/widget/news_bulletins_controller.rb index 49b358df..3ad7e3ef 100644 --- a/vendor/built_in_modules/news/app/controllers/panel/news/widget/news_bulletins_controller.rb +++ b/vendor/built_in_modules/news/app/controllers/panel/news/widget/news_bulletins_controller.rb @@ -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? diff --git a/vendor/built_in_modules/news/app/models/news_bulletin.rb b/vendor/built_in_modules/news/app/models/news_bulletin.rb index dbcd215c..97bc8dfa 100644 --- a/vendor/built_in_modules/news/app/models/news_bulletin.rb +++ b/vendor/built_in_modules/news/app/models/news_bulletin.rb @@ -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 - end + 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 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 - 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 def self.widget_datas( category_id = nil ) diff --git a/vendor/built_in_modules/news/app/views/panel/news/widget/news_bulletins/news_bulletins_search_block.html.erb b/vendor/built_in_modules/news/app/views/panel/news/widget/news_bulletins/news_bulletins_search_block.html.erb index f3512afc..a1ff5639 100644 --- a/vendor/built_in_modules/news/app/views/panel/news/widget/news_bulletins/news_bulletins_search_block.html.erb +++ b/vendor/built_in_modules/news/app/views/panel/news/widget/news_bulletins/news_bulletins_search_block.html.erb @@ -1,6 +1,7 @@ <%= form_tag panel_news_front_end_news_bulletins_path, method: :get do %>

<%= text_field_tag :search_query, params[:search_query] %> + <%= hidden_field_tag :category_id, params[:category_id] %> <%= submit_tag "Search", name: nil %>

<% end %> \ No newline at end of file diff --git a/vendor/impressionist/Gemfile b/vendor/impressionist/Gemfile index e6cc394d..42fe3e34 100644 --- a/vendor/impressionist/Gemfile +++ b/vendor/impressionist/Gemfile @@ -7,7 +7,7 @@ platforms :jruby do end platforms :ruby, :mswin, :mingw do - # gem 'sqlite3' + gem 'sqlite3' end gemspec diff --git a/vendor/impressionist/app/models/impressionist/impressionable.rb b/vendor/impressionist/app/models/impressionist/impressionable.rb index 1df2f1c3..b4163054 100644 --- a/vendor/impressionist/app/models/impressionist/impressionable.rb +++ b/vendor/impressionist/app/models/impressionist/impressionable.rb @@ -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 diff --git a/vendor/impressionist/lib/generators/impressionist_generator.rb b/vendor/impressionist/lib/generators/impressionist_generator.rb index 30290af2..008f1ecf 100644 --- a/vendor/impressionist/lib/generators/impressionist_generator.rb +++ b/vendor/impressionist/lib/generators/impressionist_generator.rb @@ -7,6 +7,7 @@ module Impressionist def copy_config_file template 'impression.rb', 'config/initializers/impression.rb' end + end end end diff --git a/vendor/impressionist/lib/generators/templates/impression.rb b/vendor/impressionist/lib/generators/templates/impression.rb index fbdee915..5de89e47 100644 --- a/vendor/impressionist/lib/generators/templates/impression.rb +++ b/vendor/impressionist/lib/generators/templates/impression.rb @@ -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 diff --git a/vendor/impressionist/lib/impressionist/controllers/mongoid/impressionist_controller.rb b/vendor/impressionist/lib/impressionist/controllers/mongoid/impressionist_controller.rb new file mode 100644 index 00000000..426c5b86 --- /dev/null +++ b/vendor/impressionist/lib/impressionist/controllers/mongoid/impressionist_controller.rb @@ -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 \ No newline at end of file diff --git a/vendor/impressionist/lib/impressionist/engine.rb b/vendor/impressionist/lib/impressionist/engine.rb index 8f953d75..fddb04f9 100644 --- a/vendor/impressionist/lib/impressionist/engine.rb +++ b/vendor/impressionist/lib/impressionist/engine.rb @@ -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 diff --git a/vendor/impressionist/lib/impressionist/models/mongoid/impression.rb b/vendor/impressionist/lib/impressionist/models/mongoid/impression.rb index 9a2d958c..5c107857 100644 --- a/vendor/impressionist/lib/impressionist/models/mongoid/impression.rb +++ b/vendor/impressionist/lib/impressionist/models/mongoid/impression.rb @@ -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 diff --git a/vendor/impressionist/lib/impressionist/models/mongoid/impressionist/impressionable.rb b/vendor/impressionist/lib/impressionist/models/mongoid/impressionist/impressionable.rb index 6100b886..5f04b03e 100644 --- a/vendor/impressionist/lib/impressionist/models/mongoid/impressionist/impressionable.rb +++ b/vendor/impressionist/lib/impressionist/models/mongoid/impressionist/impressionable.rb @@ -4,9 +4,49 @@ module Impressionist module ClassMethods def is_impressionable(options={}) - has_many :impressions, :as => :impressionable, :dependent => :destroy - @impressionist_cache_options = options[:counter_cache] + 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 +end \ No newline at end of file diff --git a/vendor/impressionist/test_app/spec/models/counter_caching_spec.rb b/vendor/impressionist/test_app/spec/models/counter_caching_spec.rb index 552bf647..2f9636d4 100644 --- a/vendor/impressionist/test_app/spec/models/counter_caching_spec.rb +++ b/vendor/impressionist/test_app/spec/models/counter_caching_spec.rb @@ -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 diff --git a/vendor/plugins/sunspot_mongoid/.document b/vendor/plugins/sunspot_mongoid/.document deleted file mode 100644 index ecf36731..00000000 --- a/vendor/plugins/sunspot_mongoid/.document +++ /dev/null @@ -1,5 +0,0 @@ -README.rdoc -lib/**/*.rb -bin/* -features/**/*.feature -LICENSE diff --git a/vendor/plugins/sunspot_mongoid/LICENSE b/vendor/plugins/sunspot_mongoid/LICENSE deleted file mode 100644 index 883f0922..00000000 --- a/vendor/plugins/sunspot_mongoid/LICENSE +++ /dev/null @@ -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. diff --git a/vendor/plugins/sunspot_mongoid/README.md b/vendor/plugins/sunspot_mongoid/README.md deleted file mode 100644 index 7c3c88fe..00000000 --- a/vendor/plugins/sunspot_mongoid/README.md +++ /dev/null @@ -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. diff --git a/vendor/plugins/sunspot_mongoid/Rakefile b/vendor/plugins/sunspot_mongoid/Rakefile deleted file mode 100644 index bec1214b..00000000 --- a/vendor/plugins/sunspot_mongoid/Rakefile +++ /dev/null @@ -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 diff --git a/vendor/plugins/sunspot_mongoid/VERSION b/vendor/plugins/sunspot_mongoid/VERSION deleted file mode 100644 index 267577d4..00000000 --- a/vendor/plugins/sunspot_mongoid/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.4.1 diff --git a/vendor/plugins/sunspot_mongoid/examples/example.rb b/vendor/plugins/sunspot_mongoid/examples/example.rb deleted file mode 100644 index 04f02e77..00000000 --- a/vendor/plugins/sunspot_mongoid/examples/example.rb +++ /dev/null @@ -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 diff --git a/vendor/plugins/sunspot_mongoid/init.rb b/vendor/plugins/sunspot_mongoid/init.rb deleted file mode 100644 index 341c6026..00000000 --- a/vendor/plugins/sunspot_mongoid/init.rb +++ /dev/null @@ -1 +0,0 @@ -require 'sunspot_mongoid' diff --git a/vendor/plugins/sunspot_mongoid/lib/sunspot/mongoid.rb b/vendor/plugins/sunspot_mongoid/lib/sunspot/mongoid.rb deleted file mode 100644 index a12703df..00000000 --- a/vendor/plugins/sunspot_mongoid/lib/sunspot/mongoid.rb +++ /dev/null @@ -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 diff --git a/vendor/plugins/sunspot_mongoid/lib/sunspot_mongoid.rb b/vendor/plugins/sunspot_mongoid/lib/sunspot_mongoid.rb deleted file mode 100644 index 454e5da2..00000000 --- a/vendor/plugins/sunspot_mongoid/lib/sunspot_mongoid.rb +++ /dev/null @@ -1 +0,0 @@ -require 'sunspot/mongoid' diff --git a/vendor/plugins/sunspot_mongoid/sunspot_mongoid.gemspec b/vendor/plugins/sunspot_mongoid/sunspot_mongoid.gemspec deleted file mode 100644 index 968884cd..00000000 --- a/vendor/plugins/sunspot_mongoid/sunspot_mongoid.gemspec +++ /dev/null @@ -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, [">= 0"]) - s.add_runtime_dependency(%q, [">= 1.1.0"]) - s.add_runtime_dependency(%q, [">= 1.1.0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 1.1.0"]) - s.add_dependency(%q, [">= 1.1.0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - end - else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 1.1.0"]) - s.add_dependency(%q, [">= 1.1.0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - end -end - diff --git a/vendor/plugins/sunspot_mongoid/test/helper.rb b/vendor/plugins/sunspot_mongoid/test/helper.rb deleted file mode 100644 index e5c3b13b..00000000 --- a/vendor/plugins/sunspot_mongoid/test/helper.rb +++ /dev/null @@ -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 diff --git a/vendor/plugins/sunspot_mongoid/test/test_sunspot_mongoid.rb b/vendor/plugins/sunspot_mongoid/test/test_sunspot_mongoid.rb deleted file mode 100644 index 141b6f3b..00000000 --- a/vendor/plugins/sunspot_mongoid/test/test_sunspot_mongoid.rb +++ /dev/null @@ -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