Skip to content

Commit

Permalink
mongoid shortener created.
Browse files Browse the repository at this point in the history
  • Loading branch information
siong1987 committed Nov 17, 2011
0 parents commit 4e0d109
Show file tree
Hide file tree
Showing 56 changed files with 818 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.bundle/
log/*.log
pkg/
test/dummy/db/*.sqlite3
test/dummy/log/*.log
test/dummy/tmp/
21 changes: 21 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
source "http://rubygems.org"

# Declare your gem's dependencies in mongoid_shortener.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec

# jquery-rails is used by the dummy application
gem "jquery-rails"

gem 'mongoid', '2.2.4'
gem 'bson_ext', '1.3.1'
gem 'yab62', '1.0.1'

# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.

# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'
111 changes: 111 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
PATH
remote: .
specs:
mongoid_shortener (0.0.1)
rails (~> 3.1.1)

GEM
remote: http://rubygems.org/
specs:
actionmailer (3.1.1)
actionpack (= 3.1.1)
mail (~> 2.3.0)
actionpack (3.1.1)
activemodel (= 3.1.1)
activesupport (= 3.1.1)
builder (~> 3.0.0)
erubis (~> 2.7.0)
i18n (~> 0.6)
rack (~> 1.3.2)
rack-cache (~> 1.1)
rack-mount (~> 0.8.2)
rack-test (~> 0.6.1)
sprockets (~> 2.0.2)
activemodel (3.1.1)
activesupport (= 3.1.1)
builder (~> 3.0.0)
i18n (~> 0.6)
activerecord (3.1.1)
activemodel (= 3.1.1)
activesupport (= 3.1.1)
arel (~> 2.2.1)
tzinfo (~> 0.3.29)
activeresource (3.1.1)
activemodel (= 3.1.1)
activesupport (= 3.1.1)
activesupport (3.1.1)
multi_json (~> 1.0)
arel (2.2.1)
bson (1.3.1)
bson_ext (1.3.1)
builder (3.0.0)
erubis (2.7.0)
hike (1.2.1)
i18n (0.6.0)
jquery-rails (1.0.17)
railties (~> 3.0)
thor (~> 0.14)
json (1.6.1)
mail (2.3.0)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.17.2)
mongo (1.3.1)
bson (= 1.3.1)
mongoid (2.2.4)
activemodel (~> 3.0)
mongo (~> 1.3)
tzinfo (~> 0.3.22)
multi_json (1.0.3)
polyglot (0.3.3)
rack (1.3.5)
rack-cache (1.1)
rack (>= 0.4)
rack-mount (0.8.3)
rack (>= 1.0.0)
rack-ssl (1.3.2)
rack
rack-test (0.6.1)
rack (>= 1.0)
rails (3.1.1)
actionmailer (= 3.1.1)
actionpack (= 3.1.1)
activerecord (= 3.1.1)
activeresource (= 3.1.1)
activesupport (= 3.1.1)
bundler (~> 1.0)
railties (= 3.1.1)
railties (3.1.1)
actionpack (= 3.1.1)
activesupport (= 3.1.1)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (~> 0.14.6)
rake (0.9.2.2)
rdoc (3.11)
json (~> 1.4)
sprockets (2.0.3)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.4)
thor (0.14.6)
tilt (1.3.3)
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.31)
yab62 (1.0.1)

PLATFORMS
ruby

DEPENDENCIES
bson_ext (= 1.3.1)
jquery-rails
mongoid (= 2.2.4)
mongoid_shortener!
sqlite3
yab62 (= 1.0.1)
20 changes: 20 additions & 0 deletions MIT-LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Copyright 2011 YOURNAME

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3 changes: 3 additions & 0 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
= MongoidShortener

This project rocks and uses MIT-LICENSE.
37 changes: 37 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env rake
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
begin
require 'rdoc/task'
rescue LoadError
require 'rdoc/rdoc'
require 'rake/rdoctask'
RDoc::Task = Rake::RDocTask
end

RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'MongoidShortener'
rdoc.options << '--line-numbers'
rdoc.rdoc_files.include('README.rdoc')
rdoc.rdoc_files.include('lib/**/*.rb')
end



Bundler::GemHelper.install_tasks

require 'rake/testtask'

Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = false
end


task :default => :test
4 changes: 4 additions & 0 deletions app/controllers/mongoid_shortener/application_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module MongoidShortener
class ApplicationController < ActionController::Base
end
end
19 changes: 19 additions & 0 deletions app/controllers/mongoid_shortener/shortened_urls_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module MongoidShortener
class ShortenedUrlsController < ApplicationController
# find the real link for the shortened link key and redirect
def translate
# pull the link out of the db
sl = ShortenedUrl.where(:unique_key => params[:unique_key][1..-1]).first

