radiospiel-app 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ gem "pg"
7
+ gem "sqlite3"
8
+ gem "redis"
9
+ gem "micro_sql"
10
+ gem "htmlentities"
11
+
12
+ # Add dependencies to develop your gem here.
13
+ # Include everything needed to run rake, tests, features, etc.
14
+ group :development do
15
+ gem "bundler"
16
+ gem "jeweler"
17
+ gem 'simplecov', :require => false
18
+ gem "ruby-debug19"
19
+ end
20
+
data/Gemfile.lock ADDED
@@ -0,0 +1,53 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ archive-tar-minitar (0.5.2)
5
+ columnize (0.3.6)
6
+ git (1.2.5)
7
+ htmlentities (4.3.1)
8
+ jeweler (1.8.3)
9
+ bundler (~> 1.0)
10
+ git (>= 1.2.5)
11
+ rake
12
+ rdoc
13
+ json (1.6.6)
14
+ linecache19 (0.5.12)
15
+ ruby_core_source (>= 0.1.4)
16
+ micro_sql (0.3.0)
17
+ pg
18
+ sqlite3
19
+ multi_json (1.2.0)
20
+ pg (0.13.2)
21
+ rake (0.9.2.2)
22
+ rdoc (3.12)
23
+ json (~> 1.4)
24
+ redis (2.2.2)
25
+ ruby-debug-base19 (0.11.25)
26
+ columnize (>= 0.3.1)
27
+ linecache19 (>= 0.5.11)
28
+ ruby_core_source (>= 0.1.4)
29
+ ruby-debug19 (0.11.6)
30
+ columnize (>= 0.3.1)
31
+ linecache19 (>= 0.5.11)
32
+ ruby-debug-base19 (>= 0.11.19)
33
+ ruby_core_source (0.1.5)
34
+ archive-tar-minitar (>= 0.5.2)
35
+ simplecov (0.6.1)
36
+ multi_json (~> 1.0)
37
+ simplecov-html (~> 0.5.3)
38
+ simplecov-html (0.5.3)
39
+ sqlite3 (1.3.5)
40
+
41
+ PLATFORMS
42
+ ruby
43
+
44
+ DEPENDENCIES
45
+ bundler
46
+ htmlentities
47
+ jeweler
48
+ micro_sql
49
+ pg
50
+ redis
51
+ ruby-debug19
52
+ simplecov
53
+ sqlite3
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 radiospiel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = app
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to app
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
+ * Fork the project.
10
+ * Start a feature/bugfix branch.
11
+ * Commit and push until you are happy with your contribution.
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2012 radiospiel. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "radiospiel-app"
18
+ gem.homepage = "http://github.com/radiospiel/app"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Application base code}
21
+ gem.description = %Q{Some basics that your application could benefit from.}
22
+ gem.email = "eno@open-lab.org"
23
+ gem.authors = ["radiospiel"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ task :default => :test
36
+
37
+ require 'rdoc/task'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "micro_sql #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/app.gemspec ADDED
@@ -0,0 +1,97 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "app"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["radiospiel"]
12
+ s.date = "2012-04-03"
13
+ s.description = "Some basics that your application could benefit from."
14
+ s.email = "eno@open-lab.org"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "app.tmproj",
28
+ "config/app.yml",
29
+ "lib/app.rb",
30
+ "lib/app/app.rb",
31
+ "lib/app/app/cache.rb",
32
+ "lib/app/app/config.rb",
33
+ "lib/app/app/logger.rb",
34
+ "lib/app/app/root.rb",
35
+ "lib/core-extensions/benchmark-logger.rb",
36
+ "lib/core-extensions/cgi_ext.rb",
37
+ "lib/core-extensions/object_ext.rb",
38
+ "lib/core-extensions/string_ext.rb",
39
+ "lib/core-extensions/string_without_accents.rb",
40
+ "lib/core-extensions/tls.rb",
41
+ "lib/core-extensions/uids.rb",
42
+ "lib/extensions/http.rb",
43
+ "lib/extensions/zz_geocoder.rb",
44
+ "script/watchr",
45
+ "test/app_test.rb",
46
+ "test/cache_test.rb",
47
+ "test/cgi_ext_test.rb",
48
+ "test/config.yml",
49
+ "test/config_test.rb",
50
+ "test/helper.rb",
51
+ "test/string_ext_test.rb",
52
+ "test/tls_test.rb",
53
+ "test/uid_test.rb"
54
+ ]
55
+ s.homepage = "http://github.com/radiospiel/appbase"
56
+ s.licenses = ["MIT"]
57
+ s.require_paths = ["lib"]
58
+ s.rubygems_version = "1.8.17"
59
+ s.summary = "Application base code"
60
+
61
+ if s.respond_to? :specification_version then
62
+ s.specification_version = 3
63
+
64
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
65
+ s.add_runtime_dependency(%q<pg>, [">= 0"])
66
+ s.add_runtime_dependency(%q<sqlite3>, [">= 0"])
67
+ s.add_runtime_dependency(%q<redis>, [">= 0"])
68
+ s.add_runtime_dependency(%q<micro_sql>, [">= 0"])
69
+ s.add_runtime_dependency(%q<htmlentities>, [">= 0"])
70
+ s.add_development_dependency(%q<bundler>, [">= 0"])
71
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
72
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
73
+ s.add_development_dependency(%q<ruby-debug19>, [">= 0"])
74
+ else
75
+ s.add_dependency(%q<pg>, [">= 0"])
76
+ s.add_dependency(%q<sqlite3>, [">= 0"])
77
+ s.add_dependency(%q<redis>, [">= 0"])
78
+ s.add_dependency(%q<micro_sql>, [">= 0"])
79
+ s.add_dependency(%q<htmlentities>, [">= 0"])
80
+ s.add_dependency(%q<bundler>, [">= 0"])
81
+ s.add_dependency(%q<jeweler>, [">= 0"])
82
+ s.add_dependency(%q<simplecov>, [">= 0"])
83
+ s.add_dependency(%q<ruby-debug19>, [">= 0"])
84
+ end
85
+ else
86
+ s.add_dependency(%q<pg>, [">= 0"])
87
+ s.add_dependency(%q<sqlite3>, [">= 0"])
88
+ s.add_dependency(%q<redis>, [">= 0"])
89
+ s.add_dependency(%q<micro_sql>, [">= 0"])
90
+ s.add_dependency(%q<htmlentities>, [">= 0"])
91
+ s.add_dependency(%q<bundler>, [">= 0"])
92
+ s.add_dependency(%q<jeweler>, [">= 0"])
93
+ s.add_dependency(%q<simplecov>, [">= 0"])
94
+ s.add_dependency(%q<ruby-debug19>, [">= 0"])
95
+ end
96
+ end
97
+
data/app.tmproj ADDED
@@ -0,0 +1,95 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>currentDocument</key>
6
+ <string>lib/app/app/config.rb</string>
7
+ <key>documents</key>
8
+ <array>
9
+ <dict>
10
+ <key>expanded</key>
11
+ <true/>
12
+ <key>name</key>
13
+ <string>app</string>
14
+ <key>regexFolderFilter</key>
15
+ <string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
16
+ <key>selected</key>
17
+ <true/>
18
+ <key>sourceDirectory</key>
19
+ <string></string>
20
+ </dict>
21
+ </array>
22
+ <key>fileHierarchyDrawerWidth</key>
23
+ <integer>221</integer>
24
+ <key>metaData</key>
25
+ <dict>
26
+ <key>Gemfile</key>
27
+ <dict>
28
+ <key>caret</key>
29
+ <dict>
30
+ <key>column</key>
31
+ <integer>17</integer>
32
+ <key>line</key>
33
+ <integer>8</integer>
34
+ </dict>
35
+ <key>firstVisibleColumn</key>
36
+ <integer>0</integer>
37
+ <key>firstVisibleLine</key>
38
+ <integer>0</integer>
39
+ </dict>
40
+ <key>lib/app/app/config.rb</key>
41
+ <dict>
42
+ <key>caret</key>
43
+ <dict>
44
+ <key>column</key>
45
+ <integer>21</integer>
46
+ <key>line</key>
47
+ <integer>27</integer>
48
+ </dict>
49
+ <key>firstVisibleColumn</key>
50
+ <integer>0</integer>
51
+ <key>firstVisibleLine</key>
52
+ <integer>0</integer>
53
+ </dict>
54
+ <key>lib/app/app/root.rb</key>
55
+ <dict>
56
+ <key>caret</key>
57
+ <dict>
58
+ <key>column</key>
59
+ <integer>0</integer>
60
+ <key>line</key>
61
+ <integer>6</integer>
62
+ </dict>
63
+ <key>firstVisibleColumn</key>
64
+ <integer>0</integer>
65
+ <key>firstVisibleLine</key>
66
+ <integer>0</integer>
67
+ </dict>
68
+ <key>lib/extensions/zz_geocoder.rb</key>
69
+ <dict>
70
+ <key>caret</key>
71
+ <dict>
72
+ <key>column</key>
73
+ <integer>21</integer>
74
+ <key>line</key>
75
+ <integer>8</integer>
76
+ </dict>
77
+ <key>firstVisibleColumn</key>
78
+ <integer>0</integer>
79
+ <key>firstVisibleLine</key>
80
+ <integer>0</integer>
81
+ </dict>
82
+ </dict>
83
+ <key>openDocuments</key>
84
+ <array>
85
+ <string>Gemfile</string>
86
+ <string>lib/app/app/config.rb</string>
87
+ <string>lib/app/app/root.rb</string>
88
+ <string>lib/extensions/zz_geocoder.rb</string>
89
+ </array>
90
+ <key>showFileHierarchyDrawer</key>
91
+ <true/>
92
+ <key>windowFrame</key>
93
+ <string>{{10, 0}, {1128, 746}}</string>
94
+ </dict>
95
+ </plist>
data/config/app.yml ADDED
@@ -0,0 +1,2 @@
1
+ default:
2
+ cache: redis://localhost:6379/0
@@ -0,0 +1,55 @@
1
+ require_relative "config"
2
+
3
+ #
4
+ # This is a cache module, which keeps entries for a certain time period,
5
+ # stored away in a redis store.
6
+ #
7
+ # Entries are packed via Marshal.
8
+ module App
9
+ module Cache
10
+ DEFAULT_MAX_AGE = 4 * 3600 # 4 hours.
11
+
12
+ attr :store, true
13
+ extend self
14
+
15
+ def self.clear
16
+ store.flushdb
17
+ end
18
+
19
+ def self.cached(key, max_age = DEFAULT_MAX_AGE, &block)
20
+ redis = App::Cache.store
21
+ return yield if !store || !max_age
22
+
23
+ if marshalled = store.get(key)
24
+ Marshal.load(marshalled)
25
+ else
26
+ yield.tap { |v|
27
+ store.set(key, Marshal.dump(v))
28
+ store.expire(key, max_age)
29
+ }
30
+ end
31
+ end
32
+
33
+ def self.setup
34
+ if !(cache_url = App.config[:cache])
35
+ App.logger.warn "No :cache configuration"
36
+ elsif !(self.store = connect_to_redis(cache_url))
37
+ App.logger.warn "Using cache at #{cache_url}"
38
+ end
39
+ end
40
+
41
+ def self.connect_to_redis(url)
42
+ require "redis"
43
+ Redis.connect(:url => url)
44
+ rescue LoadError
45
+ App.logger.warn "Cannot load 'redis' gem (connecting to #{url})"
46
+ nil
47
+ end
48
+ end
49
+
50
+ def cached(key, max_age = Cache::DEFAULT_MAX_AGE, &block)
51
+ Cache.cached(key, max_age, &block)
52
+ end
53
+ end
54
+
55
+ App::Cache.setup
@@ -0,0 +1,56 @@
1
+ require_relative "root"
2
+ require_relative "logger"
3
+
4
+ require "yaml"
5
+
6
+ module App
7
+ module Config
8
+ def self.paths
9
+ [ "#{App.root}/config/app.yml", "#{App.root}/config.yml" ]
10
+ end
11
+
12
+ def self.read(path)
13
+ return unless File.exist?(path)
14
+ App.logger.info "Reading configuration from #{path}"
15
+ yaml = File.read(path)
16
+ YAML.load(yaml) || {}
17
+ end
18
+
19
+ def self.load
20
+ config = paths.inject(nil) do |c, path|
21
+ c || read(path)
22
+ end
23
+
24
+ config ||= begin
25
+ App.logger.warn "No configuration found in #{App.root}"
26
+ {}
27
+ end
28
+ end
29
+
30
+ @@configurations = {}
31
+
32
+ def self.current
33
+ @@configurations[App.root] ||= begin
34
+ config = self.load
35
+ default_settings = config["default"] || {}
36
+ current_settings = config[App.env] || {}
37
+ default_settings.update current_settings
38
+ end.extend(TreatSymbolsAsStrings)
39
+ end
40
+
41
+ module TreatSymbolsAsStrings
42
+ def [](key)
43
+ fetch(key) do
44
+ case key
45
+ when Symbol then fetch(key.to_s, nil)
46
+ when String then fetch(key.to_sym, nil)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def config
54
+ Config.current
55
+ end
56
+ end
@@ -0,0 +1,14 @@
1
+ require "logger"
2
+
3
+ module App
4
+ def self.logger
5
+ @logger
6
+ end
7
+
8
+ def self.logger=(logger)
9
+ logger.formatter = proc { |_, _, _, msg| "*** #{msg}\n" }
10
+ @logger = logger
11
+ end
12
+ end
13
+
14
+ App.logger = Logger.new(STDERR)
@@ -0,0 +1,36 @@
1
+
2
+ module App
3
+ # -- app root ---------------------------------------------------------------
4
+
5
+ module Root
6
+ def self.find_starting_in(dir)
7
+ if is_root?(dir)
8
+ dir
9
+ elsif !dir.sub!(/\/[^\/]+$/, "")
10
+ nil
11
+ else
12
+ find_starting_in(dir)
13
+ end
14
+ end
15
+
16
+ def self.is_root?(dir)
17
+ File.exists?("#{dir}/config.ru") ||
18
+ File.exists?("#{dir}/Gemfile") ||
19
+ File.exists?("#{dir}/Procfile")
20
+ end
21
+
22
+ def self.find
23
+ find_starting_in(Dir.getwd) || raise("Could not find application root for #{dir}")
24
+ end
25
+
26
+ def root=(root)
27
+ @root = root
28
+ end
29
+
30
+ def root
31
+ @root ||= Root.find.tap { |root| App.logger.warn "Application root is #{root}" }
32
+ end
33
+ end
34
+
35
+ extend Root
36
+ end
data/lib/app/app.rb ADDED
@@ -0,0 +1,13 @@
1
+ module App
2
+ extend self
3
+
4
+ attr :env, true
5
+
6
+ def env
7
+ @env ||= ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
8
+ end
9
+ end
10
+
11
+ Dir.glob("#{File.dirname(__FILE__)}/app/*.rb").sort.each do |file|
12
+ load file
13
+ end
data/lib/app.rb ADDED
@@ -0,0 +1,9 @@
1
+ require "micro_sql"
2
+
3
+ Dir.glob("#{File.dirname(__FILE__)}/core-extensions/*.rb").sort.each do |file|
4
+ load file
5
+ end
6
+
7
+ Dir.glob("#{File.dirname(__FILE__)}/app/*.rb").sort.each do |file|
8
+ load file
9
+ end
@@ -0,0 +1,24 @@
1
+ require "logger"
2
+
3
+ class Logger
4
+ class Benchmarker
5
+ attr :msg, true
6
+
7
+ def initialize(msg)
8
+ @msg, @start = msg, Time.now
9
+ end
10
+
11
+ def runtime
12
+ Time.now - @start
13
+ end
14
+ end
15
+
16
+ def benchmark(msg = "Benchmark", opts = {}, &block)
17
+ benchmarker = Benchmarker.new(msg)
18
+ r = yield(benchmarker)
19
+
20
+ runtime = benchmarker.runtime
21
+ warn "#{benchmarker.msg}: #{(runtime * 1000).to_i} msecs" if runtime > (opts[:minimum] || -1)
22
+ r
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ require "cgi"
2
+
3
+ class CGI
4
+ def self.url_for(url, params = nil)
5
+ return url unless params
6
+ params = params.map { |k,v| "#{k}=#{CGI.escape(v.to_s)}" }.join("&")
7
+ url.index("?") ? "#{url}&#{params}" : "#{url}?#{params}"
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ class Object
2
+ def define_attribute(sym, value)
3
+ (class << self; self; end).class_eval do
4
+ define_method(sym) { value }
5
+ end
6
+ value
7
+ end
8
+ end
@@ -0,0 +1,50 @@
1
+ require "htmlentities"
2
+
3
+ # -- decode HTML entities -----------------------------------------------------
4
+
5
+ class String
6
+ module HtmlDecoder
7
+ def self.instance
8
+ @htmldecoder ||= HTMLEntities.new
9
+ end
10
+ end
11
+
12
+ def unhtml
13
+ HtmlDecoder.instance.decode self
14
+ end
15
+ end
16
+
17
+ # -- convert to UTF8 ----------------------------------------------------------
18
+
19
+ require 'iconv'
20
+ class String
21
+ def to_utf8
22
+ # require "charguess"
23
+ # encoding = CharGuess.guess(self)
24
+ # puts "encoding: #{encoding.inspect}"
25
+ # return self if !encoding || encoding == "UTF-8"
26
+
27
+ encoding = 'ISO-8859-1'
28
+ Iconv.conv('utf-8', encoding, self)
29
+ end
30
+ end
31
+
32
+ # -- remove accents -----------------------------------------------------------
33
+
34
+ require_relative "./string_without_accents"
35
+
36
+ class String
37
+ include WithoutAccents
38
+ end
39
+
40
+ class String
41
+ def sortkey
42
+ # Convert the key into an sortable ascii string
43
+ self.without_accents. # remove accents
44
+ downcase.
45
+ gsub(/^\s*(der|die|das|the|a|ein)\b\s*/, ""). # remove leading stop words
46
+ gsub(/[0-9]+/) { |s| "%03d" % s.to_i }. # fill in leading zeroes
47
+ gsub(/[^a-z0-9]/, "") # keep only letters and digits
48
+ end
49
+ end
50
+
@@ -0,0 +1,92 @@
1
+ # RemoveAccents version 1.0.3 (c) 2008-2009 Solutions Informatiques Techniconseils inc.
2
+ #
3
+ # This module adds 2 methods to the string class.
4
+ # Up-to-date version and documentation available at:
5
+ #
6
+ # http://www.techniconseils.ca/en/scripts-remove-accents-ruby.php
7
+ #
8
+ # This script is available under the following license :
9
+ # Creative Commons Attribution-Share Alike 2.5.
10
+ #
11
+ # See full license and details at :
12
+ # http://creativecommons.org/licenses/by-sa/2.5/ca/
13
+ #
14
+ # Version history:
15
+ # * 1.0.3 : July 23 2009
16
+ # Corrected some incorrect character codes. Source is now wikipedia at:
17
+ # http://en.wikipedia.org/wiki/ISO/IEC_8859-1#Related_character_maps
18
+ # Thanks to Raimon Fernandez for pointing out the incorrect codes.
19
+ # * 1.0.2 : October 29 2008
20
+ # Slightly optimized version of urlize - Jonathan Grenier (jgrenier@techniconseils.ca)
21
+ # * 1.0.1 : October 29 2008
22
+ # First public revision - Jonathan Grenier (jgrenier@techniconseils.ca)
23
+ #
24
+
25
+ module WithoutAccents
26
+
27
+ # The extended characters map used by removeaccents. The accented characters
28
+ # are coded here using their numerical equivalent to sidestep encoding issues.
29
+ # These correspond to ISO-8859-1 encoding.
30
+ ACCENTS_MAPPING = {
31
+ 'E' => [200,201,202,203],
32
+ 'e' => [232,233,234,235],
33
+ 'A' => [192,193,194,195,196,197],
34
+ 'a' => [224,225,226,227,228,229,230],
35
+ 'C' => [199],
36
+ 'c' => [231],
37
+ 'O' => [210,211,212,213,214,216],
38
+ 'o' => [242,243,244,245,246,248],
39
+ 'I' => [204,205,206,207],
40
+ 'i' => [236,237,238,239],
41
+ 'U' => [217,218,219,220],
42
+ 'u' => [249,250,251,252],
43
+ 'N' => [209],
44
+ 'n' => [241],
45
+ 'Y' => [221],
46
+ 'y' => [253,255],
47
+ 'AE' => [306],
48
+ 'ae' => [346],
49
+ 'OE' => [188],
50
+ 'oe' => [189]
51
+ }
52
+
53
+ ACCENTS_MAPPING_REGEXPS = ACCENTS_MAPPING.map do |letter, accents|
54
+ packed = accents.pack('U*')
55
+ regexp = Regexp.new("[#{packed}]", nil) #, 'U')
56
+
57
+ [letter, regexp]
58
+ end
59
+
60
+ # Remove the accents from the string. Uses String::ACCENTS_MAPPING as the source map.
61
+ def without_accents
62
+ str = String.new(self)
63
+ ACCENTS_MAPPING_REGEXPS.each {|letter,regexp|
64
+ str.gsub!(regexp, letter)
65
+ }
66
+ str
67
+ end
68
+
69
+ =begin
70
+
71
+ # Convert a string to a format suitable for a URL without ever using escaped characters.
72
+ # It calls strip, removeaccents, downcase (optional) then removes the spaces (optional)
73
+ # and finally removes any characters matching the default regexp (/[^-_A-Za-z0-9]/).
74
+ #
75
+ # Options
76
+ #
77
+ # * :downcase => call downcase on the string (defaults to true)
78
+ # * :convert_spaces => Convert space to underscore (defaults to false)
79
+ # * :regexp => The regexp matching characters that will be converting to an empty string (defaults to /[^-_A-Za-z0-9]/)
80
+ def urlize(options = {})
81
+ options[:downcase] ||= true
82
+ options[:convert_spaces] ||= false
83
+ options[:regexp] ||= /[^-_A-Za-z0-9]/
84
+
85
+ str = self.strip.removeaccents
86
+ str.downcase! if options[:downcase]
87
+ str.gsub!(/\ /,'_') if options[:convert_spaces]
88
+ str.gsub(options[:regexp], '')
89
+ end
90
+ =end
91
+
92
+ end
@@ -0,0 +1,16 @@
1
+ class Module
2
+ def thread_local_attribute(name, &block)
3
+ proc = Proc.new if block_given?
4
+ key = "tls:#{name}"
5
+
6
+ singleton_class.class_eval do
7
+ define_method(name) do
8
+ Thread.current[key] ||= proc ? proc.call : nil
9
+ end
10
+
11
+ define_method("#{name}=") do |value|
12
+ Thread.current[key] = value
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,26 @@
1
+ require "digest/md5"
2
+ require "forwardable"
3
+
4
+ class String
5
+ def crc32
6
+ Zlib.crc32(self)
7
+ end
8
+
9
+ def md5
10
+ Digest::MD5.hexdigest(self)
11
+ end
12
+
13
+ # return a 64 bit uid
14
+ def uid64
15
+ md5.unpack("LL").inject { |a,b| (a << 31) + b }
16
+ end
17
+ end
18
+
19
+ class Hash
20
+ extend Forwardable
21
+ delegate [:uid64, :crc32, :md5] => :calculate_stable_hashable
22
+
23
+ def calculate_stable_hashable
24
+ map { |k,v| "#{k.inspect}:#{v.inspect}" }.sort.join("//")
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ require 'net/http'
2
+
3
+ # The Http module defines a
4
+ #
5
+ # Http.get(url)
6
+ #
7
+ # method.
8
+ module Http
9
+ extend self
10
+
11
+ # the default expiration time for get requests.
12
+ attr :max_age
13
+
14
+ def get(url, max_age = HTTP.max_age)
15
+ LOGGER.benchmark("[GET] #{url}", :minimum => 20) do
16
+ Cache.cached(url, max_age) do
17
+ uri = URI(url)
18
+ Net::HTTP.get(uri)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,36 @@
1
+ require "cgi"
2
+ require "json"
3
+ require "micro_sql"
4
+
5
+ # A basic, caching, geocoder
6
+ module Geocoder
7
+ extend self
8
+
9
+ TIME_TO_LIVE = 3600
10
+
11
+ def geocode(address)
12
+ Geocoder.cached(address) { __geocode__(address) }
13
+ end
14
+
15
+ private
16
+
17
+ def __geocode__(address)
18
+ url = "http://maps.google.com/maps/geo?q=#{CGI.escape(address)}&output=json&oe=utf-8"
19
+
20
+ json = Http.get(url)
21
+ data = JSON.parse(json)
22
+
23
+ status = data["Status"]
24
+ if status["code"] != 200
25
+ LOGGER.warn "Geocoding failed for '#{address}' with status #{status["code"]}"
26
+ return
27
+ end
28
+
29
+ data["Placemark"].first["Point"]["coordinates"]
30
+ end
31
+
32
+ def self.cached(key, &block)
33
+ @cache ||= MicroSql.create("#{ENV["HOME"]}/geocoder.sqdb").key_value_table("geocache")
34
+ @cache.cached(key, TIME_TO_LIVE, &block)
35
+ end
36
+ end
data/script/watchr ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rb-fsevent'
3
+
4
+ if ARGV.length < 2
5
+ STDERR.puts "watchr dir ruby-parameter(s)..."
6
+ abort
7
+ end
8
+
9
+ paths = ARGV.shift.split(",")
10
+ $args = ARGV.dup
11
+
12
+
13
+ def do_ruby
14
+ STDERR.puts $args.join(" ")
15
+ STDERR.puts "=" * 80
16
+
17
+ system(*$args)
18
+ end
19
+
20
+ puts "Initial run"
21
+ do_ruby
22
+
23
+ fsevent = FSEvent.new
24
+ fsevent.watch paths do |directories|
25
+ puts "Detected change inside: #{directories.inspect}"
26
+ do_ruby
27
+ end
28
+ fsevent.run
data/test/app_test.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'helper'
2
+
3
+ class TestApp < Test::Unit::TestCase
4
+ def test_root
5
+ expected = File.expand_path("#{File.dirname(__FILE__)}/..")
6
+
7
+ assert_equal expected, App::Root.find_starting_in(File.dirname(__FILE__))
8
+ assert_equal expected, App::Root.find
9
+ assert_equal expected, App.root
10
+
11
+ App.root = "foo"
12
+ assert_equal "foo", App.root
13
+
14
+ App.root = nil
15
+ assert_equal expected, App.root
16
+ end
17
+
18
+ def test_object_attributes
19
+ a = {}
20
+ assert_raise(NoMethodError) {
21
+ a.foo
22
+ }
23
+
24
+ a.define_attribute :foo, "bar"
25
+ assert_equal("bar", a.foo)
26
+
27
+ a.define_attribute :foo, "baz"
28
+ assert_equal("baz", a.foo)
29
+
30
+ a.define_attribute :foo, nil
31
+ assert_equal(nil, a.foo)
32
+ end
33
+
34
+ def test_benchmark_logger
35
+ r = []
36
+
37
+ logger = Logger.new(STDERR)
38
+ logger.formatter = proc { |_, _, _, msg| r << msg; nil }
39
+
40
+ foo = logger.benchmark {
41
+ "foo"
42
+ }
43
+ assert_equal("foo", foo)
44
+ assert_equal(["Benchmark: 0 msecs"], r)
45
+
46
+ r = []
47
+ foo = logger.benchmark("message") { "foo" }
48
+ assert_equal("foo", foo)
49
+ assert_equal(["message: 0 msecs"], r)
50
+
51
+ r = []
52
+ foo = logger.benchmark("message", :minimum => 1) { "foo" }
53
+ assert_equal("foo", foo)
54
+ assert_equal([], r)
55
+ end
56
+ end
@@ -0,0 +1,28 @@
1
+ require 'helper'
2
+
3
+ class CacheTest < Test::Unit::TestCase
4
+ def test_caching
5
+ unless App::Cache.store
6
+ App.logger.warn "No cache configed. Skipping cache tests"
7
+ return
8
+ end
9
+
10
+ App::Cache.clear
11
+
12
+ done = 0
13
+ r = App.cached("six") do
14
+ done += 1
15
+ 2 * 3
16
+ end
17
+
18
+ assert_equal(6, r)
19
+
20
+ r = App.cached("six") do
21
+ done += 1
22
+ 2 * 3
23
+ end
24
+
25
+ assert_equal(1, done)
26
+ assert_equal(6, r)
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ class CgiExtTest < Test::Unit::TestCase
6
+ def test_url_for
7
+ assert_equal "/abc", CGI.url_for("/abc")
8
+ assert_equal "/abc?p=12", CGI.url_for("/abc", :p => 12)
9
+ assert_equal "/abc?a=1&b=1&p=12", CGI.url_for("/abc?a=1&b=1", :p => 12)
10
+ assert_equal "/abc?p=1&p=12", CGI.url_for("/abc?p=1", :p => 12)
11
+ end
12
+
13
+ def test_url_for_escaping
14
+ assert_equal "/abc?p=foo+bar", CGI.url_for("/abc", :p => "foo bar")
15
+ assert_equal "/abc?p=foo+%3E+bar", CGI.url_for("/abc", :p => "foo > bar")
16
+ assert_equal "/abc?p=foo+%26+bar", CGI.url_for("/abc", :p => "foo & bar")
17
+ assert_equal "/abc?p=foo+%C3%A4+bar", CGI.url_for("/abc", :p => "foo ä bar")
18
+ end
19
+ end
data/test/config.yml ADDED
@@ -0,0 +1,7 @@
1
+ default:
2
+ abc: "abc"
3
+ dummy: "dummy"
4
+
5
+ test:
6
+ abc: "def"
7
+
@@ -0,0 +1,13 @@
1
+ require 'helper'
2
+
3
+ class TestConfig < Test::Unit::TestCase
4
+ def test_read_from_test_config
5
+ App.root = File.dirname __FILE__
6
+
7
+ expected = {"abc"=>"def", "dummy"=>"dummy"}
8
+ assert_equal(expected, App.config)
9
+
10
+ assert_equal("def", App.config[:abc])
11
+ assert_equal("def", App.config["abc"])
12
+ end
13
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+
11
+ require 'ruby-debug'
12
+ require 'simplecov'
13
+ require 'test/unit'
14
+ SimpleCov.start do
15
+ add_filter "test/helper.rb"
16
+ end
17
+
18
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
19
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
20
+
21
+ require 'app'
22
+ App.env = "test"
23
+
24
+ App.logger.level = Logger::ERROR
25
+ MicroSql.logger = App.logger
26
+
27
+ class Test::Unit::TestCase
28
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ class StringExtTest < Test::Unit::TestCase
6
+ def test_html_decode
7
+ assert_equal("a", "a".unhtml)
8
+ assert_equal("ä", "&auml;".unhtml)
9
+ end
10
+
11
+ def test_sortkey
12
+ assert_equal("actual", "actual".sortkey)
13
+ assert_equal("schreck003012", "der schreck 3/12".sortkey)
14
+ end
15
+ end
data/test/tls_test.rb ADDED
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ class TlsTest < Test::Unit::TestCase
6
+ thread_local_attribute :tester
7
+ thread_local_attribute :dynamic do "dynamic" end
8
+ thread_local_attribute :dynamic2 do "dynamic2" end
9
+
10
+ def test_get_and_set
11
+ assert_equal(nil, TlsTest.tester)
12
+ TlsTest.tester = 1
13
+ assert_equal(1, TlsTest.tester)
14
+
15
+ assert_equal("dynamic", TlsTest.dynamic)
16
+ end
17
+
18
+ def test_thread_locality
19
+ Thread.new {
20
+ assert_equal(nil, TlsTest.tester)
21
+ TlsTest.tester = 1
22
+ assert_equal(1, TlsTest.tester)
23
+
24
+ assert_equal("dynamic", TlsTest.dynamic)
25
+ }.join
26
+
27
+ Thread.new {
28
+ assert_equal(nil, TlsTest.tester)
29
+ TlsTest.tester = 1
30
+ assert_equal(1, TlsTest.tester)
31
+
32
+ assert_equal("dynamic", TlsTest.dynamic)
33
+ }.join
34
+ end
35
+ end
data/test/uid_test.rb ADDED
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ class UidTest < Test::Unit::TestCase
6
+ def test_string_uids
7
+ assert_equal(578656804, "actual".crc32)
8
+ assert_equal("5157e3c765af93679ea07052f30f0a6e", "actual".md5)
9
+ assert_equal(1989069975706612581, "actual".uid64)
10
+ end
11
+
12
+ def test_hash_uids
13
+ assert_equal(2929690870, {1=>1}.crc32)
14
+ assert_equal("d0bd571dc19c083d82f023c9666c5574", {1=>1}.md5)
15
+ assert_equal(3616698580463597365, {1=>1}.uid64)
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: radiospiel-app
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - radiospiel
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-03 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pg
16
+ requirement: &70231006859040 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70231006859040
25
+ - !ruby/object:Gem::Dependency
26
+ name: sqlite3
27
+ requirement: &70231006858260 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70231006858260
36
+ - !ruby/object:Gem::Dependency
37
+ name: redis
38
+ requirement: &70231006857520 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70231006857520
47
+ - !ruby/object:Gem::Dependency
48
+ name: micro_sql
49
+ requirement: &70231006854220 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70231006854220
58
+ - !ruby/object:Gem::Dependency
59
+ name: htmlentities
60
+ requirement: &70231006853600 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70231006853600
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: &70231006852760 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70231006852760
80
+ - !ruby/object:Gem::Dependency
81
+ name: jeweler
82
+ requirement: &70231006851660 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70231006851660
91
+ - !ruby/object:Gem::Dependency
92
+ name: simplecov
93
+ requirement: &70231006830480 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70231006830480
102
+ - !ruby/object:Gem::Dependency
103
+ name: ruby-debug19
104
+ requirement: &70231006829160 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: *70231006829160
113
+ description: Some basics that your application could benefit from.
114
+ email: eno@open-lab.org
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files:
118
+ - LICENSE.txt
119
+ - README.rdoc
120
+ files:
121
+ - .document
122
+ - Gemfile
123
+ - Gemfile.lock
124
+ - LICENSE.txt
125
+ - README.rdoc
126
+ - Rakefile
127
+ - VERSION
128
+ - app.gemspec
129
+ - app.tmproj
130
+ - config/app.yml
131
+ - lib/app.rb
132
+ - lib/app/app.rb
133
+ - lib/app/app/cache.rb
134
+ - lib/app/app/config.rb
135
+ - lib/app/app/logger.rb
136
+ - lib/app/app/root.rb
137
+ - lib/core-extensions/benchmark-logger.rb
138
+ - lib/core-extensions/cgi_ext.rb
139
+ - lib/core-extensions/object_ext.rb
140
+ - lib/core-extensions/string_ext.rb
141
+ - lib/core-extensions/string_without_accents.rb
142
+ - lib/core-extensions/tls.rb
143
+ - lib/core-extensions/uids.rb
144
+ - lib/extensions/http.rb
145
+ - lib/extensions/zz_geocoder.rb
146
+ - script/watchr
147
+ - test/app_test.rb
148
+ - test/cache_test.rb
149
+ - test/cgi_ext_test.rb
150
+ - test/config.yml
151
+ - test/config_test.rb
152
+ - test/helper.rb
153
+ - test/string_ext_test.rb
154
+ - test/tls_test.rb
155
+ - test/uid_test.rb
156
+ homepage: http://github.com/radiospiel/app
157
+ licenses:
158
+ - MIT
159
+ post_install_message:
160
+ rdoc_options: []
161
+ require_paths:
162
+ - lib
163
+ required_ruby_version: !ruby/object:Gem::Requirement
164
+ none: false
165
+ requirements:
166
+ - - ! '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ segments:
170
+ - 0
171
+ hash: -159245804892419013
172
+ required_rubygems_version: !ruby/object:Gem::Requirement
173
+ none: false
174
+ requirements:
175
+ - - ! '>='
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ requirements: []
179
+ rubyforge_project:
180
+ rubygems_version: 1.8.17
181
+ signing_key:
182
+ specification_version: 3
183
+ summary: Application base code
184
+ test_files: []