tetrahedron 0.0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f11bb282f14b3b5c27899cdb70fef27f4154dc20
4
+ data.tar.gz: a04eafc6d60df291569009131ee564c5fc404b44
5
+ SHA512:
6
+ metadata.gz: acb35b1fe3d7a07905a753ff2d8422db1478a097f22d18840230085cf14b8c108e0257a5c71ebc10e5969c7bd8eb3ef565638ed343f883ae8512b4195c47dce6
7
+ data.tar.gz: 1c7365409ba0e9bf0d686a849df7d4a445730a23685af903c50bb2193e702960224be195dc8cc0e0265a5d0f33fd39ed3057443cb7f7f834456ef9b97794a2ab
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ # Sublime Text 2/3
2
+ *.sublime-workspace
3
+
4
+ # RubyGems
5
+ *.gem
6
+ pkg/
data/AUTHORS ADDED
File without changes
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ ruby '2.2.3'
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,65 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tetrahedron (0.0.0.1)
5
+ activesupport
6
+ sequel
7
+ sinatra
8
+ sinatra-contrib
9
+ thor
10
+
11
+ GEM
12
+ remote: https://rubygems.org/
13
+ specs:
14
+ activesupport (4.2.5)
15
+ i18n (~> 0.7)
16
+ json (~> 1.7, >= 1.7.7)
17
+ minitest (~> 5.1)
18
+ thread_safe (~> 0.3, >= 0.3.4)
19
+ tzinfo (~> 1.1)
20
+ backports (3.6.7)
21
+ coderay (1.1.0)
22
+ i18n (0.7.0)
23
+ json (1.8.3)
24
+ method_source (0.8.2)
25
+ minitest (5.8.3)
26
+ multi_json (1.11.2)
27
+ pry (0.10.3)
28
+ coderay (~> 1.1.0)
29
+ method_source (~> 0.8.1)
30
+ slop (~> 3.4)
31
+ rack (1.6.4)
32
+ rack-protection (1.5.3)
33
+ rack
34
+ rack-test (0.6.3)
35
+ rack (>= 1.0)
36
+ rake (10.4.2)
37
+ sequel (4.28.0)
38
+ sinatra (1.4.6)
39
+ rack (~> 1.4)
40
+ rack-protection (~> 1.4)
41
+ tilt (>= 1.3, < 3)
42
+ sinatra-contrib (1.4.6)
43
+ backports (>= 2.0)
44
+ multi_json
45
+ rack-protection
46
+ rack-test
47
+ sinatra (~> 1.4.0)
48
+ tilt (>= 1.3, < 3)
49
+ slop (3.6.0)
50
+ thor (0.19.1)
51
+ thread_safe (0.3.5)
52
+ tilt (2.0.1)
53
+ tzinfo (1.2.2)
54
+ thread_safe (~> 0.1)
55
+
56
+ PLATFORMS
57
+ ruby
58
+
59
+ DEPENDENCIES
60
+ pry
61
+ rake
62
+ tetrahedron!
63
+
64
+ BUNDLED WITH
65
+ 1.10.6
data/LICENSE ADDED
File without changes
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ Tetrahedron
2
+ ===========
3
+
4
+ [Welcome to the Tet.](https://www.youtube.com/watch?v=lt-udg9zQSE)
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/bin/tetrahedron ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # TODO(mtwilliams): Command line tool.
4
+ exit 1
data/config/app.ru ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env rackup
2
+
3
+ require_relative 'application'
4
+ require_relative 'environment'
5
+
6
+ # TODO(mtwilliams): Request tracking (make Heroku compatiable).
7
+ # TODO(mtwilliams): Performance monitoring (make Heroku compatiable).
8
+ # TODO(mtwilliams): Error handling.
9
+
10
+ if Tetrahedron::Sessions.configured?
11
+ use Rack::Session::Cookie, :key => Tetrahedron::Sessions.config.cookie,
12
+ :domain => Tetrahedron::Sessions.config.domain,
13
+ :expire_after => Tetrahedron::Sessions.config.lifetime,
14
+ :secret => Tetrahedron::Sessions.config.secret
15
+ else
16
+ # TODO(mtwilliams): Use a logger.
17
+ $stderr.puts "Sessions not configured!\n => Use Tetrahedron::Sessions.configure in config/environment.rb!"
18
+ end
19
+
20
+ # TODO(mtwilliams): Remove cylcical dependency so we can use a constantized version.
21
+ run Tetrahedron.config.app.constantize
@@ -0,0 +1,8 @@
1
+ # TODO(mtwilliams): Better multitenancy.
2
+
3
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ require 'tetrahedron'
5
+
6
+ require File.join(Tetrahedron.config.root, "config", "application")
7
+
8
+ Tetrahedron::Configuration.load
@@ -0,0 +1,18 @@
1
+ require_relative 'application'
2
+
3
+ Tetrahedron::Environment.load
4
+
5
+ if Tetrahedron.env.development?
6
+ # Synchronize STDOUT and STDERR to make debugging easier.
7
+ STDOUT.sync = STDERR.sync = true
8
+ end
9
+
10
+ require File.join(Tetrahedron.config.root, "config", "environment")
11
+
12
+ unless Tetrahedron::Database.configured?
13
+ $stderr.puts "Database not configured!\n => Use Tetrahedron::Database.configure in config/environment.rb!"
14
+ end
15
+
16
+ # unless Tetrahedron::Redis.configured?
17
+ # $stderr.puts "Redis not configured!\n => Use Tetrahedron::Redis.configure in config/environment.rb!"
18
+ # end
data/config/puma.rb ADDED
@@ -0,0 +1,29 @@
1
+ require_relative 'application'
2
+ require_relative 'environment'
3
+
4
+ rackup File.join(Tetrahedron.root, 'config', 'app.ru')
5
+
6
+ environment Tetrahedron.env.to_s
7
+ bind "tcp://#{ENV['HOST'] || '0.0.0.0'}:#{ENV['PORT'] || 80}"
8
+ port (ENV['PORT'] || 80).to_i
9
+ workers (ENV['PUMA_WORKERS'] || 1).to_i
10
+ threads (ENV['PUMA_MIN_THREADS'] || 1).to_i,
11
+ (ENV['PUMA_MAX_THREADS'] || 1).to_i
12
+
13
+ preload_app!
14
+
15
+ before_fork do
16
+ if Tetrahedron.env.production?
17
+ # TODO(mtwilliams): Precompile assets.
18
+ Tetrahedron::Assets.precompile
19
+ end
20
+ end
21
+
22
+ on_worker_boot do
23
+ Tetrahedron.bootfile.up.call() if Tetrahedron.bootfile.up
24
+ end
25
+
26
+ # TODO(mtwilliams): Report low-level errors in production.
27
+ # lowlevel_error_handler do |e|
28
+ # ...
29
+ # end
@@ -0,0 +1,59 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ Bundler.require(:default)
5
+
6
+ # Some things aren't nicely cut gems, unforunately.
7
+ require 'base64'
8
+ require 'erb'
9
+ require 'net/http'
10
+ require 'ostruct'
11
+ require 'securerandom'
12
+ require 'socket'
13
+ require 'time'
14
+ require 'uri'
15
+ require 'yaml'
16
+
17
+ # Smells like Rails...
18
+ require 'active_support'
19
+ require 'active_support/core_ext'
20
+
21
+ module Tetrahedron
22
+ def self.root
23
+ @root ||= File.expand_path(File.join(File.dirname(__FILE__), '..'))
24
+ end
25
+ end
26
+
27
+ require 'tetrahedron/gem'
28
+ require 'tetrahedron/bundler'
29
+
30
+ require 'tetrahedron/error'
31
+ require 'tetrahedron/errors'
32
+
33
+ require 'tetrahedron/configuration'
34
+ require 'tetrahedron/environment'
35
+ require 'tetrahedron/bootfile'
36
+
37
+ Tetrahedron::Bundler.require
38
+
39
+ require 'sinatra/base'
40
+ require 'sinatra/contrib'
41
+
42
+ require 'sequel'
43
+
44
+ Sequel.extension :migration
45
+
46
+ Sequel::Model.plugin :timestamps
47
+ Sequel::Model.plugin :subclasses
48
+
49
+ require 'tetrahedron/base'
50
+
51
+ require 'tetrahedron/assets'
52
+
53
+ require 'tetrahedron/database'
54
+ require 'tetrahedron/sessions'
55
+
56
+ require 'tetrahedron/app'
57
+ require 'tetrahedron/model'
58
+ require 'tetrahedron/controller'
59
+ require 'tetrahedron/endpoint'
@@ -0,0 +1,16 @@
1
+ module Tetrahedron
2
+ class App < Tetrahedron::Base
3
+ configure do
4
+ environment = Tetrahedron::Assets::Environment.new
5
+ set :assets, environment: environment
6
+ sprockets_based_server = Tetrahedron::Assets::Server.new(settings.assets[:environment])
7
+ set :assets, server: sprockets_based_server
8
+ end
9
+
10
+ get %r{^/assets/*} do
11
+ # Assets are handled by Sprockets.
12
+ env['PATH_INFO'].sub('/assets', '')
13
+ settings.assets[:server].call!(env)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,43 @@
1
+ module Tetrahedron
2
+ module Assets
3
+ class Environment < Sprockets::Environment
4
+ def initialize
5
+ super(Tetrahedron.config.root)
6
+
7
+ self.append_path('vendor/assets/styles')
8
+ self.append_path('vendor/assets/scripts')
9
+ self.append_path('vendor/assets/fonts')
10
+ self.append_path('vendor/assets/images')
11
+
12
+ self.append_path('assets/styles')
13
+ self.append_path('assets/scripts')
14
+ self.append_path('assets/fonts')
15
+ self.append_path('assets/images')
16
+
17
+ if Tetrahedron.env.production?
18
+ self.css_compressor = CSSminify.new
19
+ self.js_compressor = Uglifier.new
20
+ end
21
+ end
22
+ end
23
+
24
+ class Server
25
+ def initialize(environment)
26
+ @environment = environment
27
+ end
28
+
29
+ def call(env)
30
+ @environment.call(env)
31
+ end
32
+ end
33
+
34
+ class Precompiler
35
+ # Precompile.
36
+ end
37
+
38
+ def self.precompile
39
+ # TODO(mtwilliams): Implement asset precompilation.
40
+ $stderr.puts "Asset precompilation is not implemented yet!"
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,34 @@
1
+ module Tetrahedron
2
+ class Base < Sinatra::Base
3
+ set :environment, Tetrahedron.env.to_sym
4
+ set :root, Tetrahedron.config.root
5
+
6
+ # Don't use the built-in web-server.
7
+ set :run, false
8
+
9
+ # Errors are bubbled so they can be handled by middleware.
10
+ set :dump_errors, false
11
+ set :raise_errors, true
12
+ set :show_exceptions, false
13
+
14
+ # Fuck you, IE9.
15
+ disable :method_override
16
+
17
+ configure :development do
18
+ # King of iteration, baby.
19
+ register Sinatra::Reloader
20
+ end
21
+
22
+ configure do
23
+ disable :static
24
+ end
25
+
26
+ get '/*' do
27
+ # Try to serve statically first.
28
+ server = Rack::Static.new(proc {[404, {}, []]}, root: File.join(Tetrahedron.config.root, '/public'))
29
+ status, headers, response = server.call(env)
30
+ pass if status == 404
31
+ [status, headers, response]
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,43 @@
1
+ module Tetrahedron
2
+ class Bootfile
3
+ DEFAULT = "config/boot.rb"
4
+
5
+ attr_reader :up
6
+ attr_reader :down
7
+
8
+ def initialize()
9
+ # TODO(mtwilliams): Provide reasonable defaults.
10
+ end
11
+
12
+ def self.load(filename=Tetrahedron::Bootfile::DEFAULT)
13
+ bootfile = Tetrahedron::Bootfile.new
14
+ require File.join(Tetrahedron.root, "config", "application")
15
+ DomainSpecificLanguage.for(bootfile).instance_eval(File.read(filename), filename)
16
+ bootfile
17
+ end
18
+
19
+ class DomainSpecificLanguage
20
+ def initialize(bootfile)
21
+ @bootfile = bootfile
22
+ end
23
+
24
+ def up(&block)
25
+ @bootfile.instance_variable_set(:@up, block)
26
+ end
27
+
28
+ def down(&block)
29
+ @bootfile.instance_variable_set(:@down, block)
30
+ end
31
+
32
+ def self.for(bootfile)
33
+ DomainSpecificLanguage.new(bootfile)
34
+ end
35
+ end
36
+ end
37
+
38
+ def self.bootfile(path=Tetrahedron::Bootfile::DEFAULT)
39
+ @bootfile ||= begin
40
+ Bootfile.load(path)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ module Tetrahedron
5
+ module Bundler
6
+ def self.require
7
+ ::Bundler.require(:default, :assets, :db, :redis, Tetrahedron.env.to_sym)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ module Tetrahedron
2
+ class Configuration
3
+ DEFAULT = "config/tetrahedron.rb"
4
+
5
+ attr_reader :app
6
+ attr_reader :root
7
+
8
+ def initialize()
9
+ # TODO(mtwilliams): Best guess @app and @root.
10
+ end
11
+
12
+ def self.load(filename=Tetrahedron::Configuration::DEFAULT)
13
+ configuration = Tetrahedron::Configuration.new
14
+ DomainSpecificLanguage.for(configuration).instance_eval(File.read(filename), filename)
15
+ configuration
16
+ end
17
+
18
+ class DomainSpecificLanguage
19
+ def initialize(configuration)
20
+ @configuration = configuration
21
+ end
22
+
23
+ def app(name)
24
+ @configuration.instance_variable_set(:@app, name)
25
+ end
26
+
27
+ def root(directory)
28
+ raise Tetrahedron::MisconfiguredError.new(:root, 'the path given does not exist') unless File.exist?(directory)
29
+ raise Tetrahedron::MisconfiguredError.new(:root, 'the path given is not a directory') unless File.directory?(directory)
30
+ @configuration.instance_variable_set(:@root, directory)
31
+ end
32
+
33
+ def self.for(configuration)
34
+ DomainSpecificLanguage.new(configuration)
35
+ end
36
+ end
37
+ end
38
+
39
+ def self.config(path=Tetrahedron::Configuration::DEFAULT)
40
+ @configuration ||= begin
41
+ Configuration.load(path)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,17 @@
1
+ module Tetrahedron
2
+ class Controller < Tetrahedron::Base
3
+ set :views, File.join(Tetrahedron.config.root, 'app', Tetrahedron.config.app.underscore, 'views')
4
+
5
+ # Use app/<app>/views/_layouts/default as the default layout.
6
+ set :erb, :layout => :'_layouts/default'
7
+
8
+ # Recognize *.html.erb as Erubis templates.
9
+ Tilt.register Tilt::ErubisTemplate, 'html.erb'
10
+
11
+ # Don't recognize *.erb templates.
12
+ def erb(template, options={}, locals={})
13
+ options[:layout] = settings.erb[:layout] if options[:layout].nil?
14
+ render 'html.erb', template, options, locals
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,113 @@
1
+ module Tetrahedron
2
+ module Database
3
+ class Configuration
4
+ Options = %i{adapter user password host port database pool}
5
+ attr_reader *Options
6
+
7
+ def initialize(configuration={})
8
+ Options.each do |opt|
9
+ self.instance_variable_set(:"@#{opt}", configuration[opt])
10
+ end
11
+ end
12
+
13
+ def override(overrides={})
14
+ configuration = self.dup
15
+ Options.each do |opt|
16
+ configuration.instance_variable_set(:"@#{opt}", overrides[opt]) if overrides.include? opt
17
+ end
18
+ configuration
19
+ end
20
+ end
21
+
22
+ def self.configured?
23
+ !@configuration.nil?
24
+ end
25
+
26
+ def self.configure(configuration)
27
+ # TODO(mtwilliams): Validate |configuration|.
28
+ configuration[:database] ||= Terahedron.config.app.to_s.underscore.gsub(/::/,'_')
29
+ configuration[:pool] ||= 1
30
+ @configuration = Configuration.new(configuration)
31
+ end
32
+
33
+ # TODO(mtwilliams): Refactor into Terahedron::Service.wait_until_reachable
34
+ def self.wait_until_reachable(overrides={})
35
+ # By default, we wait up to 15 seconds.
36
+ overrides[:timeout] ||= 15
37
+
38
+ configuration = @configuration.override(overrides) if configured?
39
+ configuration ||= Configuration.new(overrides)
40
+
41
+ # TODO(mtwilliams): Don't assume TCP.
42
+ # Look at |configuration.adapter|.
43
+ Timeout::timeout(overrides[:timeout]) do
44
+ while true
45
+ begin
46
+ TCPSocket.new(configuration.host, configuration.port).close
47
+ return true
48
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError
49
+ # We're all good citizens, right?
50
+ Kernel.sleep(1)
51
+ end
52
+ end
53
+ end
54
+ rescue Timeout::Error
55
+ false
56
+ end
57
+
58
+ def self.wait_until_reachable!(overrides={})
59
+ # TODO(mtwilliams): Raise a custom exception type.
60
+ raise "Database is unreachable!" unless wait_until_reachable
61
+ end
62
+
63
+ def self.connect(overrides={})
64
+ # Wait some amount of time before assuming the database is down.
65
+ Tetrahedron::Database.wait_until_reachable!(overrides)
66
+
67
+ configuration = @configuration.override(overrides) if configured?
68
+ configuration ||= Configuration.new(overrides)
69
+
70
+ @connection = Sequel.connect(:adapter => configuration.adapter,
71
+ :user => configuration.user,
72
+ :password => configuration.password,
73
+ :host => configuration.host,
74
+ :port => configuration.port,
75
+ :database => configuration.database,
76
+ :test => true,
77
+ :sslmode => :prefer,
78
+ :max_connections => configuration.pool)
79
+
80
+ # Reback our models with the new connection pool.
81
+ Tetrahedron::Model.db = @connection
82
+
83
+ true
84
+ end
85
+
86
+ def self.disconnect
87
+ connection = @connection
88
+
89
+ # TODO(mtwilliams): Ensure this is thread safe.
90
+ # Make sure no one tries to use the disconnected connection pool.
91
+ Tetrahedron::Model.db = Sequel.mock
92
+ @connection = nil
93
+
94
+ connection.disconnect unless connection.nil?
95
+ end
96
+
97
+ def self.connection
98
+ @connection
99
+ end
100
+
101
+ def self.reset
102
+ # TODO(mtwilliams): Drop and recreate database.
103
+ end
104
+
105
+ def self.migrate
106
+ Sequel::IntegerMigrator.run(connection, File.join(Tetrahedron.config.root, 'db', 'migrations'))
107
+ end
108
+
109
+ def self.seed
110
+ Kernel.load(File.join(Tetrahedron.config.root, 'db', 'seed.rb'))
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,4 @@
1
+ module Tetrahedron
2
+ class Endpoint < Tetrahedron::Base
3
+ end
4
+ end
@@ -0,0 +1,28 @@
1
+ module Tetrahedron
2
+ module Environment
3
+ # Loads `ENV` from `.env` if available.
4
+ def self.load
5
+ # TODO(mtwilliams): Use a proper logger.
6
+ $stdout.puts "Loading environment from `.env` if available..."
7
+ require 'dotenv'
8
+ Dotenv.load! File.join(Tetrahedron.config.root, '.env')
9
+ $stdout.puts " => Loaded from `.env`."
10
+ rescue LoadError => _
11
+ $stderr.puts " => The 'dotenv' Gem is not available on this system."
12
+ false
13
+ rescue Errno::ENOENT
14
+ $stderr.puts " => No `.env' file."
15
+ false
16
+ end
17
+ end
18
+
19
+ def self.env
20
+ env = ENV["#{Tetrahedron.config.app.upcase.gsub(/::/,'_')}_ENV"] || ENV['TETRAHEDRON_ENV'] || ENV['RACK_ENV']
21
+ @env ||= ::ActiveSupport::StringInquirer.new(env)
22
+ end
23
+
24
+ def self.env=(new_environment)
25
+ ENV["#{Tetrahedron.config.app.upcase.gsub(/::/,'_')}_ENV"] = ENV['TETRAHEDRON_ENV'] = new_environment
26
+ @env = ::ActiveSupport::StringInquirer.new(new_environment)
27
+ end
28
+ end
@@ -0,0 +1,4 @@
1
+ module Tetrahedron
2
+ class Error < StandardError
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module Tetrahedron
2
+ class MisconfiguredError < Error
3
+ def initialize(setting, reason)
4
+ super("The setting `#{setting}` is misconfigured: #{reason}!")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,58 @@
1
+ require 'ostruct'
2
+
3
+ module Tetrahedron
4
+ module Gem
5
+ # The name of this Gem.
6
+ def self.name
7
+ "tetrahedron"
8
+ end
9
+
10
+ # The name and email address of the primary author.
11
+ def self.author
12
+ self.authors.first
13
+ end
14
+
15
+ # The name and email addresses of all authors.
16
+ def self.authors
17
+ [["Michael Williams", "m.t.williams@live.com"]].map do |author|
18
+ name, email = author
19
+ OpenStruct.new(name: name, email: email)
20
+ end
21
+ end
22
+
23
+ # This Gem's homepage URL.
24
+ def self.homepage
25
+ "http://github.com/mtwilliams/tetrahedron"
26
+ end
27
+
28
+ # This Gem's URL.
29
+ def self.url
30
+ "https://rubygems.org/gems/#{self.name}"
31
+ end
32
+
33
+ # A short summary of this Gem.
34
+ def self.summary
35
+ "Opinionated Sinatra."
36
+ end
37
+
38
+ # A full description of this Gem.
39
+ def self.description
40
+ "Tetrahedron is an opinionated web development framework."
41
+ end
42
+
43
+ module VERSION #:nodoc:
44
+ MAJOR, MINOR, PATCH, PRE = [0, 0, 0, 1]
45
+ STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
46
+ end
47
+
48
+ # The semantic version of the this Gem.
49
+ def self.version
50
+ Gem::VERSION::STRING
51
+ end
52
+
53
+ # The license covering Tetrahedron.
54
+ def self.license
55
+ "Public Domain"
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,32 @@
1
+ module Tetrahedron
2
+ Model = Class.new(Sequel::Model)
3
+
4
+ # Stop Sequel from bitching if it's subclassed before the first database
5
+ # connection is established.
6
+ Model.db = Sequel.mock if Sequel::DATABASES.empty?
7
+
8
+ class Model
9
+ def self::db=(db)
10
+ super(db)
11
+
12
+ # All the way down, boys.
13
+ self.descendents.each do |subclass|
14
+ subclass.db = db
15
+ end
16
+ end
17
+ end
18
+
19
+ def self::Model(source)
20
+ unless Sequel::Model::ANONYMOUS_MODEL_CLASSES.key?(source)
21
+ anonymous_model_class = nil
22
+ if source.is_a?(Sequel::Database)
23
+ anonymous_model_class = Class.new(Tetrahedron::Model)
24
+ anonymous_model_class.db = source
25
+ else
26
+ anonymous_model_class = Class.new(Tetrahedron::Model).set_dataset(source)
27
+ end
28
+ Sequel::Model::ANONYMOUS_MODEL_CLASSES[source] = anonymous_model_class
29
+ end
30
+ return Sequel::Model::ANONYMOUS_MODEL_CLASSES[source]
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ module Tetrahedron
2
+ module Rake
3
+ def self.install
4
+ root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
5
+ require_relative 'configuration'
6
+ Tetrahedron::Configuration.load
7
+ require_relative 'environment'
8
+ Tetrahedron::Environment.load
9
+ require File.join(root, 'config', 'application')
10
+ require File.join(root, 'config', 'environment')
11
+ Dir.glob(File.join(root, 'lib', 'tetrahedron', 'tasks', '**.rake')).each do |path|
12
+ Kernel.load(path)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module Tetrahedron
2
+ module Redis
3
+ end
4
+ end
@@ -0,0 +1,28 @@
1
+ module Tetrahedron
2
+ module Sessions
3
+ class Configuration
4
+ Options = %i{cookie domain lifetime secret}
5
+ attr_reader *Options
6
+
7
+ def initialize(configuration={})
8
+ Options.each do |opt|
9
+ self.instance_variable_set(:"@#{opt}", configuration[opt])
10
+ end
11
+ end
12
+ end
13
+
14
+ def self.config
15
+ @configuration
16
+ end
17
+
18
+ def self.configured?
19
+ !@configuration.nil?
20
+ end
21
+
22
+ def self.configure(configuration)
23
+ # TODO(mtwilliams): Validate |configuration|.
24
+ configuration[:cookie] ||= "#{Tetrahedron.config.app.to_s.downcase.gsub(/::/,'.')}.session"
25
+ @configuration = Sessions::Configuration.new(configuration)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ namespace :tet do
2
+ task :up do
3
+ exec "puma -C #{File.join(Tetrahedron.root, 'config', 'puma.rb')}"
4
+ end
5
+ end
@@ -0,0 +1,34 @@
1
+ $:.push File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
2
+ require 'tetrahedron/gem'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = Tetrahedron::Gem.name
6
+ s.version = Tetrahedron::Gem.version
7
+ s.platform = Gem::Platform::RUBY
8
+ s.author = Tetrahedron::Gem.author.name
9
+ s.email = Tetrahedron::Gem.author.email
10
+ s.homepage = Tetrahedron::Gem.homepage
11
+ s.summary = Tetrahedron::Gem.summary
12
+ s.description = Tetrahedron::Gem.description
13
+ s.license = Tetrahedron::Gem.license
14
+
15
+ s.required_ruby_version = '>= 2.2.3'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+
21
+ s.require_paths = %w(lib)
22
+
23
+ s.add_development_dependency("rake")
24
+ s.add_development_dependency("pry")
25
+
26
+ s.add_dependency("activesupport")
27
+
28
+ s.add_dependency("sinatra")
29
+ s.add_dependency("sinatra-contrib")
30
+
31
+ s.add_dependency("sequel")
32
+
33
+ s.add_dependency("thor")
34
+ end
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tetrahedron
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sinatra
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sinatra-contrib
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sequel
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: thor
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Tetrahedron is an opinionated web development framework.
112
+ email: m.t.williams@live.com
113
+ executables:
114
+ - tetrahedron
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - AUTHORS
120
+ - Gemfile
121
+ - Gemfile.lock
122
+ - LICENSE
123
+ - README.md
124
+ - Rakefile
125
+ - bin/tetrahedron
126
+ - config/app.ru
127
+ - config/application.rb
128
+ - config/environment.rb
129
+ - config/puma.rb
130
+ - lib/tetrahedron.rb
131
+ - lib/tetrahedron/app.rb
132
+ - lib/tetrahedron/assets.rb
133
+ - lib/tetrahedron/base.rb
134
+ - lib/tetrahedron/bootfile.rb
135
+ - lib/tetrahedron/bundler.rb
136
+ - lib/tetrahedron/configuration.rb
137
+ - lib/tetrahedron/controller.rb
138
+ - lib/tetrahedron/database.rb
139
+ - lib/tetrahedron/endpoint.rb
140
+ - lib/tetrahedron/environment.rb
141
+ - lib/tetrahedron/error.rb
142
+ - lib/tetrahedron/errors.rb
143
+ - lib/tetrahedron/gem.rb
144
+ - lib/tetrahedron/model.rb
145
+ - lib/tetrahedron/rake.rb
146
+ - lib/tetrahedron/redis.rb
147
+ - lib/tetrahedron/sessions.rb
148
+ - lib/tetrahedron/tasks/tet.rake
149
+ - tetrahedron.gemspec
150
+ homepage: http://github.com/mtwilliams/tetrahedron
151
+ licenses:
152
+ - Public Domain
153
+ metadata: {}
154
+ post_install_message:
155
+ rdoc_options: []
156
+ require_paths:
157
+ - lib
158
+ required_ruby_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: 2.2.3
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ requirements: []
169
+ rubyforge_project:
170
+ rubygems_version: 2.4.5.1
171
+ signing_key:
172
+ specification_version: 4
173
+ summary: Opinionated Sinatra.
174
+ test_files: []