Skip to content

Commit

Permalink
Added the Guesser JavaScript Halcyon example application.
Browse files Browse the repository at this point in the history
  • Loading branch information
mtodd committed Apr 18, 2008
1 parent 8d10fc3 commit f926f5b
Show file tree
Hide file tree
Showing 15 changed files with 659 additions and 2 deletions.
30 changes: 28 additions & 2 deletions examples/guesser/README
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
= Guesser

This application consists of the back end to keep track as the game progresses,
and the client which is a website to facilitate playing the game.

== Introduction

Asks the viewer a question and the viewer can see if their answer was correct.

This is a sample of a complicated Rack application (which can serve both the
necessary static files as well as the Halcyon application routes) and a simple
example of how to use the JavaScript client in a website.


== Installation

Just make sure that all of the dependencies are installed to run a normal
Halcyon application, include Rack, Merb, JSON, etc.


=== Dependencies

* Halcyon (halcyon >= 0.5.0)

== License

MIT License <http://www.opensource.org/licenses/mit-license.php>


== Contact

* Matt Todd <chiology@gmail.com>
32 changes: 32 additions & 0 deletions examples/guesser/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
%w(rubygems rake rake/clean rake/rdoctask fileutils pp halcyon).each{|dep|require dep}

include FileUtils

# Halcyon.root => the root application directory
# Halcyon.app => the application name

desc "Start the application on port 4647"
task :start do
sh "halcyon start -p 4647"
end

desc "Generate RDoc documentation"
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.options << '--line-numbers' << '--inline-source' <<
'--main' << 'README' <<
'--title' << "#{Halcyon.app} Documentation" <<
'--charset' << 'utf-8'
rdoc.rdoc_dir = "doc"
rdoc.rdoc_files.include('README')
rdoc.rdoc_files.include('app/**/*.rb')
rdoc.rdoc_files.include('lib/**/*.rb')
end

# = Custom Rake Tasks
#
# Add your custom rake tasks here.

# ...

# = Default Task
task :default => Rake::Task['start']
10 changes: 10 additions & 0 deletions examples/guesser/app/answers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Answers < Application

def check
question = post[:question]
answer = post[:answer]

ok Guesser.guess(question, answer)
end

end
5 changes: 5 additions & 0 deletions examples/guesser/app/application.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Application < Halcyon::Controller

# ...

end
21 changes: 21 additions & 0 deletions examples/guesser/app/questions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class Questions < Application

def random
problem = Guesser::Questions[rand(Guesser::Questions.length)]
response = {
:question => problem[:question],
:options => problem[:options]
}
ok response
end

def show
case params[:id]
when "random"
self.random
else
#
end
end

end
29 changes: 29 additions & 0 deletions examples/guesser/config/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# = Framework
#
# <tt>allow_from</tt>: specifies what connections to accept;
# * <tt>all</tt>: allow connections from all clients
# * <tt>local</tt>: only allow connections from the same host (localhost et al)
# * <tt>halcyon_clients</tt>: only Halcyon clients (tests the User-Agent only)
allow_from: all

# = Logging
#
# Configures the logging client in the framework, including destination,
# level filter, and what logger to use.
#
# <tt>type</tt>: the logger to use (defaults to Ruby's <tt>Logger</tt>)
# * <tt>Logger</tt>
# * <tt>Analogger</tt>
# * <tt>Logging</tt>
# * <tt>Log4r</tt>
# <tt>file</tt>: the log file; leave unset for STDOUT
# <tt>level</tt>: the message filter level (default to <tt>debug</tt>)
# * specific to the client used, often is: debug, info, warn, error, fatal
logging:
type: Logger
# file: # STDOUT
level: debug

# = Application
#
# Your application-specific configuration options here.
42 changes: 42 additions & 0 deletions examples/guesser/config/initialize/hooks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# = Hooks
#
# Specify actions to run at specific times during the application's execution,
# such as the startup or shutdown events.
#
# Available Hooks
# +startup+
# +shutdown+
#
# All hooks take the current application configuration as its sole block param.
#
# Examples
# Halcyon::Application.startup do |config|
# # Halcyon.db set in config/initialize/database.rb
# ::DB = Sequel(Halcyon.db)
# logger.info "Connected to database"
# end
#
# The +logger+ object is available to log messages on status or otherwise.

# = Startup
#
# Run when the Halcyon::Application object is instanciated, after all
# initializers are loaded.
#
# Ideal for establishing connections to resources like databases.
# Establish configuration options in initializer files, though.
Halcyon::Application.startup do |config|
# Load questions.
logger.info 'Questions: loading...'
Guesser::Questions = Halcyon::Runner.load_config(Halcyon.root/'config'/'questions.yml')[:questions]
logger.info 'Questions: loaded.'
end

# = Shutdown
#
# Run <tt>at_exit</tt>. Should run in most cases of termination.
#
# Ideal for closing connections to resources.
Halcyon::Application.shutdown do |config|
# logger.info 'Define shutdown tasks in config/initialize/hooks.rb'
end
10 changes: 10 additions & 0 deletions examples/guesser/config/initialize/requires.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# = Required Libraries
#
# Specify required libraries specific to the operation of your application.
#
# Examples
# %(digest/md5 tempfile date).each{|dep|require dep}
#
# RubyGems should already be required by Halcyon, so don't include it.

