picky-generators 2.0.0.pre1 → 2.0.0.pre2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/prototypes/client/sinatra/Gemfile +1 -1
- data/prototypes/client/sinatra/app.rb +20 -17
- data/prototypes/client/sinatra/book.rb +1 -1
- data/prototypes/client/sinatra/images/picky.png +0 -0
- data/prototypes/client/sinatra/javascripts/picky.min.js +2 -2
- data/prototypes/client/sinatra/stylesheets/application.css +1 -1
- data/prototypes/client/sinatra/views/search.haml +2 -1
- data/prototypes/server/shared_unicorn/Gemfile +1 -1
- data/prototypes/server/unicorn/app/application.rb +13 -24
- metadata +4 -4
@@ -2,21 +2,22 @@ require 'rubygems'
|
|
2
2
|
require 'bundler'
|
3
3
|
Bundler.require
|
4
4
|
|
5
|
-
#
|
5
|
+
# Sinatra settings.
|
6
6
|
#
|
7
|
-
|
7
|
+
set :static, true
|
8
|
+
set :public, File.dirname(__FILE__)
|
9
|
+
set :views, File.expand_path('views', File.dirname(__FILE__))
|
10
|
+
set :haml, :format => :html5
|
8
11
|
|
9
|
-
|
12
|
+
# Load the simplified "model".
|
13
|
+
#
|
14
|
+
require File.expand_path 'book', File.dirname(__FILE__)
|
10
15
|
|
11
16
|
# Sets up a search instance to the server.
|
12
17
|
#
|
13
18
|
BookSearch = Picky::Client.new :host => 'localhost', :port => 8080, :path => '/books'
|
14
19
|
|
15
|
-
|
16
|
-
set :public, File.dirname(__FILE__)
|
17
|
-
set :views, File.expand_path('views', File.dirname(__FILE__))
|
18
|
-
|
19
|
-
# Root, the search interface.
|
20
|
+
# Root, the search page.
|
20
21
|
#
|
21
22
|
get '/' do
|
22
23
|
@query = params[:q]
|
@@ -24,12 +25,8 @@ get '/' do
|
|
24
25
|
haml :'/search'
|
25
26
|
end
|
26
27
|
|
27
|
-
#
|
28
|
+
# Renders the results into the json.
|
28
29
|
#
|
29
|
-
get '/configure' do
|
30
|
-
haml :'/configure'
|
31
|
-
end
|
32
|
-
|
33
30
|
# You get the ids from the picky server and then
|
34
31
|
# populate the result with rendered models.
|
35
32
|
#
|
@@ -37,21 +34,21 @@ get '/search/full' do
|
|
37
34
|
results = BookSearch.search params[:query], :ids => params[:ids], :offset => params[:offset]
|
38
35
|
results.extend Picky::Convenience
|
39
36
|
results.populate_with Book do |book|
|
40
|
-
book.
|
37
|
+
book.render
|
41
38
|
end
|
42
39
|
|
43
40
|
#
|
44
|
-
# Or use:
|
41
|
+
# Or, to populate with the model instances, use:
|
45
42
|
# results.populate_with Book
|
46
43
|
#
|
47
|
-
# Then:
|
44
|
+
# Then to render:
|
48
45
|
# rendered_entries = results.entries.map do |book| (render each book here) end
|
49
46
|
#
|
50
47
|
|
51
48
|
ActiveSupport::JSON.encode results
|
52
49
|
end
|
53
50
|
|
54
|
-
#
|
51
|
+
# Updates the search count while the user is typing.
|
55
52
|
#
|
56
53
|
# We don't parse/reencode the returned json string using search_unparsed.
|
57
54
|
#
|
@@ -59,6 +56,12 @@ get '/search/live' do
|
|
59
56
|
BookSearch.search_unparsed params[:query], :ids => params[:ids], :offset => params[:offset]
|
60
57
|
end
|
61
58
|
|
59
|
+
# Configure. The configuration info page.
|
60
|
+
#
|
61
|
+
get '/configure' do
|
62
|
+
haml :'/configure'
|
63
|
+
end
|
64
|
+
|
62
65
|
helpers do
|
63
66
|
|
64
67
|
def js path
|
Binary file
|
@@ -6,8 +6,8 @@ this.text=o;var q=function(h){n.text(h);h>0&&h<=5&&n.fadeTo("fast",0.5).fadeTo("
|
|
6
6
|
d.focus()}else{k.remove();p.render(h);$("body").animate({scrollTop:$("#picky div.results div.header:last").position().top-12},500)}};this.liveResultsCallback=function(h){v(w(h));q(h.total)};this.allocationChosen=function(h){h=h.data.query;d.val(h);c.allocationChosen(h)};this.addinationClicked=function(h){c.addinationClicked(o(),h)};(function(){d.keyup(function(h){if(o()==""){f();c.searchTextCleared()}else{c.searchTextEntered(o(),h);a()}});n.click(function(){o()==""||c.searchButtonClicked(o())});m.click(function(){o()==
|
7
7
|
""||c.searchButtonClicked(o())});e.click(function(){f("");c.clearButtonClicked();d.focus()})})();d.focus()};var PickyBackend=function(c){var i=function(g,d,e,m){var n=m||{};n=$.extend({query:g,offset:e},m);$.getJSON(c,n,function(s){d&&d(new PickyData(s))})};this.search=function(g,d,e,m,n){i(g,function(s){d&&d(n,s)},e,m)}},LiveBackend=function(c){var i=new PickyBackend(c);this.search=function(g,d,e,m,n){n=n||{};latestRequestTimestamp=new Date;n.live=latestRequestTimestamp;m=$.extend({ids:0},m);i.search(g,function(s,u){if(!s.live||s.live==latestRequestTimestamp)d&&d(u)},e,m,n)}},FullBackend=function(c){var i=
|
8
8
|
new PickyBackend(c);this.search=function(g,d,e,m,n){n=n||{};latestRequestTimestamp=new Date;n.full=latestRequestTimestamp;m=$.extend({ids:20},m);i.search(g,function(s,u){if(!s.full||s.full==latestRequestTimestamp)d&&d(u)},e,m,n)}};var PickyController=function(c){var i=new PickyView(this,c),g=c.backends,d=c.before||function(){},e=c.success||function(){},m=c.after||function(){},n=function(a){return(a=a&&a.match(/q=([^&]+)/))&&unescape(a[1]||"")};this.extractQuery=n;var s=function(){var a=window.History&&window.History.getState();return n(a&&a.url)};this.lastQuery=s;var u=function(a,b){a=e(a,b)||a;i.liveResultsCallback(a);m(a,b)},j,k=function(){var a=i.text();d({});var b=g.live;b&&b.search(a,u,0,void 0);clearInterval(j)};j=setInterval(k,
|
9
|
-
180);clearInterval(j);var r=function(a,b){a=e(a,b)||a;i.fullResultsCallback(a);m(a,b)},p=function(a,b,f){f=f||{};b=b||0;clearInterval(j);if(a!=s()){var o="?q="+a;window.History&&window.History.getState()&&window.History.pushState&&window.History.pushState(null,null,o)}f=d(f,a,b)||f;(o=g.full)&&o.search(a,r,b,f)};this.insert=function(a,b){i.insert(a);b&&p(a)};this.clearButtonClicked=function(){clearInterval(j)};this.searchTextCleared=function(){clearInterval(j)};this.searchTextEntered=
|
10
|
-
[0,8,13,32,46,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90])>-1)if(b.keyCode==13)p(a);else{clearInterval(j);j=setInterval(k,180)}};this.searchButtonClicked=function(a){p(a)};this.allocationChosen=function(a){p(a)};this.addinationClicked=function(a,b){p(a,b.data.offset)}};var Localization={},PickyClient=function(c){Localization.qualifiers=c.qualifiers||{};Localization.explanations=c.explanations||{};Localization.choices=c.choices||{};Localization.explanation_delimiters={de:"und",fr:"et",it:"e",en:"and",ch:"und"};var i=c.backends;if(i){i.live||alert("Both a full and live backend must be provided.");i.full||alert("Both a full and live backend must be provided.")}else c.backends={live:c.live&&new LiveBackend(c.live)||alert("A live backend path must be provided."),full:c.full&&
|
9
|
+
180);clearInterval(j);var r=function(a,b){a=e(a,b)||a;i.fullResultsCallback(a);m(a,b)},p=function(a,b,f){f=f||{};b=b||0;clearInterval(j);if(a!=s()){var o="?q="+escape(a).replace(/\*/g,"%2A");window.History&&window.History.getState()&&window.History.pushState&&window.History.pushState(null,null,o)}f=d(f,a,b)||f;(o=g.full)&&o.search(a,r,b,f)};this.insert=function(a,b){i.insert(a);b&&p(a)};this.clearButtonClicked=function(){clearInterval(j)};this.searchTextCleared=function(){clearInterval(j)};this.searchTextEntered=
|
10
|
+
function(a,b){if($.inArray(b.keyCode,[0,8,13,32,46,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90])>-1)if(b.keyCode==13)p(a);else{clearInterval(j);j=setInterval(k,180)}};this.searchButtonClicked=function(a){p(a)};this.allocationChosen=function(a){p(a)};this.addinationClicked=function(a,b){p(a,b.data.offset)}};var Localization={},PickyClient=function(c){Localization.qualifiers=c.qualifiers||{};Localization.explanations=c.explanations||{};Localization.choices=c.choices||{};Localization.explanation_delimiters={de:"und",fr:"et",it:"e",en:"and",ch:"und"};var i=c.backends;if(i){i.live||alert("Both a full and live backend must be provided.");i.full||alert("Both a full and live backend must be provided.")}else c.backends={live:c.live&&new LiveBackend(c.live)||alert("A live backend path must be provided."),full:c.full&&
|
11
11
|
new FullBackend(c.full)||alert("A live backend path must be provided.")};var g=c.controller&&new c.controller(c)||new PickyController(c);var d=this.insert=function(e,m){g.insert(e,m||true)};this.insertFromURL=function(e){if(e&&e!="")d(e);else(e=g.lastQuery())&&d(e)};window.History&&window.History.Adapter.bind(window,"statechange",function(){var e=window.History.getState();(e=g.extractQuery(e.url))&&d(e)})};var PickyAddination=function(c,i){this.remove=function(){i.find(".addination").remove()};this.render=function(g){var d=g.total,e;e=g.offset+20+0;var m=e+20;g=g.total;if(g<m)m=g;e={offset:e,start:e+1,end:m};if(e.offset<d){d=$("<div class='addination'>"+t("results.addination.more")+"</div>");d.bind("click",{offset:e.offset},c.addinationClicked);return d}else return""}};var PickyResultsRenderer=function(c,i){var g=i.wrapResults||'<ol class="results"></ol>',d=["street_number","zipcode"],e=function(j){var k=j[j.length-1];j=j.slice(0,j.length-1);if(j==[])j=[j];if(!d.include(k[0]))if(k[1].match(/[^\*~]$/))k[1]+="*";j.push(k);return j},m=function(j){for(var k=Localization.explanations&&Localization.explanations[PickyI18n.locale]||{},r=[],p,a=0,b=j.length;a<b;a++){p=j[a];var f=p[0];f=k[f]||f;r.push([f,p[1]])}return r},n=function(j,k){return[j.replace(/([\w\s\u00c4\u00e4\u00d6\u00f6\u00dc\u00fc\u00e9\u00e8\u00e0]+)/,
|
12
12
|
"<strong>$1</strong>"),k].join(" ")},s=function(j,k){var r=Localization.explanation_delimiters[PickyI18n.locale],p=m(e(k)),a="",b=[];p=$.map(p,function(f){var o=f[0];f=f[1];if(a==""||o==a){b.push(f);a=o}else{var q=n(a,b.join(" "));b=[];b.push(f);a=o;return q}});p.push(n(a,b.join(" ")));p=p.join(" "+r+" ");return'<span class="explanation">'+j+" "+p+"</span>"},u=function(j,k){var r='<div class="header">';r+=s(k.type,k.combination);if(j.offset>0)r+='<div class="tothetop"><a href="#" onclick="javascript:$(\'body\').animate({scrollTop: 0}, 500);">↑</a></div>';
|
13
13
|
return r};this.render=function(j){var k=$("#picky div.results");j.allocations.each(function(r,p){k.append(u(j,p)).append(p.entries.join("")).append(c.render(j));k.children("li").wrapAll(g)})}};function AllocationRenderer(c,i){function g(a){var b={},f={},o=[],q;q=0;for(l=a.length;q<l;q++){var w=a[q][0];if(w in b){b[w]=b[w]+" "+a[q][1];o.push(q)}else{b[w]=a[q][1];f[q]=w}}for(q in f)a[q][1]=b[f[q]];for(q=o.length-1;q>=0;q--)a.remove(o[q]);return a}function d(a){return $.map(a,function(b,f){return"%"+(f+1)+"$s"}).join(" ")}function e(a){if(a.length==0)return"";var b=a=g(a);b.sort(function(x,y){return x[0]<y[0]?-1:1});for(var f=[],o=0,q=b.length;o<q;o++)f.push(b[o][0]);var w=f.length==1,v=r[f]||
|
@@ -3,44 +3,33 @@
|
|
3
3
|
# TODO Adapt the generated example
|
4
4
|
# (a library books finder) to what you need.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
# Ask me or the google group if you have questions or specific requests.
|
6
|
+
# Questions? Mail me, IRC #picky, the google group, http://github.com/floere/picky/wiki.
|
8
7
|
#
|
9
8
|
class PickySearch < Application
|
10
9
|
|
11
|
-
#
|
10
|
+
# How text is indexed.
|
12
11
|
#
|
13
12
|
default_indexing removes_characters: /[^a-zA-Z0-9\s\/\-\"\&\.]/,
|
14
13
|
stopwords: /\b(and|the|of|it|in|for)\b/,
|
15
14
|
splits_text_on: /[\s\/\-\"\&\.]/
|
16
15
|
|
17
|
-
#
|
16
|
+
# How query text is preprocessed.
|
18
17
|
#
|
19
18
|
default_querying removes_characters: /[^a-zA-Z0-9\s\/\-\,\&\"\~\*\:]/, # Picky needs control chars *"~: to pass through.
|
20
19
|
stopwords: /\b(and|the|of|it|in|for)\b/,
|
21
20
|
splits_text_on: /[\s\/\-\,\&]+/,
|
22
|
-
|
23
|
-
maximum_tokens: 5, # Amount of tokens passing into a query (5 = default).
|
21
|
+
maximum_tokens: 5, # Amount of tokens used in a search (5 = default).
|
24
22
|
substitutes_characters_with: CharacterSubstituters::WestEuropean.new # Normalizes special user input, Ä -> Ae, ñ -> n etc.
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
books_index.define_category :author,
|
35
|
-
partial: Partial::Substring.new(from: 1)
|
36
|
-
books_index.define_category :year,
|
37
|
-
partial: Partial::None.new # Partial substring searching on the year does not make
|
38
|
-
# much sense, neither does similarity.
|
39
|
-
|
40
|
-
options = { :weights => { [:title, :author] => +3, [:title] => +1 } } # +/- points for combinations.
|
41
|
-
|
42
|
-
route %r{\A/books\Z} => Search.new(books_index, options)
|
24
|
+
library_src = Sources::CSV.new :title, :author, :year, file: 'app/library.csv'
|
25
|
+
books_index = Index::Memory.new :books, library_src do
|
26
|
+
category :title,
|
27
|
+
similarity: Similarity::Phonetic.new(3), # Default is no similarity.
|
28
|
+
partial: Partial::Substring.new(from: 1) # Default is from: -3.
|
29
|
+
category :author, partial: Partial::Substring.new(from: 1)
|
30
|
+
category :year, partial: Partial::None.new
|
31
|
+
end
|
43
32
|
|
44
|
-
|
33
|
+
route %r{\A/books\Z} => Search.new(books_index, :weights => { [:title, :author] => +3, [:title] => +1 })
|
45
34
|
|
46
35
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: picky-generators
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: 6
|
5
|
-
version: 2.0.0.
|
5
|
+
version: 2.0.0.pre2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Florian Hanke
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-03-
|
13
|
+
date: 2011-03-21 00:00:00 +01:00
|
14
14
|
default_executable: picky-generate
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
requirements:
|
33
33
|
- - ~>
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: 2.0.0.
|
35
|
+
version: 2.0.0.pre2
|
36
36
|
type: :runtime
|
37
37
|
version_requirements: *id002
|
38
38
|
- !ruby/object:Gem::Dependency
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
requirements:
|
44
44
|
- - ~>
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 2.0.0.
|
46
|
+
version: 2.0.0.pre2
|
47
47
|
type: :runtime
|
48
48
|
version_requirements: *id003
|
49
49
|
description: Generators for Picky.
|