shawty-server 1.0.0

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/README.markdown ADDED
@@ -0,0 +1,32 @@
1
+ # Shawty
2
+
3
+
4
+ Shawty is the simplest Ruby url-shortening app ever. Run your own server that works like [tinyurl.com](tinyurl.com).
5
+
6
+
7
+ ## What you need to get this running
8
+
9
+ * Clone this: `git clone git://github.com/JackDanger/shawty-server.git`
10
+ * Signup for an account at Heroku ([better details here](http://github.com/sinatra/heroku-sinatra-app))
11
+ * push this to Heroku.com: `git push heroku master`
12
+ * Revel.
13
+
14
+
15
+ ## Why?
16
+
17
+ If you run any application with published content it's helpful to have shorter links to that content.
18
+
19
+ Consider that your Rails app might offer pages like the following:
20
+
21
+ http://myapp.com/accounts/megacorp/invoices?single_access_token=5ASD32ADf89JKASF2346
22
+
23
+ Imagine trying to fit that in a text message. Instead, how about:
24
+
25
+ http://url.myapp.com/a7D
26
+
27
+ Way groovy.
28
+
29
+
30
+ Patches welcome, forks celebrated.
31
+
32
+ Copyright (c) 2009 [Jack Danger Canty](http://jåck.com). See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "shawty-server"
5
+ gem.summary = %Q{Ultra-lightweight url shortening server for Heroku.com}
6
+ gem.description = %Q{Run your own url shortener add your own web address for free on Heroku.com}
7
+ gem.email = "gitcommit@6brand.com"
8
+ gem.homepage = "http://github.com/JackDanger/shawty-server"
9
+ gem.authors = ["Jack Danger Canty"]
10
+ gem.add_development_dependency "active_record", ">= 0"
11
+ gem.add_development_dependency "shoulda", ">= 0"
12
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13
+ end
14
+ Jeweler::GemcutterTasks.new
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
17
+ end
18
+
19
+
20
+
21
+ task :default => :test
22
+
23
+ require 'rake/testtask'
24
+ Rake::TestTask.new(:test) do |test|
25
+ test.libs << '.'
26
+ test.pattern = 'test.rb'
27
+ test.verbose = true
28
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,14 @@
1
+ credentials: &credentials
2
+ adapter: postgresql
3
+
4
+ development:
5
+ <<: *credentials
6
+ database: shawty_development
7
+
8
+ test:
9
+ <<: *credentials
10
+ database: shawty_test
11
+
12
+ staging:
13
+ <<: *credentials
14
+ database: shawty_staging
data/config.ru ADDED
@@ -0,0 +1,6 @@
1
+ require 'shawty'
2
+
3
+ ## There is no need to set directories here anymore;
4
+ ## Just run the application
5
+
6
+ run Sinatra::Application
@@ -0,0 +1,50 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{shawty-server}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jack Danger Canty"]
12
+ s.date = %q{2010-03-26}
13
+ s.description = %q{Run your own url shortener add your own web address for free on Heroku.com}
14
+ s.email = %q{gitcommit@6brand.com}
15
+ s.extra_rdoc_files = [
16
+ "README.markdown"
17
+ ]
18
+ s.files = [
19
+ "README.markdown",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "config.ru",
23
+ "config/database.yml",
24
+ "shawty-server.gemspec",
25
+ "shawty.rb",
26
+ "test.rb"
27
+ ]
28
+ s.homepage = %q{http://github.com/JackDanger/shawty-server}
29
+ s.rdoc_options = ["--charset=UTF-8"]
30
+ s.require_paths = ["lib"]
31
+ s.rubygems_version = %q{1.3.5}
32
+ s.summary = %q{Ultra-lightweight url shortening server for Heroku.com}
33
+
34
+ if s.respond_to? :specification_version then
35
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
36
+ s.specification_version = 3
37
+
38
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
39
+ s.add_development_dependency(%q<active_record>, [">= 0"])
40
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
41
+ else
42
+ s.add_dependency(%q<active_record>, [">= 0"])
43
+ s.add_dependency(%q<shoulda>, [">= 0"])
44
+ end
45
+ else
46
+ s.add_dependency(%q<active_record>, [">= 0"])
47
+ s.add_dependency(%q<shoulda>, [">= 0"])
48
+ end
49
+ end
50
+
data/shawty.rb ADDED
@@ -0,0 +1,101 @@
1
+ ## Resources
2
+ require 'rubygems'
3
+ gem 'sinatra', :version => '1.0'
4
+ require 'sinatra'
5
+ require 'active_record'
6
+ gem 'alphadecimal'
7
+ require 'alphadecimal'
8
+
9
+ ## Application
10
+
11
+ get '/' do
12
+ "Post to '/' to save a url and receive a plaintext short url in response" +
13
+ "<br />" +
14
+ "Example: POST /http://some.url/at.someplace" +
15
+ "<br />" +
16
+ "<form action=/ method=POST onsubmit='if(\"\"==this.url.value)return false;else{this.action=\"/\"+this.url.value}'><input type=text name='url' /><input type=submit value='Get Shawty' /></form>"
17
+ end
18
+
19
+ get '/:id' do
20
+ pass unless url = find_url_by_id(params[:id].alphadecimal)
21
+
22
+ redirect url, 301
23
+ end
24
+
25
+ post '*' do
26
+ pass if params[:splat].empty?
27
+
28
+ url = params[:splat].first
29
+ url = url[1, url.size] if url.chars.first == '/'
30
+
31
+ pass if url.empty?
32
+
33
+ quoted = quote url
34
+
35
+ found = execute %Q{ SELECT id FROM #{table_name} WHERE url = #{quoted} }
36
+
37
+ if found.any?
38
+ id = found.first['id']
39
+ else
40
+ connection.transaction do
41
+ found = execute %Q{
42
+ INSERT INTO #{table_name} (url, id) VALUES (#{quoted}, nextval('shawty_id_seq'));
43
+ SELECT MAX(id) from #{table_name}
44
+ }
45
+ end
46
+ id = found.first['max']
47
+ end
48
+
49
+ "http://#{request.host}/#{id.alphadecimal}"
50
+ end
51
+
52
+
53
+ ## Helpers
54
+
55
+ def find_url_by_id(id)
56
+ result = execute %Q{ SELECT url FROM #{table_name} WHERE id = #{quote id.to_i} }
57
+ return result.map.first['url'] if result.map.length > 0
58
+ end
59
+
60
+ def execute sql
61
+ connection.execute sql
62
+ end
63
+
64
+ def quote string
65
+ connection.quote string
66
+ end
67
+
68
+ def table_name
69
+ connection.quote_table_name 'shawty'
70
+ end
71
+
72
+ def connection
73
+ ActiveRecord::Base.connection
74
+ end
75
+
76
+ def initialize_database
77
+ table = execute %Q{select * from pg_tables where tablename = #{quote 'shawty'}}
78
+ return if table.any?
79
+ execute %Q{
80
+ CREATE TABLE #{table_name} (
81
+ id SERIAL PRIMARY KEY,
82
+ url varchar(255) UNIQUE
83
+ )
84
+ }
85
+ end
86
+
87
+ def database_config
88
+ YAML.load(File.read('config/database.yml'))
89
+ end
90
+
91
+ def init(environment)
92
+ ActiveRecord::Base.establish_connection database_config[environment]
93
+ initialize_database
94
+ end
95
+
96
+
97
+ ## Environments
98
+
99
+ configure :development do init 'development' end
100
+ configure :test do init 'test' end
101
+ configure :production do init 'production' end
data/test.rb ADDED
@@ -0,0 +1,95 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'active_support'
6
+ require 'shoulda'
7
+ require 'rack/test'
8
+ require 'shawty'
9
+
10
+ class ShawtyTest < Test::Unit::TestCase
11
+ include Rack::Test::Methods
12
+
13
+ def setup
14
+ execute "DELETE FROM #{table_name}"
15
+ end
16
+
17
+ def app
18
+ Sinatra::Application
19
+ end
20
+
21
+ context "on GET to /" do
22
+ setup {
23
+ get '/'
24
+ }
25
+ should "return ok" do
26
+ assert last_response.ok?
27
+ end
28
+ should "have some kind of welcome" do
29
+ assert last_response.body =~ /to save a url/
30
+ end
31
+ end
32
+
33
+ context "on GET to / with url" do
34
+ setup {
35
+ execute %Q{
36
+ INSERT INTO #{table_name} (url, id)
37
+ VALUES (
38
+ #{quote 'http://google.com/'},
39
+ nextval('shawty_id_seq')
40
+ )
41
+ }
42
+ id = execute(%Q{
43
+ SELECT id FROM #{table_name}
44
+ WHERE url = #{quote 'http://google.com/'}
45
+ }).first['id'].to_i
46
+
47
+ get "/#{id.alphadecimal}"
48
+ }
49
+ should "return a 301 redirect" do
50
+ assert_equal 301, last_response.status
51
+ end
52
+ should "return Location: header to url" do
53
+ assert_equal 'http://google.com/',
54
+ last_response.headers['Location']
55
+ end
56
+ end
57
+
58
+ context "on POST to /" do
59
+ setup {
60
+ post '/http://some.url/path.ext'
61
+ }
62
+ should "return ok" do
63
+ assert last_response.ok?
64
+ end
65
+ should_change "record count", :by => 1 do
66
+ execute(%Q{ SELECT COUNT(*) FROM #{table_name} }).first['count'].to_i
67
+ end
68
+ should "save the url" do
69
+ res = execute(%Q{
70
+ SELECT * FROM #{table_name}
71
+ WHERE url = #{quote 'http://some.url/path.ext'}
72
+ })
73
+ assert res.one?, res.map.inspect
74
+ end
75
+ should "display the shortened url" do
76
+ id = execute(%Q{
77
+ SELECT id FROM #{table_name}
78
+ WHERE url = #{quote 'http://some.url/path.ext'}
79
+ }).first['id']
80
+ assert_equal "http://example.org/#{id.alphadecimal}",
81
+ last_response.body
82
+ end
83
+ context "with a url that's been saved previously" do
84
+ setup {
85
+ post '/http://some.url/path.ext'
86
+ }
87
+ should "return ok" do
88
+ assert last_response.ok?
89
+ end
90
+ should_not_change "record count" do
91
+ execute(%Q{ SELECT COUNT(*) FROM #{table_name} }).first['count'].to_i
92
+ end
93
+ end
94
+ end
95
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shawty-server
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jack Danger Canty
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-03-26 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: active_record
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: shoulda
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: Run your own url shortener add your own web address for free on Heroku.com
36
+ email: gitcommit@6brand.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.markdown
43
+ files:
44
+ - README.markdown
45
+ - Rakefile
46
+ - VERSION
47
+ - config.ru
48
+ - config/database.yml
49
+ - shawty-server.gemspec
50
+ - shawty.rb
51
+ - test.rb
52
+ has_rdoc: true
53
+ homepage: http://github.com/JackDanger/shawty-server
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --charset=UTF-8
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.3.5
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Ultra-lightweight url shortening server for Heroku.com
80
+ test_files: []
81
+