%w(lib/guesser).each{|dep|require dep}
51 changes: 51 additions & 0 deletions examples/guesser/config/initialize/routes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# = Routes
#
# Halcyon::Application::Router is the request routing mapper for the merb
# framework.
#
# You can route a specific URL to a controller / action pair:
#
# r.match("/contact").
# to(:controller => "info", :action => "contact")
#
# You can define placeholder parts of the url with the :symbol notation. These
# placeholders will be available in the params hash of your controllers. For example:
#
# r.match("/books/:book_id/:action").
# to(:controller => "books")
#
# Or, use placeholders in the "to" results for more complicated routing, e.g.:
#
# r.match("/admin/:module/:controller/:action/:id").
# to(:controller => ":module/:controller")
#
# You can also use regular expressions, deferred routes, and many other options.
# See merb/specs/merb/router.rb for a fairly complete usage sample.
#
# Stolen directly from generated Merb app. All documentation applies.
# Read more about the Merb router at http://merbivore.com/.
Halcyon::Application.route do |r|

# Sample route for the sample functionality in Application.
# Safe to remove!
# r.match('/time').to(:controller => 'application', :action => 'time')

# RESTful routes
r.resources :questions
# r.match('/questions/random').to(:controller => 'questions', :action => 'random')

# This is the default route for /:controller/:action/:id
# This is fine for most cases. If you're heavily using resource-based
# routes, you may want to comment/remove this line to prevent
# clients from calling your create or destroy actions with a GET
r.default_routes

# Change this for the default route to be available at /
# r.match('/').to(:controller => 'application', :action => 'index')
# It can often be useful to respond with available functionality if the
# application is a public-facing service.

# Default not-found route
{:action => 'not_found'}

end
45 changes: 45 additions & 0 deletions examples/guesser/config/questions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
questions:

- question: "Freebie"
options:
- "Pick me!"
answer: "Pick me!"

- question: "What time is it?"
options:
- "Now!"
- "Then."
- "Soon."
answer: "Now!"

- question: "What's up?"
options:
- "Nothing."
- "Something!"
answer: "Nothing."

- question: "What year did Columbus sail to America first?"
options:
- "1388"
- "1469"
- "1492"
- "1545"
answer: "1492"

- question: "Which of these shows does Cartoon Network not air?"
options:
- "Robot Chicken"
- "Metalocolypse"
- "Harvey Birdman, Attorney at Law"
- "The Damn Show"
- "Futurama"
- "Venture Brothers"
answer: "The Damn Show"

- question: "When I say 'What?', you say:"
options:
- "What what in the Butt"
- "Yeehaw!"
- "Galappegos Islands"
- "The Damn Show"
answer: "What what in the Butt"
66 changes: 66 additions & 0 deletions examples/guesser/lib/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
%w(rubygems halcyon).each{|dep|require dep}

module Guesser

# = Client
#
# The client interface for accessing services provided by the Halcyon
# application as defined in the controllers in <tt>app/</tt>.
#
# == Usage
#
# To use the Client in your application, create an instance and call methods
# defined here. For example:
#
# client = Guesser::Client.new('http://localhost:4647/')
# client.time #=> "Tue Apr 15 21:04:15 -0400 2008"
#
# You can just as easily call the primary <tt>get</tt>, <tt>post</tt>,
# <tt>put</tt>, and <tt>delete</tt> methods as well, passing in the +path+
# and any params. For example:
#
# client.get('/time') #=> "Tue Apr 15 21:04:15 -0400 2008"
#
# By default, if you enter a bad (non-existent) path or the application
# raises an exception and cannot complete successfully, the standard response
# format will be returned but with more appropriate +status+ and +body+
# values. For instance:
#
# client.get('/nonexistent/path') #=> {:status=>404,:body=>"Not Found"}
#
# Exceptions can be raised on any +status+ returned other than +200+ if you
# set <tt>Halcyon::Client#raise_exceptions!</tt> to +true+ (which is the
# default param).
#
# client.raise_exceptions! #=> true
# client.get('/nonexistent/path') #=> NotFound exception is raised
#
# These exceptions all inherit from <tt>Halcyon::Exceptions::Base</tt> so
# <tt>rescue</tt>ing just normal Halcyon errors is trivial.
#
# However, setting this value can cause the meaning and the appropriate
# error-handling measures put in place in actions. Although each method
# could just as easily set the +raise_exceptions+ configuration option
# itself, it is not advised to do so due to the possibility of non-
# consistent and confusing behavior it can cause.
#
# If raising exceptions is preferred, it should be set as soon as the
# client is created and the client methods should be designed accordingly.
class Client < Halcyon::Client

def self.version
VERSION.join('.')
end

def get_question
if (res = get('/questions/random'))[:status] == 200
res[:body]
else
warn "[#{res[:status]}] " << res[:body]
nil
end
end

end

end
21 changes: 21 additions & 0 deletions examples/guesser/lib/guesser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Guesser

VERSION = [0,1,0]

class << self

def version
VERSION.join('.')
end

def guess(question, answer)
response = false
Questions.each do |problem|
next unless problem[:question] == question
response = (problem[:answer] == answer)
end
response
end

end
end

0 comments on commit f926f5b

Please sign in to comment.