forked from maccman/go
-
Notifications
You must be signed in to change notification settings - Fork 2
/
app.rb
142 lines (117 loc) · 3.02 KB
/
app.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
require 'sinatra'
require 'sequel'
require 'sinatra/sequel'
require 'sinatra/respond_with'
require 'json'
# added this to make the Model.order(:symbol.desc) syntax work. May want to not use the core extensions long-term.
Sequel.extension :core_extensions
class Link < Sequel::Model
def hit!
self.hits += 1
self.save(:validate => false)
end
def validate
super
errors.add(:name, 'cannot be empty') if !name || name.empty?
errors.add(:url, 'cannot be empty') if !url || url.empty?
end
def to_json
{
name: self.name,
url: self.url,
description: self.description,
hits: self.hits,
}
end
end
# Configuration
configure do
set :erb, :escape_html => false
set :public_folder, Proc.new { File.join(root, "static") }
end
# Actions
get '/' do
@links = Link.order(:hits.desc).all
respond_with :index do |f|
f.html { erb :index, params: params }
f.json { @links.map(&:to_json).to_json }
end
end
get '/links' do
redirect '/'
end
post '/links' do
begin
Link.create(
:name => params[:name].strip,
:url => params[:url].strip,
:description => params[:description].strip,
)
redirect '/'
rescue Sequel::ValidationFailed,
Sequel::DatabaseError => e
halt "Error: #{e.message}"
end
end
get '/links/suggest' do
query = params[:q]
results = Link.filter(:name.like("#{query}%")).or(:url.like("%#{query}%"))
results = results.all.map {|r| r.name }
content_type :json
results.to_json
end
get '/links/search' do
query = params[:q]
@links = Link.filter(:name.like("#{query}%")).order(:hits.desc).all
respond_with :index do |f|
f.html { erb :index, params: params }
f.json { @links.map(&:to_json).to_json }
end
end
post '/links/:id/remove' do
link = Link.find(:id => params[:id])
halt 404 unless link
link.destroy
redirect '/'
end
post '/links/:id/update' do
link = Link.find(:id => params[:id])
halt 404 unless link
begin
link.name = params[:name]
link.description = params[:description]
link.url = params[:url]
link.save
redirect '/'
rescue Sequel::ValidationFailed,
Sequel::DatabaseError => e
halt "Error: #{e.message}"
end
end
get '/:name/?*?' do
link = Link[:name => [params[:name], params[:splat].first].join('/')]
params[:splat] = [''] if link # remove the splat so we don't reuse it
# Just try the straight link if we didn't find a matching link
link ||= Link[:name => params[:name]]
if link
link.hit!
parts = params[:splat].first.split('/')
parts = nil if parts.empty?
url = link.url
url %= parts
redirect url
else
# try to list sub-links of the namespace
filtered_links = Link.filter(:name.like("#{params[:name]}%")).order(:hits.desc).all
if filtered_links.empty?
@links = Link.order(:hits.desc).all
params[:not_found] = params[:name]
else
@links = filtered_links
params[:links_filter] = params[:name]
end
respond_with :index do |f|
f.html { erb(:index, params: params) }
end
end
end