pakyow-core 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. data/pakyow-core/CHANGES +3 -0
  2. data/pakyow-core/MIT-LICENSE +20 -0
  3. data/pakyow-core/README +1 -0
  4. data/pakyow-core/bin/pakyow +14 -0
  5. data/pakyow-core/lib/commands/USAGE +8 -0
  6. data/pakyow-core/lib/commands/USAGE-NEW +11 -0
  7. data/pakyow-core/lib/commands/USAGE-SERVER +12 -0
  8. data/pakyow-core/lib/commands/server.rb +8 -0
  9. data/pakyow-core/lib/core/application.rb +463 -0
  10. data/pakyow-core/lib/core/base.rb +17 -0
  11. data/pakyow-core/lib/core/configuration/app.rb +73 -0
  12. data/pakyow-core/lib/core/configuration/base.rb +32 -0
  13. data/pakyow-core/lib/core/configuration/server.rb +19 -0
  14. data/pakyow-core/lib/core/helpers.rb +22 -0
  15. data/pakyow-core/lib/core/loader.rb +35 -0
  16. data/pakyow-core/lib/core/log.rb +35 -0
  17. data/pakyow-core/lib/core/presenter_base.rb +7 -0
  18. data/pakyow-core/lib/core/request.rb +66 -0
  19. data/pakyow-core/lib/core/route_store.rb +117 -0
  20. data/pakyow-core/lib/generators/pakyow/app/app_generator.rb +26 -0
  21. data/pakyow-core/lib/generators/pakyow/app/templates/README +54 -0
  22. data/pakyow-core/lib/generators/pakyow/app/templates/app/lib/application_controller.rb +6 -0
  23. data/pakyow-core/lib/generators/pakyow/app/templates/app/views/main.html +1 -0
  24. data/pakyow-core/lib/generators/pakyow/app/templates/app/views/pakyow.html +12 -0
  25. data/pakyow-core/lib/generators/pakyow/app/templates/config/application.rb +18 -0
  26. data/pakyow-core/lib/generators/pakyow/app/templates/config.ru +10 -0
  27. data/pakyow-core/lib/generators/pakyow/app/templates/logs/requests.log +0 -0
  28. data/pakyow-core/lib/generators/pakyow/app/templates/public/favicon.ico +0 -0
  29. data/pakyow-core/lib/generators/pakyow/app/templates/rakefile +5 -0
  30. data/pakyow-core/lib/pakyow-core.rb +14 -0
  31. data/pakyow-core/lib/utils/dir.rb +18 -0
  32. data/pakyow-core/lib/utils/hash.rb +31 -0
  33. data/pakyow-core/lib/utils/string.rb +37 -0
  34. metadata +113 -0