if sl
sl.inc(:use_count, 1)
# do a 301 redirect to the destination url
head :moved_permanently, :location => sl.url
else
# if we don't find the shortened link, redirect to the root
# make this configurable in future versions
head :moved_permanently, :location => main_app.root_url
end
end
end
end
4 changes: 4 additions & 0 deletions app/helpers/mongoid_shortener/application_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module MongoidShortener
module ApplicationHelper
end
end
10 changes: 10 additions & 0 deletions app/helpers/mongoid_shortener/shortened_urls_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module MongoidShortener
module ShortenedUrlsHelper
# generate a url from either a url string, or a shortened url object
def shortened_url(url)
raise "Only String accepted: #{url}" unless url.class == String
short_url = MongoidShortener::ShortenedUrl.generate(url)
short_url
end
end
end
74 changes: 74 additions & 0 deletions app/models/mongoid_shortener/shortened_url.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
module MongoidShortener
class ShortenedUrl
include Mongoid::Document
include Mongoid::Timestamps

field :url, :type => String
field :unique_key, :type => String
field :use_count, :type => Integer, :default => 0

index :url, :unique => true
index :unique_key, :unique => true

URL_PROTOCOL_HTTP = "http://"

REGEX_HTTP_URL = /^\s*(http[s]?:\/\/)?[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?\s*$/i
REGEX_LINK_HAS_PROTOCOL = Regexp.new('\Ahttp:\/\/|\Ahttps:\/\/', Regexp::IGNORECASE)

validates_format_of :url, :with => REGEX_HTTP_URL, :allow_blank => true

validates_presence_of :url
validates_uniqueness_of :url

validates_presence_of :unique_key
validates_uniqueness_of :unique_key

attr_accessible :url

before_validation :clean_destination_url, :init_unique_key, :on => :create

# ensure the url starts with it protocol
def clean_destination_url
if !self.url.blank? and self.url !~ REGEX_LINK_HAS_PROTOCOL
self.url.insert(0, URL_PROTOCOL_HTTP)
end
end

def init_unique_key
# generate a unique key for the link
begin
self.unique_key = YAB62.encode62(ShortenedUrl::count)
end while ShortenedUrl::where(:unique_key => self.unique_key).first
end

# generate a shortened link from a url
# link to a user if one specified
# throw an exception if anything goes wrong
def self.generate!(orig_url)
# don't want to generate the link if it has already been generated
# so check the datastore
sl = ShortenedUrl.where(:url => orig_url).first

return sl if sl

# create the shortened link, storing it
sl = ShortenedUrl.create!(:url => orig_url)

# return the url
return sl
end

# return shortened url on success, nil on failure
def self.generate(orig_url)
sl = nil

begin
sl = ShortenedUrl::generate!(orig_url, user)
rescue
sl = nil
end

return sl
end
end
end
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MongoidShortener::Engine.routes.draw do
get '/:unique_key', :to => 'shortened_urls#translate', :constraints => { :unique_key => /~.+/ }
end
4 changes: 4 additions & 0 deletions lib/mongoid_shortener.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require "mongoid_shortener/engine"

module MongoidShortener
end
5 changes: 5 additions & 0 deletions lib/mongoid_shortener/engine.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module MongoidShortener
class Engine < Rails::Engine
isolate_namespace MongoidShortener
end
end
3 changes: 3 additions & 0 deletions lib/mongoid_shortener/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module MongoidShortener
VERSION = "0.0.1"
end
4 changes: 4 additions & 0 deletions lib/tasks/mongoid_shortener_tasks.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# desc "Explaining what the task does"
# task :mongoid_shortener do
# # Task goes here
# end
23 changes: 23 additions & 0 deletions mongoid_shortener.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
$:.push File.expand_path("../lib", __FILE__)

# Maintain your gem's version:
require "mongoid_shortener/version"

# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "mongoid_shortener"
s.version = MongoidShortener::VERSION
s.authors = ["TODO: Your name"]
s.email = ["TODO: Your email"]
s.homepage = "TODO"
s.summary = "TODO: Summary of MongoidShortener."
s.description = "TODO: Description of MongoidShortener."

s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.rdoc"]
s.test_files = Dir["test/**/*"]

s.add_dependency "rails", "~> 3.1.1"
s.add_dependency "yab62", "1.0.1"

s.add_development_dependency "sqlite3"
end
6 changes: 6 additions & 0 deletions script/rails
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env ruby
#!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.

ENGINE_PATH = File.expand_path('../..', __FILE__)
load File.expand_path('../../test/dummy/script/rails', __FILE__)
7 changes: 7 additions & 0 deletions test/dummy/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require File.expand_path('../config/application', __FILE__)

Dummy::Application.load_tasks
9 changes: 9 additions & 0 deletions test/dummy/app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
//= require jquery
//= require jquery_ujs
//= require_tree .
Loading

0 comments on commit 4e0d109

Please sign in to comment.