Permalink
Browse files

init

  • Loading branch information...
1 parent 5559997 commit 6d8d15f88ab09f0f2076ef117ccdd8fb9789a807 cloudhead committed Apr 15, 2009
Showing with 359 additions and 0 deletions.
  1. +5 −0 lib/document.rb
  2. +66 −0 lib/melon.rb
  3. +27 −0 lib/modules/base/controller.rb
  4. +84 −0 lib/modules/base/model.rb
  5. +17 −0 lib/modules/comments.rb
  6. +9 −0 lib/modules/error.rb
  7. +18 −0 lib/modules/posts.rb
  8. +90 −0 lib/modules/session.rb
  9. +43 −0 lib/router.rb
View
@@ -0,0 +1,5 @@
+module Melon
+ class Document < Hash
+
+ end
+end
View
@@ -0,0 +1,66 @@
+# Ruby
+require 'rack'
+require 'date'
+require 'digest'
+require 'json'
+
+$:.unshift File.dirname(__FILE__)
+
+require 'document'
+require 'router'
+
+# Load modules
+Dir.chdir('lib/modules') do
+ puts '* Opening modules/'
+ require 'base/model'
+ require 'base/controller'
+ Dir.new('.').entries.each do |f|
+ unless File.directory?( f )
+ puts '* Found ' + f
+ require f
+ end
+ end
+end
+
+module Melon
+ class Server
+ def initialize
+ puts "*"
+ puts "* Initializing Melon..."
+ puts "* Ruby " + RUBY_VERSION
+
+ raise "Melon needs ruby 1.9.1 or higher!" if RUBY_VERSION < '1.9.1'
+ end
+
+ # Called on each request
+ def call env
+ Router.new( env ).go.finish
+ end
+ end
+
+end
+
+class Object
+ # Syntactic sugar for const_get()
+ def self.[]( const )
+ self.const_get( const )
+ end
+
+ # For modules
+ def []( const )
+ self.const_get( const )
+ end
+
+ def null
+ nil.to_json
+ end
+end
+
+class String
+ alias each each_line
+end
+
+class Array
+ def second; self[1] end
+ def third; self[2] end
+end
@@ -0,0 +1,27 @@
+module Melon
+ module Base
+ class Controller
+ attr_reader :session
+
+ def initialize( key = '', params = {}, session )
+ @key = key
+ @input = params
+ @session = Melon::Session.new( session )
+ @response = {}
+
+ self
+ end
+
+ #
+ # All the CRUD stuff goes through here
+ #
+ def do action
+ { content: send( action ), session: @session }
+ end
+
+ def method_missing *args
+ { error: args.first + "doesn't exist" }
+ end
+ end
+ end
+end
View
@@ -0,0 +1,84 @@
+module Melon
+ module Base
+ class Model
+ attr_reader :doc
+
+ @has = nil
+ @belongs = ''
+ @key = :id
+
+ #
+ # Set the key to `value`
+ #
+ def initialize( doc = {} )
+
+ if doc.is_a? Document # From response object
+ @doc = doc
+ else # New document
+ @doc = Document.new
+ self.is = self.class.to_s.downcase.split('::').first
+
+ # Send the values through the attribute= functions
+ doc.each do |k, v|
+ send( k.to_s + '=', v )
+ end
+
+ puts "* Setting default values..."
+ # Set defaults on missing values
+ self.class.has.each do |k, v|
+ send( k.to_s + '=', v ) unless @doc[ k ]
+ end
+ puts "* New #{ self.class }: " + @doc.inspect
+ @doc[:id] = id
+ end
+
+ self
+ end
+
+ def id
+ @doc.id || send( self.class.key ).downcase.gsub(/[^a-z0-9]+/i, '-')
+ end
+
+ def is= a
+ @doc.is = a
+ end
+
+ #
+ # Accessor methods
+ #
+ # Define how the model hierarchy will be traversed
+ #
+ class << self
+ def has( has = nil )
+ @has = has || @has
+ end
+
+ def key
+ has.keys.first
+ end
+
+ def get id
+ self.new( Sky.get( id ) )
+ end
+ end
+
+ def to_json
+ @doc.to_json
+ end
+
+ #
+ # If the method isn't found, look in @doc
+ #
+ def method_missing *args
+ print "* super: Method :#{ args.first } not found, looking in @doc... "
+ if args.first.to_s =~ /=$/
+ puts "setting to #{args.last}"
+ @doc[ args.first.to_s.chop.intern ] = args.last
+ else # CASE
+ puts @doc[ args.first ]
+ @doc[ args.first ]
+ end
+ end
+ end
+ end
+end
View
@@ -0,0 +1,17 @@
+module Melon
+ module Comments
+ class Controller < Base::Controller
+ def create
+ Dir.chdir('public/json/comments') do
+ File.open( @input[:id] + '.json' ) do |f|
+ f.write( ( JSON.parse( f.read ) << {
+ author: @input[:author],
+ body: @input[:body],
+ date: Time.now.to_i
+ }).to_json )
+ end
+ end
+ end
+ end
+ end
+end
View
@@ -0,0 +1,9 @@
+module Melon
+ module Error
+ class Controller < Base::Controller
+ def report
+ "Routing error!"
+ end
+ end
+ end
+end
View
@@ -0,0 +1,18 @@
+module Melon
+ module Posts
+ class Model < Base::Model
+ end
+
+ class Controller < Base::Controller
+ def frontpage
+ Dir.chdir("public/json/posts") do
+ Dir.new( Dir.pwd ).entries.collect do |f|
+ if File.file?(f) && f =~ /.json$/
+ JSON.parse( File.read( f ) )
+ end
+ end.compact
+ end
+ end
+ end
+ end
+end
View
@@ -0,0 +1,90 @@
+module Melon
+ module Session
+ def self.new(*args)
+ Session::Model.new(*args)
+ end
+
+ class Model < Hash
+ def initialize session = {}
+ @env = session #unless session.empty?
+
+ self[:auth] = false
+ self[:failed] = 0
+
+ self <= session if session
+
+ self
+ end
+
+ # Copy a hash into the session
+ def <= s
+ s.each do |k, v|
+ self[ k ] = v
+ end
+ end
+
+ def god?
+ self[:god]
+ end
+
+ def god= bool
+ self[:god] = bool
+ end
+
+ def name
+ self[:name]
+ end
+
+ def login name = nil
+ self[:auth] = true
+ self[:name] ||= name
+ self
+ end
+
+ # Delete all cookies
+ def logout
+ self.each do |k,|
+ self.delete k
+ end
+ self
+ end
+
+ # Write session to env
+ def save!
+ @env.replace self
+ end
+
+ end
+
+ class Controller < Base::Controller
+ def create
+ unless @input.empty?
+ puts "* " + @input['name'] + " is logging in..."
+ thinker = Sky.get @input['name']
+
+ if @input['password'] == thinker['password']
+ # Login
+ @session.login @input['name']
+ @session.god = @input['name'] == Settings.cloudder.god ? true : false
+ else
+ @session[:auth] = false
+ @session[:failed] += 1
+ end
+ end
+ { session: @session, redirect: self./ }
+ end
+
+ def new
+ { session: @session }
+ end
+
+ def destroy
+ { session: @session.logout }
+ end
+
+ def method_missing *args
+ super
+ end
+ end
+ end
+end
View
@@ -0,0 +1,43 @@
+module Melon
+ class Router
+ def initialize env
+ @request = Rack::Request.new env
+ @response = Rack::Response.new
+ @session, path, @input = Session.new( @request.env['rack.session'] ),
+ @request.path_info,
+ @request.params
+
+ # Break path into discreet parts & trim slashes
+ route = path.
+ split('/').
+ reject { |i| i.empty? }.
+ drop(1) # Remove /m/
+
+ if route.size >= 2 && @request.xhr?
+ @module, @action, @key = *route
+ else
+ @module, @action = :error, :report
+ end
+
+ puts
+ puts "* Path: #@module/#@action/#@key"
+
+ self
+ end
+
+ #
+ # Create controller object & call action
+ #
+ def go
+ controller = Melon[ @module.capitalize ]::Controller.new( @key, @input, @session )
+ @output = controller.do( @action ) || {}
+ (@session <= @output[:session]).save!
+
+ @response.body = @output[:content].to_json
+ @response['Content-Length'] = @response.body.size.to_s
+ @response['Content-Type'] = 'application/json'
+
+ @response
+ end
+ end
+end

0 comments on commit 6d8d15f

Please sign in to comment.