static_search 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f9cf632c8ca6b071da82c5870adf7332e84f2e0f
4
+ data.tar.gz: 23274c0cc813ecfa19341810452ebdcffd9b562a
5
+ SHA512:
6
+ metadata.gz: b97ce839718279eed1460052f5a8dedd6e5805717703b7fa6d014b508589e537b4456036003bebdf4e4900ece20107ec167dc7d24f7fa9fc2dcaf4a354f6c703
7
+ data.tar.gz: 37de39d42734f9a6e86ff4dd6977fb46c17c7de5a705a0b854070929c76c6b27fd63cee49a204e3ed8409c2149390c1ae091a583245485ee1f84a4ce0c9e0632
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ spec/pages
16
+ spec/tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in static_search.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 DanielRavina
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # StaticSearch
2
+
3
+ StaticSearch allow you to index your static content (i.e "pages") in your Rails app easily!. Why would you want to index static pages? You can search the content within it, generate analytics etc.
4
+ It's made of 2 modules - Indexing and Searching.
5
+
6
+ #### Keep In mind:
7
+ This gem is currently a work in progress and it is not a part of the Rubygem site. I am using it currently for a specific project and I change stuff on the fly. Once I feel it's stable enough, I will release it to the world
8
+
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'static-search'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install static-search
25
+
26
+ Run the migration:
27
+
28
+ $ rake db:migrate
29
+
30
+ ## Usage
31
+ ### Indexing
32
+ First make sure all of your static pages are in the right place:
33
+
34
+ - app/
35
+ - views/
36
+ - pages/
37
+ - index.html
38
+ - about.html.erb
39
+ - faq.html
40
+ - privacy_policy.html
41
+
42
+ Now, you are able to run the built-in rake task:
43
+
44
+ $ rake static:index
45
+
46
+
47
+ The output should be something like that
48
+
49
+ Indexing index
50
+ Indexing about
51
+ Indexing faq
52
+ Indexing privacy_policy
53
+ -- Completed
54
+
55
+ If you made a change in the content and you want to update the index, simply run the rake task again and it will update everything.
56
+
57
+ At this point, the content (text) of the page, including parsed erb, is saved in the database *without* the html tags.
58
+
59
+ ### Searcing
60
+
61
+ TODO: Build search module.
62
+
63
+ ## Contributing
64
+
65
+ 1. Fork it ( https://github.com/danielravina/static_search/fork )
66
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
67
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
68
+ 4. Push to the branch (`git push origin my-new-feature`)
69
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,3 @@
1
+ class StaticContent < ActiveRecord::Base
2
+ self.table_name = "static_content"
3
+ end
@@ -0,0 +1,9 @@
1
+ class CreateStaticContent < ActiveRecord::Migration
2
+ def change
3
+ create_table :static_content do |t|
4
+ t.text :content
5
+ t.string :title
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
data/lib/engine.rb ADDED
@@ -0,0 +1,16 @@
1
+ # The engine file add the gem's migration to the Rails app it is located in
2
+
3
+ class StaticSearch::Engine < ::Rails::Engine
4
+ isolate_namespace StaticSearch
5
+
6
+ config.autoload_paths += Dir["#{config.root}/lib/**/"]
7
+
8
+ initializer :append_migrations do |app|
9
+ unless app.root.to_s.match root.to_s
10
+ config.paths["db/migrate"].expanded.each do |expanded_path|
11
+ app.config.paths["db/migrate"] << expanded_path
12
+ end
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,59 @@
1
+ class StaticSearch::IndexBuilder
2
+
3
+ require File.dirname(File.expand_path '../..', __FILE__) + '/app/models/static_content.rb'
4
+
5
+ def build(pages_path, options = {})
6
+ Dir["#{pages_path}/**/*"].each do |fname|
7
+ unless File.directory? fname
8
+ erb = parse_file fname
9
+ filename = parse_title fname
10
+ text = parse_content(erb, options[:keep_tags] || {})
11
+ save_content(text, filename)
12
+ end
13
+ end
14
+ puts "-- Completed" if production?
15
+ end
16
+
17
+ def save_content (text, title)
18
+ puts "Indexing #{title} page" if production?
19
+ static_content = StaticContent.find_or_initialize_by(title: title)
20
+ static_content.update content: text
21
+ return static_content
22
+ end
23
+
24
+
25
+ def parse_file(fname)
26
+ file = File.read(fname)
27
+ ERB.new file, nil, "%"
28
+ end
29
+
30
+ def parse_content (erb, options = {})
31
+
32
+ html = Nokogiri.HTML erb.result
33
+ html.css('script').remove
34
+ if options[:keep_tags]
35
+ html.css("body")
36
+ else
37
+ html.css("body")
38
+ .text
39
+ .gsub("\n"," ")
40
+ .gsub(/(\s{2,})/," ")
41
+ .strip
42
+ end
43
+ end
44
+
45
+ def parse_title(fname)
46
+ filename = fname.split("/pages/").last
47
+ if filename.match(/\./)
48
+ return filename.split(".").first
49
+ else
50
+ return filename
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def production?
57
+ defined?(Rails) || defined?(Rake)
58
+ end
59
+ end
@@ -0,0 +1,30 @@
1
+ class StaticSearch::Search
2
+
3
+ def self.find_content(q, options = {})
4
+ return [] unless q.present?
5
+ result = StaticContent.where("LOWER(content) like ? OR LOWER(title) like ?", "% #{q} %", "%#{q}%");
6
+ if options[:truncation]
7
+ return result.map do |page|
8
+ page = page.as_json
9
+ page["content"] = truncate_body(page["content"], q, options[:truncation])
10
+ page
11
+ end
12
+ else
13
+ return result.map(&:as_json)
14
+ end
15
+ end
16
+
17
+ def self.truncate_body content, q, truncation_size
18
+ content = \
19
+ if content.include? q
20
+ index = content.downcase.index(q.downcase) || 0
21
+ content[index..(index + truncation_size)]
22
+ else
23
+ content[0..truncation_size]
24
+ end
25
+ if content && content.size > truncation_size
26
+ content << "..."
27
+ end
28
+ return content
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module StaticSearch
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,15 @@
1
+ require "static_search/version"
2
+ require 'nokogiri'
3
+
4
+ if defined?(Rails)
5
+ require 'engine'
6
+ Dir["lib/static_search/**/*.rb"].each { |ext| load ext }
7
+ end
8
+
9
+ if defined?(Rake)
10
+ Dir["lib/tasks/**/*.rake"].each { |ext| load ext }
11
+ end
12
+
13
+ module StaticSearch
14
+ end
15
+
@@ -0,0 +1,31 @@
1
+ namespace :static do
2
+
3
+ task :seed , [:path] => :environment do |t, args|
4
+
5
+ require 'httparty'
6
+ require 'static_search/index_builder'
7
+
8
+ puts "This action will override existing data.\nAre you sure you want to continue? [Y/N]"
9
+ user_confirm = STDIN.gets
10
+
11
+ if !!(user_confirm =~ /Y|y|Yes|yes|YES/)
12
+ pages_path = "#{Rails.root}/app/views/pages"
13
+ p "Populating random stuff..."
14
+
15
+ unless Dir.exists? pages_path
16
+ raise "Pages directory doesn't exists. Please create it in #{pages_path}"
17
+ end
18
+
19
+ random_wiki = 'http://en.wikipedia.org/wiki/Special:Random'
20
+
21
+ Dir["#{pages_path}/**/*"].each do |fname|
22
+ unless File.directory? fname
23
+ response = HTTParty.get(random_wiki)
24
+ page = File.open(fname, "w")
25
+ page.puts response.parsed_response
26
+ page.close
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ namespace :static do
2
+ task :index , [:path] => :environment do |t, args|
3
+
4
+ require 'static_search/index_builder'
5
+
6
+ pages_path = "#{Rails.root}/app/views/pages"
7
+
8
+ unless Dir.exists? pages_path
9
+ raise "Pages directory doesn't exists. Please create it in #{pages_path}"
10
+ end
11
+
12
+ index_builder = StaticSearch::IndexBuilder.new
13
+ index_builder.build(pages_path)
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ namespace :static do
2
+ task :clear , [:path] => :environment do |t, args|
3
+
4
+ require 'static_search/index_builder'
5
+
6
+ pages_path = "#{Rails.root}/app/views/pages"
7
+
8
+ unless Dir.exists? pages_path
9
+ raise "Pages directory doesn't exists. Please create it in #{pages_path}"
10
+ end
11
+
12
+ StaticContent.destroy_all
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ namespace :static do
2
+
3
+ task :remove_seed , [:path] => :environment do |t, args|
4
+
5
+ require 'static_search/index_builder'
6
+
7
+ puts "This action will override existing data.\nAre you sure you want to continue? [Y/N]"
8
+ user_confirm = STDIN.gets
9
+
10
+ if !!(user_confirm =~ /Y|y|Yes|yes|YES/)
11
+ pages_path = "#{Rails.root}/app/views/pages"
12
+ p "Removing page content"
13
+
14
+ unless Dir.exists? pages_path
15
+ raise "Pages directory doesn't exists. Please create it in #{pages_path}"
16
+ end
17
+
18
+ Dir["#{pages_path}/**/*"].each do |fname|
19
+ unless File.directory? fname
20
+ page = File.open(fname, "w")
21
+ page.puts ""
22
+ page.close
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+ require 'httparty'
3
+ require 'static_search/index_builder'
4
+
5
+ require File.dirname(File.expand_path '../', __FILE__) + '/app/models/static_content.rb'
6
+
7
+ describe StaticSearch::IndexBuilder do
8
+ describe "build" do
9
+ let(:index_builder) { StaticSearch::IndexBuilder.new }
10
+ let(:example_direcotry) { 'spec/pages' }
11
+ let(:example_file) { "#{example_direcotry}/example.html" }
12
+ let(:exampl_url) { 'http://en.wikipedia.org/wiki/Special:Random' }
13
+
14
+ before do
15
+ unless Dir.exists? example_direcotry
16
+ Dir.mkdir(example_direcotry)
17
+ end
18
+ if File.exists? (example_file)
19
+ File.delete(example_file)
20
+ end
21
+ response = HTTParty.get(exampl_url)
22
+ temp_file = File.new(example_file, "w")
23
+ temp_file.puts response.parsed_response
24
+ temp_file.close
25
+ end
26
+
27
+ it "parses the file" do
28
+ parsed_erb = index_builder.parse_file(example_file)
29
+ expect(parsed_erb).to be_kind_of ERB
30
+ end
31
+
32
+ it "converts HTML to text" do
33
+ parsed_erb = index_builder.parse_file(example_file)
34
+ text = index_builder.parse_content parsed_erb
35
+ expect(text).to be_kind_of String
36
+ expect(text[0]).to_not be_empty
37
+ end
38
+
39
+ it "Saves raw HTML" do
40
+ parsed_erb = index_builder.parse_file example_file
41
+ text = index_builder.parse_content parsed_erb, keep_tags: true
42
+ title = index_builder.parse_title example_file
43
+ index_builder.save_content text, title
44
+ static_content = StaticContent.first
45
+ expect(static_content.content).to include "<body"
46
+ end
47
+
48
+ it "saves the content" do
49
+ parsed_erb = index_builder.parse_file(example_file)
50
+ text = index_builder.parse_content parsed_erb
51
+ title = index_builder.parse_title example_file
52
+
53
+ expect(index_builder.save_content(text, title)).to be_kind_of StaticContent
54
+ static_content = StaticContent.first
55
+ expect(StaticContent.count).to eq 1
56
+ expect(static_content.title).to eq "example"
57
+ expect(static_content.content).to_not match(/<div|<script|<noscript|<a/)
58
+ end
59
+
60
+ it "includes the sub-directory in the file name" do
61
+ sub_dir = "sub"
62
+ filename = "subtest"
63
+ new_dir = "#{example_direcotry}/#{sub_dir}/"
64
+ unless Dir.exists? new_dir
65
+ Dir.mkdir(new_dir)
66
+ end
67
+ temp_file = File.new(new_dir << filename + ".html", "w")
68
+ p
69
+ title = index_builder.parse_title temp_file.path
70
+ expect(title).to eq sub_dir + "/" + filename
71
+ end
72
+
73
+ end
74
+ end
data/spec/schema.rb ADDED
@@ -0,0 +1,11 @@
1
+ ActiveRecord::Schema.define do
2
+ self.verbose = false
3
+
4
+ create_table "static_content", force: :cascade do |t|
5
+ t.text "content", limit: 65535
6
+ t.string "title"
7
+ t.datetime "created_at"
8
+ t.datetime "updated_at"
9
+ end
10
+
11
+ end
@@ -0,0 +1,13 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'static_search'
5
+ require 'active_record'
6
+
7
+ RSpec.configure do |config|
8
+ # some (optional) config here
9
+ end
10
+
11
+
12
+ ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
13
+ load File.dirname(__FILE__) + '/schema.rb'
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'static_search/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "static_search"
8
+ spec.version = StaticSearch::VERSION
9
+ spec.authors = ["DanielRavina"]
10
+ spec.email = ["danielravina@gmail.com"]
11
+ spec.summary = %q{Index your Rails app's static content and search it easily}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency 'nokogiri', '~> 1.6.6.2'
21
+ spec.add_dependency 'httparty', '~> 0.13.3'
22
+ spec.add_development_dependency 'activerecord', '~> 4.2.1'
23
+ spec.add_development_dependency 'sqlite3'
24
+ spec.add_development_dependency 'database_cleaner', '~> 1.3.0'
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "bundler", "~> 1.7"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ end
metadata ADDED
@@ -0,0 +1,180 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: static_search
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - DanielRavina
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.6.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.6.6.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.13.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.13.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: activerecord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 4.2.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 4.2.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: database_cleaner
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.3.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.3.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: bundler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.7'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.7'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '10.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '10.0'
125
+ description:
126
+ email:
127
+ - danielravina@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".rspec"
134
+ - Gemfile
135
+ - LICENSE.txt
136
+ - README.md
137
+ - Rakefile
138
+ - app/models/static_content.rb
139
+ - db/migrate/20150524221831_create_static_content.rb
140
+ - lib/engine.rb
141
+ - lib/static_search.rb
142
+ - lib/static_search/index_builder.rb
143
+ - lib/static_search/search.rb
144
+ - lib/static_search/version.rb
145
+ - lib/tasks/add_dummy_content.rake
146
+ - lib/tasks/build_index.rake
147
+ - lib/tasks/clear_index.rake
148
+ - lib/tasks/remove_dummy_content.rake
149
+ - spec/index_spec.rb
150
+ - spec/schema.rb
151
+ - spec/spec_helper.rb
152
+ - static_search.gemspec
153
+ homepage: ''
154
+ licenses:
155
+ - MIT
156
+ metadata: {}
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubyforge_project:
173
+ rubygems_version: 2.4.7
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: Index your Rails app's static content and search it easily
177
+ test_files:
178
+ - spec/index_spec.rb
179
+ - spec/schema.rb
180
+ - spec/spec_helper.rb