cheap_skate 0.0.1 → 0.0.2
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/bin/cheapskate +5 -0
- data/conf/cheapskate.yml-dist +1 -1
- data/lib/cheap_skate/application.rb +2 -2
- data/lib/cheap_skate/cli.rb +48 -0
- data/lib/cheap_skate/index.rb +40 -1
- data/lib/cheap_skate/models.rb +1 -1
- data/lib/cheap_skate/schema.rb +191 -189
- data/lib/cheap_skate/tasks.rb +123 -0
- metadata +8 -5
data/bin/cheapskate
ADDED
data/conf/cheapskate.yml-dist
CHANGED
@@ -61,8 +61,8 @@ END
|
|
61
61
|
end
|
62
62
|
|
63
63
|
before do
|
64
|
-
if
|
65
|
-
request.path_info.sub!(/^#{
|
64
|
+
if options.prefix_path
|
65
|
+
request.path_info.sub!(/^#{options.prefix_path}/,'')
|
66
66
|
end
|
67
67
|
unless request.path_info[-1,1] == "/"
|
68
68
|
request.path_info << "/"
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'yaml'
|
3
|
+
require 'fileutils'
|
4
|
+
require File.dirname(__FILE__)+'/tasks'
|
5
|
+
|
6
|
+
module CheapSkate
|
7
|
+
class CLI < Rake::Application
|
8
|
+
def initialize
|
9
|
+
super
|
10
|
+
end
|
11
|
+
def load_rakefile
|
12
|
+
@name = 'cheapskate'
|
13
|
+
|
14
|
+
# Load the main warbler tasks
|
15
|
+
CheapSkate::Task.new
|
16
|
+
|
17
|
+
task :default => :help
|
18
|
+
|
19
|
+
desc "Create a new CheapSkate instance"
|
20
|
+
task :init => "cheapskate:init"
|
21
|
+
|
22
|
+
desc "Convert a Solr schema.xml to CheapSkate schema.yml"
|
23
|
+
task :convertschema => "cheapskate:convertschema"
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# Loads the project Rakefile in a separate application
|
28
|
+
def load_project_rakefile
|
29
|
+
Rake.application = Rake::Application.new
|
30
|
+
Rake::Application::DEFAULT_RAKEFILES.each do |rf|
|
31
|
+
if File.exist?(rf)
|
32
|
+
load rf
|
33
|
+
break
|
34
|
+
end
|
35
|
+
end
|
36
|
+
Rake.application = self
|
37
|
+
end
|
38
|
+
|
39
|
+
# Run the application: The equivalent code for the +warble+ command
|
40
|
+
# is simply <tt>Warbler::Application.new.run</tt>.
|
41
|
+
def run
|
42
|
+
Rake.application = self
|
43
|
+
super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
data/lib/cheap_skate/index.rb
CHANGED
@@ -153,7 +153,7 @@ module CheapSkate
|
|
153
153
|
bool.add_query(filtq, :must)
|
154
154
|
else
|
155
155
|
(idx, term) = fq.split(":")
|
156
|
-
term.sub
|
156
|
+
term = term.sub(/^\"/,'').sub(/\"$/,'')
|
157
157
|
bool.add_query(Ferret::Search::TermQuery.new(idx.to_sym, term), :must)
|
158
158
|
end
|
159
159
|
end
|
@@ -169,7 +169,46 @@ module CheapSkate
|
|
169
169
|
end
|
170
170
|
|
171
171
|
def parse_morelikethis_query(params)
|
172
|
+
q = case params["q"].class.name
|
173
|
+
when "Array" then params["q"].first
|
174
|
+
when "String" then params["q"]
|
175
|
+
else "*:*"
|
176
|
+
end
|
177
|
+
opts = {}
|
178
|
+
opts[:limit] = 1
|
179
|
+
if params['mlt.match.offset']
|
180
|
+
opts[:offset] = [*params['mlt.match.offset']].first.to_i
|
181
|
+
end
|
182
|
+
mlt = nil
|
183
|
+
self.search_each(q, opts) do |doc, score|
|
184
|
+
mlt = self[doc].load
|
185
|
+
end
|
186
|
+
bool = Ferret::Search::BooleanQuery.new
|
187
|
+
unless params['mlt.match.include'] && [*params['mlt.match.include']].first == "true"
|
188
|
+
b = Ferret::Search::BooleanQuery.new
|
189
|
+
bool.add_query(Ferret::Search::TermQuery.new(:id, mlt[:id]), :must_not)
|
190
|
+
end
|
191
|
+
mlt.each_pair do |key, val|
|
192
|
+
|
193
|
+
if val.is_a?(Array)
|
194
|
+
val.each do | v |
|
195
|
+
b = Ferret::Search::BooleanQuery.new
|
196
|
+
b.add_query(Ferret::Search::TermQuery.new(key, v))
|
197
|
+
bool << b
|
198
|
+
end
|
199
|
+
else
|
200
|
+
b = Ferret::Search::BooleanQuery.new
|
201
|
+
b.add_query(Ferret::Search::TermQuery.new(key, val))
|
202
|
+
bool << b
|
203
|
+
end
|
204
|
+
end
|
205
|
+
query = CheapSkate::Query.new
|
206
|
+
|
207
|
+
# No idea why this is necessary, but Ferret will ignore our boolean NOT otherwise
|
208
|
+
p = Ferret::QueryParser.new
|
209
|
+
query.query = p.parse(bool.to_s)
|
172
210
|
|
211
|
+
return query
|
173
212
|
end
|
174
213
|
|
175
214
|
def create_document(id=UUID.generate, boost=1.0)
|
data/lib/cheap_skate/models.rb
CHANGED
@@ -263,7 +263,7 @@ end
|
|
263
263
|
next
|
264
264
|
end
|
265
265
|
if @fields[i] == "id"
|
266
|
-
doc[@index.schema.id_field] = field
|
266
|
+
doc[@index.schema.id_field] = field.strip
|
267
267
|
else
|
268
268
|
if @field_meta[@fields[i]] && @field_meta[@fields[i]]["split"] == "true"
|
269
269
|
field.split(@field_meta[@fields[i]]["separator"]).each do |f|
|
data/lib/cheap_skate/schema.rb
CHANGED
@@ -1,227 +1,229 @@
|
|
1
1
|
require 'rexml/document'
|
2
2
|
require 'yaml'
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
3
|
+
module CheapSkate
|
4
|
+
class Schema
|
5
|
+
include CheapSkate
|
6
|
+
attr_reader :name, :fields, :config, :field_types, :id_field, :copy_fields, :dynamic_fields, :default_field, :default_operator
|
7
|
+
def self.xml_to_yaml(xml)
|
8
|
+
doc = REXML::Document.new xml
|
9
|
+
y = {"schema"=>{"types"=>{}, "fields"=>{}}}
|
10
|
+
y["schema"]["name"] = doc.root.attributes["name"]
|
11
|
+
y["schema"]["version"] = doc.root.attributes["version"]
|
12
|
+
doc.each_element("/schema/fields/field") do |field|
|
13
|
+
f = {}
|
14
|
+
field.attributes.each do |a,v|
|
15
|
+
next if a == "name"
|
16
|
+
f[a] = case v
|
17
|
+
when "true" then true
|
18
|
+
when "false" then false
|
19
|
+
else v
|
20
|
+
end
|
19
21
|
end
|
22
|
+
y["schema"]["fields"][field.attributes['name']] = f
|
20
23
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
else v
|
24
|
+
doc.each_element("/schema/fields/dynamicField") do |dyn_field|
|
25
|
+
f = {}
|
26
|
+
dyn_field.attributes.each do |a,v|
|
27
|
+
next if a == "name"
|
28
|
+
f[a] = case v
|
29
|
+
when "true" then true
|
30
|
+
when "false" then false
|
31
|
+
else v
|
32
|
+
end
|
31
33
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
t[:index] = :omit_norms
|
48
|
-
end
|
49
|
-
unless t[:type] == :text
|
50
|
-
if t[:index] == :omit_norms
|
51
|
-
t[:index] = :untokenized_omit_norms
|
52
|
-
else
|
53
|
-
t[:index] = :untokenized
|
34
|
+
y["schema"]["dynamic_fields"] ||= {}
|
35
|
+
y["schema"]["dynamic_fields"][dyn_field.attributes['name']] = f
|
36
|
+
end
|
37
|
+
doc.each_element("/schema/types/fieldType") do |type|
|
38
|
+
t = {}
|
39
|
+
t[:type] = case type.attributes['class']
|
40
|
+
when "solr.StrField" then :string
|
41
|
+
when "solr.TextField" then :text
|
42
|
+
when "solr.IntField" then :int
|
43
|
+
when "solr.FloatField" then :float
|
44
|
+
when "solr.BoolField" then :bool
|
45
|
+
when "solr.DateField" then :date
|
46
|
+
end
|
47
|
+
if type.attributes['omitNorms'] && type.attributes['omitNorms'] == "true"
|
48
|
+
t[:index] = :omit_norms
|
54
49
|
end
|
50
|
+
unless t[:type] == :text
|
51
|
+
if t[:index] == :omit_norms
|
52
|
+
t[:index] = :untokenized_omit_norms
|
53
|
+
else
|
54
|
+
t[:index] = :untokenized
|
55
|
+
end
|
56
|
+
end
|
57
|
+
y["schema"]["types"][type.attributes['name']] = t
|
55
58
|
end
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
59
|
+
doc.each_element("/schema/types/fieldtype") do |type|
|
60
|
+
t = {}
|
61
|
+
t[:type] = case type.attributes['class']
|
62
|
+
when "solr.StrField" then :string
|
63
|
+
when "solr.TextField" then :text
|
64
|
+
when "solr.IntField" then :int
|
65
|
+
when "solr.FloatField" then :float
|
66
|
+
when "solr.BoolField" then :bool
|
67
|
+
when "solr.DateField" then :date
|
68
|
+
end
|
69
|
+
if type.attributes['omitNorms'] && type.attributes['omitNorms'] == "true"
|
70
|
+
t[:index] = :omit_norms
|
71
|
+
end
|
72
|
+
unless t[:type] == :text
|
73
|
+
if t[:index] == :omit_norms
|
74
|
+
t[:index] = :untokenized_omit_norms
|
75
|
+
else
|
76
|
+
t[:index] = :untokenized
|
77
|
+
end
|
78
|
+
end
|
79
|
+
y["schema"]["types"][type.attributes['name']] = t
|
80
|
+
end
|
81
|
+
if dflt = doc.elements['/schema/defaultSearchField']
|
82
|
+
y["schema"]["defaultSearchField"] = dflt.get_text.value if dflt.has_text?
|
67
83
|
end
|
68
|
-
if
|
69
|
-
|
84
|
+
if uniq_key = doc.elements['/schema/uniqueKey']
|
85
|
+
y["schema"]["uniqueKey"] = uniq_key.get_text.value if uniq_key.has_text?
|
86
|
+
end
|
87
|
+
copy_fields = []
|
88
|
+
doc.each_element("/schema/copyField") do |copy|
|
89
|
+
copy_fields << {copy.attributes['source']=>copy.attributes['dest']}
|
70
90
|
end
|
71
|
-
unless
|
72
|
-
|
73
|
-
t[:index] = :untokenized_omit_norms
|
74
|
-
else
|
75
|
-
t[:index] = :untokenized
|
76
|
-
end
|
91
|
+
unless copy_fields.empty?
|
92
|
+
y["schema"]["copyFields"] = copy_fields
|
77
93
|
end
|
78
|
-
y
|
79
|
-
end
|
80
|
-
if dflt = doc.elements['/schema/defaultSearchField']
|
81
|
-
y["schema"]["defaultSearchField"] = dflt.get_text.value if dflt.has_text?
|
94
|
+
y.to_yaml
|
82
95
|
end
|
83
|
-
if uniq_key = doc.elements['/schema/uniqueKey']
|
84
|
-
y["schema"]["uniqueKey"] = uniq_key.get_text.value if uniq_key.has_text?
|
85
|
-
end
|
86
|
-
copy_fields = []
|
87
|
-
doc.each_element("/schema/copyField") do |copy|
|
88
|
-
copy_fields << {copy.attributes['source']=>copy.attributes['dest']}
|
89
|
-
end
|
90
|
-
unless copy_fields.empty?
|
91
|
-
y["schema"]["copyFields"] = copy_fields
|
92
|
-
end
|
93
|
-
y.to_yaml
|
94
|
-
end
|
95
96
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
def initialize
|
103
|
-
@copy_fields = {}
|
104
|
-
end
|
97
|
+
def self.new_from_config(config_hash)
|
98
|
+
schema = self.new
|
99
|
+
schema.load_from_conf(config_hash)
|
100
|
+
schema
|
101
|
+
end
|
105
102
|
|
106
|
-
|
107
|
-
|
108
|
-
@field_types ={}
|
109
|
-
@name = conf['schema']['name']
|
110
|
-
conf['schema']['fields'].keys.each do |field|
|
111
|
-
@fields[field.to_sym] = {}
|
112
|
-
fld = conf['schema']['fields'][field]
|
113
|
-
@fields[field.to_sym][:field_type] = fld['type'].to_sym
|
114
|
-
if fld['indexed'] == false
|
115
|
-
@fields[field.to_sym][:index] = :no
|
116
|
-
end
|
117
|
-
if fld['stored'] == false
|
118
|
-
@fields[field.to_sym][:store] = :no
|
119
|
-
end
|
120
|
-
@fields[field.to_sym][:multi_valued] = fld['multiValued']||false
|
103
|
+
def initialize
|
104
|
+
@copy_fields = {}
|
121
105
|
end
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
106
|
+
|
107
|
+
def load_from_conf(conf)
|
108
|
+
@fields ={}
|
109
|
+
@field_types ={}
|
110
|
+
@name = conf['schema']['name']
|
111
|
+
conf['schema']['fields'].keys.each do |field|
|
112
|
+
@fields[field.to_sym] = {}
|
113
|
+
fld = conf['schema']['fields'][field]
|
114
|
+
@fields[field.to_sym][:field_type] = fld['type'].to_sym
|
128
115
|
if fld['indexed'] == false
|
129
|
-
@
|
116
|
+
@fields[field.to_sym][:index] = :no
|
130
117
|
end
|
131
118
|
if fld['stored'] == false
|
132
|
-
@
|
119
|
+
@fields[field.to_sym][:store] = :no
|
120
|
+
end
|
121
|
+
@fields[field.to_sym][:multi_valued] = fld['multiValued']||false
|
122
|
+
end
|
123
|
+
if conf['schema']['dynamic_fields']
|
124
|
+
conf['schema']['dynamic_fields'].keys.each do |field|
|
125
|
+
@dynamic_fields ||= {}
|
126
|
+
@dynamic_fields[field.to_sym] = {}
|
127
|
+
fld = conf['schema']['dynamic_fields'][field]
|
128
|
+
@dynamic_fields[field.to_sym][:field_type] = fld['type'].to_sym
|
129
|
+
if fld['indexed'] == false
|
130
|
+
@dynamic_fields[field.to_sym][:index] = :no
|
131
|
+
end
|
132
|
+
if fld['stored'] == false
|
133
|
+
@dynamic_fields[field.to_sym][:store] = :no
|
134
|
+
end
|
135
|
+
@dynamic_fields[field.to_sym][:multi_valued] = fld['multiValued']||false
|
133
136
|
end
|
134
|
-
@dynamic_fields[field.to_sym][:multi_valued] = fld['multiValued']||false
|
135
137
|
end
|
136
|
-
|
137
|
-
|
138
|
-
@field_types[type.to_sym] = conf['schema']['types'][type]
|
139
|
-
end
|
140
|
-
conf['schema']['copyFields'].each do |copy|
|
141
|
-
copy.each_pair do | orig, dest|
|
142
|
-
@copy_fields[orig.to_sym] ||= []
|
143
|
-
@copy_fields[orig.to_sym] << dest.to_sym
|
138
|
+
conf['schema']['types'].keys.each do |type|
|
139
|
+
@field_types[type.to_sym] = conf['schema']['types'][type]
|
144
140
|
end
|
141
|
+
conf['schema']['copyFields'].each do |copy|
|
142
|
+
copy.each_pair do | orig, dest|
|
143
|
+
@copy_fields[orig.to_sym] ||= []
|
144
|
+
@copy_fields[orig.to_sym] << dest.to_sym
|
145
|
+
end
|
146
|
+
end
|
147
|
+
@id_field = (conf['schema']['uniqueKey'] || "id").to_sym
|
148
|
+
@default_field = (conf['schema']['defaultSearchField']||"*").to_sym
|
149
|
+
@default_operator = (conf['schema']['defaultOperator']||"OR")
|
145
150
|
end
|
146
|
-
@id_field = (conf['schema']['uniqueKey'] || "id").to_sym
|
147
|
-
@default_field = (conf['schema']['defaultSearchField']||"*").to_sym
|
148
|
-
@default_operator = (conf['schema']['defaultOperator']||"OR")
|
149
|
-
end
|
150
151
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
152
|
+
def typed_document(lazy_doc)
|
153
|
+
doc = {}
|
154
|
+
lazy_doc.fields.each do |field|
|
155
|
+
[*lazy_doc[field]].each do |fld|
|
156
|
+
if doc[field]
|
157
|
+
doc[field] = [*doc[field]]
|
158
|
+
doc[field] << type_field(field, fld)
|
159
|
+
elsif multi_valued?(field)
|
160
|
+
doc[field] = [type_field(field, fld)]
|
161
|
+
else
|
162
|
+
doc[field] = type_field(field, fld)
|
163
|
+
end
|
162
164
|
end
|
163
165
|
end
|
166
|
+
doc
|
164
167
|
end
|
165
|
-
doc
|
166
|
-
end
|
167
168
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
169
|
+
def multi_valued?(field)
|
170
|
+
if @fields[field]
|
171
|
+
return @fields[field][:multi_valued]
|
172
|
+
else
|
173
|
+
dyn_field = nil
|
174
|
+
@dynamic_fields.keys.each do |dyn|
|
175
|
+
if dyn =~ /^\*/
|
176
|
+
r = Regexp.new(dyn.sub(/^\*/,".*"))
|
177
|
+
elsif dyn =~ /\*$/
|
178
|
+
r = Regexp.new(dyn.sub(/\*$/,".*"))
|
179
|
+
end
|
180
|
+
if field =~ dyn
|
181
|
+
dyn_field = dyn
|
182
|
+
break
|
183
|
+
end
|
178
184
|
end
|
179
|
-
|
180
|
-
dyn_field = dyn
|
181
|
-
break
|
182
|
-
end
|
185
|
+
return dyn_field[:multi_valued] if dyn_field
|
183
186
|
end
|
184
|
-
|
187
|
+
false
|
185
188
|
end
|
186
|
-
false
|
187
|
-
end
|
188
189
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
190
|
+
def type_field(field_name, value)
|
191
|
+
return value.to_s unless @fields[field_name]
|
192
|
+
val = case @field_types[@fields[field_name][:field_type]][:type]
|
193
|
+
when :string then value.to_s
|
194
|
+
when :text then value.to_s
|
195
|
+
when :int then value.to_i
|
196
|
+
when :float then value.to_f
|
197
|
+
when :date then Date.parse(value)
|
198
|
+
when :bool
|
199
|
+
if value == "true"
|
200
|
+
true
|
201
|
+
else
|
202
|
+
false
|
203
|
+
end
|
200
204
|
else
|
201
|
-
|
205
|
+
val.to_s
|
202
206
|
end
|
203
|
-
|
204
|
-
val.to_s
|
207
|
+
val
|
205
208
|
end
|
206
|
-
val
|
207
|
-
end
|
208
|
-
|
209
|
-
def field_names
|
210
|
-
return @fields.keys
|
211
|
-
end
|
212
209
|
|
213
|
-
|
214
|
-
|
215
|
-
if @fields[field_name][:index] == :no
|
216
|
-
opts[:index] = :no
|
217
|
-
opts[:term_vector] = :no
|
218
|
-
elsif @field_types[@fields[field_name][:field_type]][:index]
|
219
|
-
opts[:index] = @field_types[@fields[field_name][:field_type]][:index]
|
210
|
+
def field_names
|
211
|
+
return @fields.keys
|
220
212
|
end
|
221
|
-
|
222
|
-
|
213
|
+
|
214
|
+
def field_to_field_info(field_name)
|
215
|
+
opts = {}
|
216
|
+
if @fields[field_name][:index] == :no
|
217
|
+
opts[:index] = :no
|
218
|
+
opts[:term_vector] = :no
|
219
|
+
elsif @field_types[@fields[field_name][:field_type]][:index]
|
220
|
+
opts[:index] = @field_types[@fields[field_name][:field_type]][:index]
|
221
|
+
end
|
222
|
+
if @fields[field_name][:stored] == :no
|
223
|
+
opts[:store] = :no
|
224
|
+
end
|
225
|
+
Ferret::Index::FieldInfo.new(field_name, opts)
|
223
226
|
end
|
224
|
-
Ferret::Index::FieldInfo.new(field_name, opts)
|
225
|
-
end
|
226
227
|
|
228
|
+
end
|
227
229
|
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'rake/tasklib'
|
2
|
+
require File.dirname(__FILE__)+'/schema'
|
3
|
+
module CheapSkate
|
4
|
+
class Task < Rake::TaskLib
|
5
|
+
attr_accessor :name
|
6
|
+
def initialize(name = :cheapskate)
|
7
|
+
@name = name
|
8
|
+
|
9
|
+
yield self if block_given?
|
10
|
+
define_tasks
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def define_tasks
|
15
|
+
define_help_task
|
16
|
+
namespace name do
|
17
|
+
define_init_task
|
18
|
+
define_convertschema_task
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_help_task
|
23
|
+
desc "Explains the available commands"
|
24
|
+
task "help" do
|
25
|
+
puts "Available commands:\n\n"
|
26
|
+
puts "\tcheapskate init [project_name] # creates a new CheapSkate instance"
|
27
|
+
puts "\tcheapskate convertschema xml=/path/to/schema.xml {yaml=/path/to/output/schema.yml} # converts a schema.xml to schema.yml"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def define_init_task
|
32
|
+
|
33
|
+
task :init do |t|
|
34
|
+
args = ARGV
|
35
|
+
raise ArgumentError, "Must supply an project name. Usage: cheapskate init {project_name}" if args.length < 2
|
36
|
+
raise ArgumentError, "Too many arguments supplied. Usage: cheapskate init {project_name}" if args.length > 2
|
37
|
+
raise ArgumentError, "First argument was not 'init' -- how did we get here?!" unless args.first == 'init'
|
38
|
+
cwd = Dir.getwd
|
39
|
+
project = args[1]
|
40
|
+
puts "Create new CheapSkate in #{cwd}/#{project}? [y/N]"
|
41
|
+
STDOUT.flush
|
42
|
+
input = STDIN.gets
|
43
|
+
input.chomp!
|
44
|
+
input = "N" if input !~ /^y$/i
|
45
|
+
if input == "N"
|
46
|
+
puts "Exiting."
|
47
|
+
exit
|
48
|
+
else
|
49
|
+
if exists = File.exists?("#{cwd}/#{project}")
|
50
|
+
puts "A directory already exists at #{cwd}/#{project}!\nExiting."
|
51
|
+
exit
|
52
|
+
else
|
53
|
+
puts "Creating CheapSkate root: #{cwd}/#{project}"
|
54
|
+
root = FileUtils.mkdir("#{cwd}/#{project}")
|
55
|
+
puts "Creating configuration directory: #{cwd}/#{project}/conf"
|
56
|
+
conf = FileUtils.mkdir("#{cwd}/#{project}/conf")
|
57
|
+
puts "Creating directory for the Ferret index: #{cwd}/#{project}/db"
|
58
|
+
db = FileUtils.mkdir("#{cwd}/#{project}/db")
|
59
|
+
puts "Creating log directory: #{cwd}/#{project}/log"
|
60
|
+
db = FileUtils.mkdir("#{cwd}/#{project}/log")
|
61
|
+
puts "Creating public directory: #{cwd}/#{project}/public"
|
62
|
+
db = FileUtils.mkdir("#{cwd}/#{project}/public")
|
63
|
+
config = {project.to_sym=>{:ferret=>{:path=>"db/skate"}, :facet_score_threshold=>0.0, :schema=>"conf/schema.yml"}}
|
64
|
+
puts "Writing default cheapskate.yml"
|
65
|
+
cs_yml = open("#{cwd}/#{project}/conf/cheapskate.yml", "w")
|
66
|
+
cs_yml << config.to_yaml
|
67
|
+
cs_yml.close
|
68
|
+
schema = {"schema"=>{"name"=>"example", "copyFields"=>[{"cat"=>"text"}, {"name"=>"text"}, {"manu"=>"text"}, {"features"=>"text"}, {"includes"=>"text"}, {"manu"=>"manu_exact"}], "fields"=>{"name"=>{"stored"=>true, "indexed"=>true, "type"=>"textgen"}, "cat"=>{"stored"=>true, "multiValued"=>true, "indexed"=>true, "type"=>"text_ws", "omitNorms"=>true}, "price"=>{"stored"=>true, "indexed"=>true, "type"=>"float"}, "popularity"=>{"stored"=>true, "indexed"=>true, "type"=>"int"}, "category"=>{"stored"=>true, "indexed"=>true, "type"=>"textgen"}, "includes"=>{"termOffsets"=>true, "stored"=>true, "indexed"=>true, "termVectors"=>true, "type"=>"text", "termPositions"=>true}, "title"=>{"stored"=>true, "multiValued"=>true, "indexed"=>true, "type"=>"text"}, "comments"=>{"stored"=>true, "indexed"=>true, "type"=>"text"}, "author"=>{"stored"=>true, "indexed"=>true, "type"=>"textgen"}, "content_type"=>{"stored"=>true, "multiValued"=>true, "indexed"=>true, "type"=>"string"}, "weight"=>{"stored"=>true, "indexed"=>true, "type"=>"float"}, "text"=>{"stored"=>false, "multiValued"=>true, "indexed"=>true, "type"=>"text"}, "id"=>{"required"=>true, "stored"=>true, "indexed"=>true, "type"=>"string"}, "subject"=>{"stored"=>true, "indexed"=>true, "type"=>"text"}, "text_rev"=>{"stored"=>false, "multiValued"=>true, "indexed"=>true, "type"=>"text_rev"}, "sku"=>{"stored"=>true, "indexed"=>true, "type"=>"textTight", "omitNorms"=>true}, "features"=>{"stored"=>true, "multiValued"=>true, "indexed"=>true, "type"=>"text"}, "links"=>{"stored"=>true, "multiValued"=>true, "indexed"=>true, "type"=>"string"}, "manu_exact"=>{"stored"=>false, "indexed"=>true, "type"=>"string"}, "inStock"=>{"stored"=>true, "indexed"=>true, "type"=>"boolean"}, "description"=>{"stored"=>true, "indexed"=>true, "type"=>"text"}, "alphaNameSort"=>{"stored"=>false, "indexed"=>true, "type"=>"alphaOnlySort"}, "manu"=>{"stored"=>true, "indexed"=>true, "type"=>"textgen", "omitNorms"=>true}, "last_modified"=>{"stored"=>true, "indexed"=>true, "type"=>"date"}, "payloads"=>{"stored"=>true, "indexed"=>true, "type"=>"payloads"}, "keywords"=>{"stored"=>true, "indexed"=>true, "type"=>"textgen"}}, "uniqueKey"=>"id", "version"=>"1.2", "types"=>{"pint"=>{:type=>:int, :index=>:untokenized_omit_norms}, "boolean"=>{:type=>:bool, :index=>:untokenized_omit_norms}, "tfloat"=>{:type=>nil, :index=>:untokenized_omit_norms}, "tdate"=>{:type=>nil, :index=>:untokenized_omit_norms}, "sfloat"=>{:type=>nil, :index=>:untokenized_omit_norms}, "phonetic"=>{:type=>:text}, "plong"=>{:type=>nil, :index=>:untokenized_omit_norms}, "pfloat"=>{:type=>:float, :index=>:untokenized_omit_norms}, "pdouble"=>{:type=>nil, :index=>:untokenized_omit_norms}, "binary"=>{:type=>nil, :index=>:untokenized}, "int"=>{:type=>nil, :index=>:untokenized_omit_norms}, "text"=>{:type=>:text}, "lowercase"=>{:type=>:text}, "date"=>{:type=>nil, :index=>:untokenized_omit_norms}, "sint"=>{:type=>nil, :index=>:untokenized_omit_norms}, "slong"=>{:type=>nil, :index=>:untokenized_omit_norms}, "text_rev"=>{:type=>:text}, "tint"=>{:type=>nil, :index=>:untokenized_omit_norms}, "tlong"=>{:type=>nil, :index=>:untokenized_omit_norms}, "tdouble"=>{:type=>nil, :index=>:untokenized_omit_norms}, "random"=>{:type=>nil, :index=>:untokenized}, "text_ws"=>{:type=>:text}, "textgen"=>{:type=>:text}, "string"=>{:type=>:string, :index=>:untokenized_omit_norms}, "double"=>{:type=>nil, :index=>:untokenized_omit_norms}, "pdate"=>{:type=>:date, :index=>:untokenized_omit_norms}, "sdouble"=>{:type=>nil, :index=>:untokenized_omit_norms}, "alphaOnlySort"=>{:type=>:text, :index=>:omit_norms}, "payloads"=>{:type=>:text}, "ignored"=>{:type=>:string, :index=>:untokenized}, "float"=>{:type=>nil, :index=>:untokenized_omit_norms}, "long"=>{:type=>nil, :index=>:untokenized_omit_norms}, "textTight"=>{:type=>:text}}, "dynamic_fields"=>{"*_tf"=>{"stored"=>true, "indexed"=>true, "type"=>"tfloat"}, "*_l"=>{"stored"=>true, "indexed"=>true, "type"=>"long"}, "*_b"=>{"stored"=>true, "indexed"=>true, "type"=>"boolean"}, "*_ti"=>{"stored"=>true, "indexed"=>true, "type"=>"tint"}, "random_*"=>{"type"=>"random"}, "*_d"=>{"stored"=>true, "indexed"=>true, "type"=>"double"}, "*_f"=>{"stored"=>true, "indexed"=>true, "type"=>"float"}, "*_tl"=>{"stored"=>true, "indexed"=>true, "type"=>"tlong"}, "*_tdt"=>{"stored"=>true, "indexed"=>true, "type"=>"tdate"}, "*_pi"=>{"stored"=>true, "indexed"=>true, "type"=>"pint"}, "*_s"=>{"stored"=>true, "indexed"=>true, "type"=>"string"}, "attr_*"=>{"stored"=>true, "multiValued"=>true, "indexed"=>true, "type"=>"textgen"}, "*_i"=>{"stored"=>true, "indexed"=>true, "type"=>"int"}, "*_t"=>{"stored"=>true, "indexed"=>true, "type"=>"text"}, "*_dt"=>{"stored"=>true, "indexed"=>true, "type"=>"date"}, "*_td"=>{"stored"=>true, "indexed"=>true, "type"=>"tdouble"}, "ignored_*"=>{"multiValued"=>true, "type"=>"ignored"}}, "defaultSearchField"=>"text"}}
|
69
|
+
puts "Writing default schema.yml"
|
70
|
+
s_yml = open("#{cwd}/#{project}/conf/schema.yml", "w")
|
71
|
+
s_yml << schema.to_yaml
|
72
|
+
s_yml.close
|
73
|
+
puts "Writing default rackup file at #{cwd}/#{project}/config.ru"
|
74
|
+
rackup = open("#{cwd}/#{project}/config.ru", "w")
|
75
|
+
rackup_body =<<END
|
76
|
+
require 'rubygems'
|
77
|
+
require 'sinatra'
|
78
|
+
|
79
|
+
root_dir = File.dirname(__FILE__)
|
80
|
+
|
81
|
+
set :environment, :production
|
82
|
+
set :configuration, root_dir+"/conf/cheapskate.yml"
|
83
|
+
set :site, :#{project}
|
84
|
+
set :root, root_dir
|
85
|
+
|
86
|
+
set :logging, false
|
87
|
+
disable :run
|
88
|
+
|
89
|
+
FileUtils.mkdir_p 'log' unless File.exists?('log')
|
90
|
+
log = File.new("log/\#{Sinatra::Application.site}.log", "a")
|
91
|
+
STDOUT.reopen(log)
|
92
|
+
STDERR.reopen(log)
|
93
|
+
require 'cheap_skate'
|
94
|
+
run CheapSkate::Application
|
95
|
+
|
96
|
+
END
|
97
|
+
rackup << rackup_body
|
98
|
+
rackup.close
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
def define_convertschema_task
|
106
|
+
desc "Parses a Solr schema.xml document and outputs a CheapSkate schema.yml. Needs the arguments xml=/path/to/schema.xml Defaults to ./conf/schema.yml, use the yaml= argument to specify the output."
|
107
|
+
task "convertschema" do
|
108
|
+
raise ArgumentError, "No schema.xml specified. Usage: cheapskate convertschema xml=/path/to/schema.xml" unless ENV['xml']
|
109
|
+
xml = open(ENV['xml'],'r')
|
110
|
+
yml = CheapSkate::Schema.xml_to_yaml(xml)
|
111
|
+
if ENV['yaml']
|
112
|
+
puts "Writing #{ENV['xml']} out to #{ENV['yaml']}."
|
113
|
+
outfile = open(ENV['yaml'],'w')
|
114
|
+
else
|
115
|
+
puts "Writing #{ENV['xml']} out to ./conf/schema.yml."
|
116
|
+
outfile = open('./conf/schema.yml','w')
|
117
|
+
end
|
118
|
+
outfile << yml.to_s
|
119
|
+
outfile.close
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ross Singer
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-06-01 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -91,8 +91,9 @@ dependencies:
|
|
91
91
|
version_requirements: *id006
|
92
92
|
description: A Solr-like interface for situations where running a Java application server is not an option (such as shared web hosting).
|
93
93
|
email: rossfsinger@gmail.com
|
94
|
-
executables:
|
95
|
-
|
94
|
+
executables:
|
95
|
+
- cheapskate
|
96
|
+
- cheapskate
|
96
97
|
extensions: []
|
97
98
|
|
98
99
|
extra_rdoc_files:
|
@@ -104,9 +105,11 @@ files:
|
|
104
105
|
- config.ru-dist
|
105
106
|
- lib/cheap_skate.rb
|
106
107
|
- lib/cheap_skate/application.rb
|
108
|
+
- lib/cheap_skate/cli.rb
|
107
109
|
- lib/cheap_skate/index.rb
|
108
110
|
- lib/cheap_skate/models.rb
|
109
111
|
- lib/cheap_skate/schema.rb
|
112
|
+
- lib/cheap_skate/tasks.rb
|
110
113
|
- LICENSE
|
111
114
|
- README
|
112
115
|
has_rdoc: true
|