@@ -0,0 +1,22 @@
1
+ module Pakyow
2
+
3
+ # Helper methods that simply provide information (for use in binders)
4
+ module GeneralHelpers
5
+ def request
6
+ Pakyow.app.request
7
+ end
8
+
9
+ def response
10
+ Pakyow.app.response
11
+ end
12
+ end
13
+
14
+ # Helper methods specific to delegates and controllers.
15
+ module Helpers
16
+ include GeneralHelpers
17
+
18
+ def app
19
+ Pakyow.app
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,35 @@
1
+ module Pakyow
2
+
3
+ # Handles the loading and reloading of a Pakyow application. If in development
4
+ # mode, files are automatically reloaded if modified.
5
+ class Loader
6
+
7
+ # Loads files in the provided path, decending into child directories.
8
+ def load!(path)
9
+ require_recursively(path)
10
+ end
11
+
12
+ protected
13
+
14
+ def require_recursively(dir)
15
+ @times ||= {}
16
+ if File.exists?(dir)
17
+ DirUtils.walk_dir(dir) do |path|
18
+ next if FileTest.directory?(path)
19
+
20
+ split = path.split('/')
21
+ next if split[split.length-1].start_with?('.')
22
+
23
+ if Configuration::Base.app.auto_reload
24
+ if !@times[path] || (@times[path] && File.mtime(path) - @times[path] > 0)
25
+ load(path)
26
+ @times[path] = File.mtime(path)
27
+ end
28
+ else
29
+ require path
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ module Pakyow
2
+
3
+ # Provides an easy way to log text, warnings, etc.
4
+ class Log
5
+
6
+ # Adds text to the log.
7
+ def self.puts(text = "")
8
+ return if !Configuration::Base.app.log
9
+
10
+ @@console ||= Logger.new($stdout)
11
+ @@console << "#{text}\r\n"
12
+
13
+ dir = "#{Configuration::Base.app.log_dir}"
14
+
15
+ if File.exists?(dir)
16
+ @@file ||= Logger.new("#{dir}/#{Configuration::Base.app.log_name}")
17
+ @@file << "#{text}\r\n"
18
+ end
19
+ end
20
+
21
+ class << self
22
+ alias :enter :puts
23
+ end
24
+
25
+ # Adds warning text to the log.
26
+ def self.warn(text)
27
+ Log.enter("WARNING: #{text}")
28
+ end
29
+
30
+ # Adds error text to the log.
31
+ def self.error(text)
32
+ Log.enter("ERROR: #{text}")
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,7 @@
1
+ module Pakyow
2
+ class PresenterBase
3
+ def self.inherited(subclass)
4
+ Configuration::Base.app.presenter = subclass
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,66 @@
1
+ module Pakyow
2
+
3
+ # The Request object.
4
+ class Request < Rack::Request
5
+ attr_accessor :restful, :route_spec, :controller, :action, :format, :error
6
+
7
+ # Easy access to path_info.
8
+ def path
9
+ self.path_info
10
+ end
11
+
12
+ # Determines the request method.
13
+ def method
14
+ request_method.downcase.to_sym
15
+ end
16
+
17
+ def format=(format)
18
+ @format = format ? format.to_sym : :html
19
+
20
+ # Set response type
21
+ Pakyow.app.response["Content-Type"] = Rack::Mime.mime_type(".#{@format}")
22
+ end
23
+
24
+ def session
25
+ env['rack.session'] || {}
26
+ end
27
+
28
+ def cookies
29
+ @cookies ||= HashUtils.strhash(super)
30
+ end
31
+
32
+ # Returns indifferent params (see {HashUtils.strhash} for more info on indifferent hashes).
33
+ def params
34
+ @params ||= HashUtils.strhash(super)
35
+ end
36
+
37
+ # Returns array of url components.
38
+ def url_parts
39
+ unless @url
40
+ @url = self.class.split_url(self.env['PATH_INFO'])
41
+ end
42
+
43
+ return @url
44
+ end
45
+
46
+ # Returns array of referer components.
47
+ def referer_parts
48
+ unless @referer
49
+ @referer = self.class.split_url(self.env['HTTP_REFERER'])
50
+ end
51
+
52
+ return @referer
53
+ end
54
+
55
+ private
56
+
57
+ def self.split_url(url)
58
+ arr = []
59
+ url.split('/').each { |r|
60
+ arr << r unless r.empty?
61
+ }
62
+
63
+ return arr
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,117 @@
1
+ module Pakyow
2
+ class RouteStore
3
+
4
+ def initialize()
5
+ @order = 1
6
+ @store =
7
+ {
8
+ # string routes are stored, for each method, as a hash of 'route'=>{:block=>b,:order=>n}
9
+ :string => {:get=>{}, :post=>{}, :put=>{}, :delete=>{}},
10
+
11
+ # regex routes are stored, for each method, as an array of hashes {:regex=>r,:block=>b,:order=>n,:vars=>{n=>var}}
12
+ # they are in definition order in the array
13
+ :regex => {:get=>[], :post=>[], :put=>[], :delete=>[]}
14
+
15
+ # :order is a global order across both string and regex routes.
16
+ }
17
+ end
18
+
19
+ def add_route(route_spec, block, method, data)
20
+ route_spec = normalize_route(route_spec)
21
+ route_to_match, vars = extract_route_vars(route_spec)
22
+ if route_to_match.class == String
23
+ @store[:string][method][route_to_match]={:block => block,
24
+ :order => @order,
25
+ :data => data}
26
+ @order = @order + 1
27
+ elsif route_to_match.class == Regexp
28
+ @store[:regex][method] << {:regex => route_to_match,
29
+ :block => block,
30
+ :order => @order,
31
+ :vars => vars,
32
+ :data => data}
33
+ @order = @order + 1
34
+ end
35
+ end
36
+
37
+ # returns block, {:vars=>{:var=>matched_value, ...}, :data=>data}
38
+ def get_block(route, method)
39
+ route = normalize_route(route)
40
+ # Get the match for a string route
41
+ string_route_match = @store[:string][method][route]
42
+
43
+ # Get first regex match
44
+ regex_route_match = nil
45
+ match_data = nil
46
+ @store[:regex][method].each { |rinfo|
47
+ if match_data = rinfo[:regex].match(route)
48
+ regex_route_match = rinfo
49
+ break
50
+ end
51
+ }
52
+
53
+ # return block for match with smaller :order
54
+ if string_route_match && regex_route_match
55
+ if string_route_match[:order] < regex_route_match[:order]
56
+ data = string_route_match[:data]
57
+ return string_route_match[:block], {:vars=>{}, :data=>data}
58
+ else
59
+ data = regex_route_match[:data]
60
+ return regex_route_match[:block], {:vars=>build_regex_var_values(regex_route_match[:vars], match_data), :data=>data}
61
+ end
62
+ elsif string_route_match
63
+ data = string_route_match[:data]
64
+ return string_route_match[:block], {:vars=>{}, :data=>data}
65
+ elsif regex_route_match
66
+ data = regex_route_match[:data]
67
+ return regex_route_match[:block], {:vars=>build_regex_var_values(regex_route_match[:vars], match_data), :data=>data}
68
+ else
69
+ return nil, {:vars=>{}, :data=>nil}
70
+ end
71
+
72
+ end
73
+
74
+ private
75
+
76
+ # Returns a regex and an array of variable info
77
+ def extract_route_vars(route_spec)
78
+ return route_spec, [] if route_spec.is_a?(Regexp)
79
+
80
+ unless route_spec[0,1] == ':' || route_spec.index('/:')
81
+ return route_spec, []
82
+ end
83
+
84
+ vars = []
85
+ position_counter = 0
86
+ regex_route = route_spec
87
+ route_spec.split('/').each_with_index do |segment, i|
88
+ if segment.include?(':')
89
+ position_counter += 1
90
+ vars << { :position => position_counter, :var => segment.gsub(':', '').to_sym }
91
+ regex_route = regex_route.gsub(segment, '([^new/]+)')
92
+ end
93
+ end
94
+
95
+ reg = Regexp.new("^#{regex_route}$")
96
+
97
+ return reg, vars
98
+ end
99
+
100
+ # remove leading/trailing forward slashes
101
+ def normalize_route(route_spec)
102
+ return route_spec if route_spec.is_a?(Regexp)
103
+ route_spec = route_spec[1, route_spec.length - 1] if route_spec[0, 1] == '/'
104
+ route_spec = route_spec[0, route_spec.length - 1] if route_spec[route_spec.length - 1, 1] == '/'
105
+ route_spec
106
+ end
107
+
108
+ def build_regex_var_values(vars_info, match_data)
109
+ var_values = {}
110
+ vars_info.each { |vi|
111
+ var_values[vi[:var]] = match_data[vi[:position]]
112
+ }
113
+ var_values
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,26 @@
1
+ require 'fileutils'
2
+
3
+ module Pakyow
4
+ module Generators
5
+ class AppGenerator
6
+ class << self
7
+ def start
8
+ if ARGV.first == '--help' || ARGV.first == '-h'
9
+ puts File.open(File.join(CORE_PATH, 'commands/USAGE-NEW')).read
10
+ else
11
+ generator = self.new
12
+ generator.build(ARGV.first)
13
+ end
14
+ end
15
+ end
16
+
17
+ def initialize
18
+ @src = "#{File.expand_path('../', __FILE__)}/templates/."
19
+ end
20
+
21
+ def build(dest)
22
+ FileUtils.cp_r(@src, dest)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,54 @@
1
+ # Introduction
2
+
3
+ Pakyow is a web framework for Ruby that knocks out projects with a serious
4
+ punch. Pound for pound its the best way to build a web app. Get ready to rumble.
5
+
6
+ Pakyow brings a unique approach to development:
7
+
8
+ ## Views are views.
9
+ Views are 100% HTML, no template language required. The view has finally been
10
+ freed from logic.
11
+
12
+ ## Views are data aware.
13
+ A view knows what it presents. Use this to create powerful connections between
14
+ business logic and views.
15
+
16
+ ## Keep you moving forward.
17
+ Prototype an app by building the views first. Then write the view logic
18
+ without changing a single view.
19
+
20
+ There are two main components of Pakyow. The first is Pakyow Core, which
21
+ handles routing requests to business logic. The second component is Pakyow
22
+ Presenter, which gives an application the ability to have a presentation
23
+ layer and provides mechanisms for the controller to bind data to the
24
+ presentation layer. Pakyow Core can operate independently of Pakyow
25
+ Presenter for those cases where an application doesn't need a presentation layer.
26
+
27
+ # Getting Started
28
+
29
+ 1. Install Pakyow:
30
+
31
+ gem install pakyow
32
+
33
+ 2. Create a new Pakyow application from the command prompt:
34
+
35
+ pakyow new webapp
36
+
37
+ 3. Move to the "webapp" directory and start the application:
38
+
39
+ cd webapp; pakyow server
40
+
41
+ 4. You'll find the application running here: http://localhost:3000
42
+
43
+ # Next Steps
44
+
45
+ The following resources might be handy:
46
+
47
+ Website:
48
+ http://pakyow.com
49
+
50
+ Manual:
51
+ http://pakyow.com/manual
52
+
53
+ Code:
54
+ http://github.com/metabahn/pakyow
@@ -0,0 +1,6 @@
1
+ class ApplicationController
2
+ include Pakyow::Helpers
3
+
4
+ def index
5
+ end
6
+ end
@@ -0,0 +1 @@
1
+ <h1>Welcome to Pakyow!</h1>
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Pakyow</title>
5
+ </head>
6
+
7
+ <body>
8
+ <div id="wrapper">
9
+ <div id="main"></div>
10
+ </div>
11
+ </body>
12
+ </html>
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'pakyow'
3
+
4
+ module PakyowApplication
5
+ class Application < Pakyow::Application
6
+ config.app.default_environment = :development
7
+
8
+ configure(:development) do
9
+ end
10
+
11
+ routes do
12
+ default :ApplicationController, :index
13
+ end
14
+
15
+ middleware do
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ require 'config/application'
2
+ PakyowApplication::Application.stage(:development)
3
+
4
+ app = Rack::Builder.new do
5
+ # Needed for Pakyow to work
6
+ use Rack::MethodOverride
7
+ run PakyowApplication::Application.new
8
+ end.to_app
9
+
10
+ run(app)
@@ -0,0 +1,5 @@
1
+ env = ARGV[1] || 'development'
2
+ env = env.split('=')[1] || env
3
+
4
+ require 'config/application'
5
+ PakyowApplication::Application.stage(env.to_sym)
@@ -0,0 +1,14 @@
1
+ libdir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
+
4
+ # Gems
5
+ require 'find'
6
+ require 'rack'
7
+ require 'rack/file'
8
+ require 'logger'
9
+ require 'cgi'
10
+
11
+ # Base
12
+ autoload :Pakyow, 'core/base'
13
+
14
+ include Pakyow
@@ -0,0 +1,18 @@
1
+ module Pakyow
2
+
3
+ # Utility methods for directories and files.
4
+ class DirUtils
5
+
6
+ # visit dir, then all files in dir, then walk_dir each directory in dir
7
+ def self.walk_dir(dir, &block)
8
+ yield dir
9
+ all = Dir.entries(dir)
10
+ partition = all.partition{|e| File.file?("#{dir}/#{e}")}
11
+ files = partition[0]
12
+ dirs = partition[1]
13
+ files.each{|f| yield "#{dir}/#{f}" unless f.start_with?(".")}
14
+ dirs.each{|d| walk_dir("#{dir}/#{d}", &block) unless d.start_with?(".")}
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ module Pakyow
2
+
3
+ # Utility methods for hashes.
4
+ class HashUtils
5
+ # Creates an indifferent hash. This means that when indifferentized, this hash:
6
+ # { 'foo' => 'bar' }
7
+ #
8
+ # Can be accessed like this:
9
+ # { :foo => 'bar' }
10
+ #
11
+ def self.strhash(hash)
12
+ indifferentize(hash)
13
+ end
14
+
15
+ protected
16
+
17
+ # (see {strhash})
18
+ def self.indifferentize(hash)
19
+ hash.each_pair do |key, value|
20
+ hash[key] = indifferentize(value) if value.is_a? Hash
21
+ end
22
+
23
+ indifferent_hash.merge(hash)
24
+ end
25
+
26
+ # (see {strhash})
27
+ def self.indifferent_hash
28
+ Hash.new { |hash,key| hash[key.to_s] if Symbol === key }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,37 @@
1
+ module Pakyow
2
+
3
+ # Utility methods for strings.
4
+ class StringUtils
5
+
6
+ # Creates an underscored, lowercase version of a string.
7
+ # This was borrowed from another library, probably ActiveSupport.
8
+ def self.underscore(string)
9
+ string.gsub(/::/, '/').
10
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
11
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
12
+ tr("-", "_").
13
+ downcase
14
+ end
15
+
16
+ # split . seperated string at the last .
17
+ def self.split_at_last_dot(s)
18
+ split_index = s.rindex('.')
19
+ return s,nil unless split_index
20
+ left = s[0,split_index]
21
+ right = s[split_index+1,s.length-(split_index+1)]
22
+ return left,right
23
+ end
24
+
25
+ def self.remove_route_vars(route_spec)
26
+ return unless route_spec
27
+ arr = route_spec.split('/')
28
+ new_arr = []
29
+ arr.each {|e| new_arr << e unless e[0,1] == ':'}
30
+ ret = new_arr.join('/')
31
+ return '/' if ret == ''
32
+ return ret
33
+ end
34
+
35
+
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pakyow-core
3
+ version: !ruby/object:Gem::Version
4
+ hash: 5
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 1
10
+ version: 0.6.1
11
+ platform: ruby
12
+ authors:
13
+ - Bryan Powell
14
+ autorequire:
15
+ bindir: pakyow-core/bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-20 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rack
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 11
29
+ segments:
30
+ - 1
31
+ - 2
32
+ version: "1.2"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: pakyow-core
36
+ email: bryan@metabahn.com
37
+ executables:
38
+ - pakyow
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - pakyow-core/CHANGES
45
+ - pakyow-core/README
46
+ - pakyow-core/MIT-LICENSE
47
+ - pakyow-core/lib/commands/server.rb
48
+ - pakyow-core/lib/commands/USAGE
49
+ - pakyow-core/lib/commands/USAGE-NEW
50
+ - pakyow-core/lib/commands/USAGE-SERVER
51
+ - pakyow-core/lib/core/application.rb
52
+ - pakyow-core/lib/core/base.rb
53
+ - pakyow-core/lib/core/configuration/app.rb
54
+ - pakyow-core/lib/core/configuration/base.rb
55
+ - pakyow-core/lib/core/configuration/server.rb
56
+ - pakyow-core/lib/core/helpers.rb
57
+ - pakyow-core/lib/core/loader.rb
58
+ - pakyow-core/lib/core/log.rb
59
+ - pakyow-core/lib/core/presenter_base.rb
60
+ - pakyow-core/lib/core/request.rb
61
+ - pakyow-core/lib/core/route_store.rb
62
+ - pakyow-core/lib/generators/pakyow/app/app_generator.rb
63
+ - pakyow-core/lib/generators/pakyow/app/templates/app/lib/application_controller.rb
64
+ - pakyow-core/lib/generators/pakyow/app/templates/app/views/main.html
65
+ - pakyow-core/lib/generators/pakyow/app/templates/app/views/pakyow.html
66
+ - pakyow-core/lib/generators/pakyow/app/templates/config/application.rb
67
+ - pakyow-core/lib/generators/pakyow/app/templates/config.ru
68
+ - pakyow-core/lib/generators/pakyow/app/templates/logs/requests.log
69
+ - pakyow-core/lib/generators/pakyow/app/templates/public/favicon.ico
70
+ - pakyow-core/lib/generators/pakyow/app/templates/rakefile
71
+ - pakyow-core/lib/generators/pakyow/app/templates/README
72
+ - pakyow-core/lib/pakyow-core.rb
73
+ - pakyow-core/lib/utils/dir.rb
74
+ - pakyow-core/lib/utils/hash.rb
75
+ - pakyow-core/lib/utils/string.rb
76
+ - pakyow-core/bin/pakyow
77
+ homepage: http://pakyow.com
78
+ licenses: []
79
+
80
+ post_install_message:
81
+ rdoc_options: []
82
+
83
+ require_paths:
84
+ - pakyow-core/lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 57
91
+ segments:
92
+ - 1
93
+ - 8
94
+ - 7
95
+ version: 1.8.7
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ requirements: []
106
+
107
+ rubyforge_project: pakyow-core
108
+ rubygems_version: 1.8.8
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: pakyow-core
112
+ test_files: []
113
+