gin 0.0.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ require 'cgi'
2
+
3
+ unless RUBY_VERSION >= "2.0"
4
+
5
+ class CGI #:nodoc:
6
+ class << self
7
+ alias_method :__escapeHTML, :escapeHTML
8
+ end
9
+
10
+ def self.escapeHTML str
11
+ __escapeHTML(str).gsub!("'", "&#39;")
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,10 @@
1
+ module GinClass #:nodoc:
2
+ private
3
+
4
+ def class_proxy name, *names
5
+ names.unshift name
6
+ names.each do |n|
7
+ define_method(n){|*args,&block| self.class.send(n,*args,&block) }
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,113 @@
1
+ module Gin::Errorable
2
+ extend GinClass
3
+
4
+ def self.included klass
5
+ klass.extend ClassMethods
6
+ end
7
+
8
+
9
+ module ClassMethods
10
+
11
+ ##
12
+ # Define an error handler for this Controller. Configurable with exceptions
13
+ # or status codes. Omitting the err_types argument acts as a catch-all for
14
+ # non-explicitly handled errors.
15
+ #
16
+ # error 502, 503, 504 do
17
+ # # handle unexpected upstream error
18
+ # end
19
+ #
20
+ # error do |err|
21
+ # # catch-all
22
+ # end
23
+ #
24
+ # error Timeout::Error do |err|
25
+ # # something timed out
26
+ # end
27
+
28
+ def error *err_types, &block
29
+ return unless block_given?
30
+ err_types << nil if err_types.empty?
31
+
32
+ err_types.each do |name|
33
+ self.error_handlers[name] = block
34
+ end
35
+ end
36
+
37
+
38
+ ##
39
+ # Run after an error has been raised and optionally handled by an
40
+ # error callback. The block will get run on all errors and is given
41
+ # the exception instance as an argument.
42
+ # Note: This block will not get run after http status error handlers.
43
+
44
+ def all_errors &block
45
+ return unless block_given?
46
+ self.error_handlers[:all] = block
47
+ end
48
+
49
+
50
+ ##
51
+ # Hash of error handlers defined by Gin::Controller.error.
52
+
53
+ def error_handlers
54
+ @err_handlers ||= {}
55
+ end
56
+
57
+
58
+ ##
59
+ # Find the appropriate error handler for the given error.
60
+ # First looks for handler in the current class, then looks
61
+ # in parent classes if none is found.
62
+
63
+ def error_handler_for err #:nodoc:
64
+ handler =
65
+ case err
66
+ when Integer
67
+ error_handlers[err] || error_handlers[nil]
68
+
69
+ when Exception
70
+ klasses = err.class.ancestors[0...-3]
71
+ key = klasses.find{|klass| error_handlers[klass] }
72
+ error_handlers[key]
73
+
74
+ else
75
+ error_handlers[err]
76
+ end
77
+
78
+ handler ||
79
+ self.superclass.respond_to?(:error_handler_for) &&
80
+ self.superclass.error_handler_for(err)
81
+ end
82
+ end
83
+
84
+
85
+ class_proxy :error_handlers, :error_handler_for
86
+
87
+ ##
88
+ # Calls the appropriate error handlers for the given error.
89
+ # Re-raises the error if no handler is found.
90
+
91
+ def handle_error err
92
+ (@env[Gin::App::RACK_KEYS[:errors]] ||= []) << err
93
+ status(err.http_status) if err.respond_to?(:http_status)
94
+ status(500) unless (400..599).include? status
95
+
96
+ handler = error_handler_for(err)
97
+ instance_exec(err, &handler) if handler
98
+
99
+ ahandler = error_handler_for(:all)
100
+ instance_exec(err, &ahandler) if ahandler
101
+
102
+ raise err unless handler
103
+ end
104
+
105
+
106
+ ##
107
+ # Calls the appropriate error handlers for the given status code.
108
+
109
+ def handle_status code
110
+ handler = error_handler_for(code)
111
+ instance_exec(&handler) if handler
112
+ end
113
+ end
@@ -0,0 +1,200 @@
1
+ module Gin::Filterable
2
+
3
+ extend GinClass
4
+
5
+ class InvalidFilterError < Gin::Error; end
6
+
7
+ def self.included klass
8
+ klass.extend ClassMethods
9
+ end
10
+
11
+
12
+ module ClassMethods
13
+
14
+ ##
15
+ # Create a filter for controller actions.
16
+ # filter :logged_in do
17
+ # @user && @user.logged_in?
18
+ # end
19
+ #
20
+ # Use Gin::Controller.before_filter and Gin::Controller.after_filter to
21
+ # apply filters.
22
+
23
+ def filter name, &block
24
+ self.filters[name.to_sym] = block
25
+ end
26
+
27
+
28
+ ##
29
+ # Hash of filters defined by Gin::Controller.filter.
30
+ # This attribute is inherited.
31
+
32
+ def filters
33
+ @filters ||= self.superclass.respond_to?(:filters) ?
34
+ self.superclass.filters.dup : {}
35
+ end
36
+
37
+
38
+ def modify_filter_stack filter_hsh, name, *names #:nodoc:
39
+ names = [name].concat(names)
40
+ opts = Hash === names[-1] ? names.pop : {}
41
+ names.map!(&:to_sym)
42
+
43
+ if opts[:only]
44
+ Array(opts[:only]).each do |action|
45
+ action = action.to_sym
46
+ filter_hsh[action] ||= filter_hsh[nil].dup
47
+ yield filter_hsh, action, names
48
+ end
49
+
50
+ elsif opts[:except]
51
+ except = Array(opts[:except])
52
+ filter_hsh.keys.each do |action|
53
+ next if action.nil?
54
+ filter_hsh[action] ||= filter_hsh[nil].dup and next if
55
+ except.include?(action)
56
+
57
+ yield filter_hsh, action, names
58
+ end
59
+ yield filter_hsh, nil, names
60
+
61
+ else
62
+ filter_hsh.keys.each do |action|
63
+ yield filter_hsh, action, names
64
+ end
65
+ end
66
+ end
67
+
68
+
69
+ def append_filters filter_hsh, name, *names #:nodoc:
70
+ modify_filter_stack(filter_hsh, name, *names) do |h,k,n|
71
+ h[k].concat n
72
+ end
73
+ end
74
+
75
+
76
+ def skip_filters filter_hsh, name, *names #:nodoc:
77
+ modify_filter_stack(filter_hsh, name, *names) do |h,k,n|
78
+ h[k] -= n
79
+ end
80
+ end
81
+
82
+
83
+ ##
84
+ # Assign one or more filters to run before calling an action.
85
+ # Set for all actions by default.
86
+ # This attribute is inherited.
87
+ # Supports an options hash as the last argument with :only and :except
88
+ # keys.
89
+ #
90
+ # before_filter :logged_in, :except => :index do
91
+ # verify_session! || halt 401
92
+ # end
93
+
94
+ def before_filter name, *opts, &block
95
+ filter(name, &block) if block_given?
96
+ append_filters(before_filters, name, *opts)
97
+ end
98
+
99
+
100
+ ##
101
+ # List of before filters.
102
+ # This attribute is inherited.
103
+
104
+ def before_filters
105
+ return @before_filters if @before_filters
106
+ @before_filters ||= {nil => []}
107
+
108
+ if superclass.respond_to?(:before_filters)
109
+ superclass.before_filters.each{|k,v| @before_filters[k] = v.dup }
110
+ end
111
+
112
+ @before_filters
113
+ end
114
+
115
+
116
+ ##
117
+ # Skip a before filter in the context of the controller.
118
+ # This attribute is inherited.
119
+ # Supports an options hash as the last argument with :only and :except
120
+ # keys.
121
+
122
+ def skip_before_filter name, *names
123
+ skip_filters(self.before_filters, name, *names)
124
+ end
125
+
126
+
127
+ ##
128
+ # Assign one or more filters to run after calling an action.
129
+ # Set for all actions by default.
130
+ # This attribute is inherited.
131
+ # Supports an options hash as the last argument with :only and :except
132
+ # keys.
133
+ #
134
+ # after_filter :clear_cookies, :only => :logout do
135
+ # session[:user] = nil
136
+ # end
137
+
138
+ def after_filter name, *opts, &block
139
+ filter(name, &block) if block_given?
140
+ append_filters(self.after_filters, name, *opts)
141
+ end
142
+
143
+
144
+ ##
145
+ # List of after filters.
146
+
147
+ def after_filters
148
+ return @after_filters if @after_filters
149
+ @after_filters ||= {nil => []}
150
+
151
+ if superclass.respond_to?(:after_filters)
152
+ superclass.after_filters.each{|k,v| @after_filters[k] = v.dup }
153
+ end
154
+
155
+ @after_filters
156
+ end
157
+
158
+
159
+ ##
160
+ # Skip an after filter in the context of the controller.
161
+ # This attribute is inherited.
162
+ # Supports an options hash as the last argument with :only and :except
163
+ # keys.
164
+
165
+ def skip_after_filter name, *names
166
+ skip_filters(self.after_filters, name, *names)
167
+ end
168
+
169
+
170
+ ##
171
+ # Get an Array of before filter names for the given action.
172
+
173
+ def before_filters_for action
174
+ before_filters[action] || before_filters[nil] || []
175
+ end
176
+
177
+
178
+ ##
179
+ # Get an Array of after filter names for the given action.
180
+
181
+ def after_filters_for action
182
+ after_filters[action] || after_filters[nil] || []
183
+ end
184
+ end
185
+
186
+
187
+ class_proxy :filters, :before_filters, :after_filters,
188
+ :before_filters_for, :after_filters_for
189
+
190
+ ##
191
+ # Chain-call filters from an action. Raises the filter exception if any
192
+ # filter in the chain fails.
193
+ # filter :logged_in, :admin
194
+
195
+ def filter *names
196
+ names.each do |n|
197
+ instance_eval(&self.filters[n.to_sym])
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,90 @@
1
+ module Gin::Reloadable #:nodoc:
2
+ extend GinClass
3
+
4
+ def self.included klass
5
+ klass.extend ClassMethods
6
+ end
7
+
8
+
9
+ module ClassMethods #:nodoc:
10
+ def reloadables
11
+ @reloadables ||= {}
12
+ end
13
+
14
+
15
+ def erase_dependencies!
16
+ reloadables.each do |key, (path, files, consts)|
17
+ erase! files, consts
18
+ end
19
+ true
20
+ end
21
+
22
+
23
+ def erase! files, consts, parent=nil
24
+ parent ||= Object
25
+ files.each{|f| $LOADED_FEATURES.delete f }
26
+ clear_constants parent, consts
27
+ end
28
+
29
+
30
+ def clear_constants parent, names=nil
31
+ names ||= parent.constants
32
+
33
+ names.each do |name|
34
+ const = parent.const_get(name)
35
+ next unless const
36
+
37
+ if Class === const
38
+ next unless parent == Object || const.name =~ /(^|::)#{parent.name}::/
39
+ clear_constants const
40
+ parent.send(:remove_const, name)
41
+ else
42
+ parent.send(:remove_const, name) rescue nil
43
+ end
44
+ end
45
+ end
46
+
47
+
48
+ def without_warnings &block
49
+ warn_level = $VERBOSE
50
+ $VERBOSE = nil
51
+ yield
52
+ ensure
53
+ $VERBOSE = warn_level
54
+ end
55
+
56
+
57
+ def track_require file
58
+ old_consts = Object.constants
59
+ old_features = $LOADED_FEATURES.dup
60
+
61
+ filepath = Gin.find_loadpath file
62
+
63
+ if !reloadables[filepath]
64
+ success = Object.send(:require, file)
65
+
66
+ else reloadables[filepath]
67
+ without_warnings{
68
+ success = Object.send(:require, file)
69
+ }
70
+ end
71
+
72
+ reloadables[filepath] = [
73
+ file,
74
+ $LOADED_FEATURES - old_features,
75
+ Object.constants - old_consts
76
+ ] if success
77
+
78
+ success
79
+ end
80
+
81
+
82
+ def require file
83
+ if autoreload
84
+ track_require file
85
+ else
86
+ super file
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,76 @@
1
+ class Gin::Request < Rack::Request
2
+
3
+ def initialize env
4
+ super
5
+ self.params.update env[Gin::App::RACK_KEYS[:path_params]] if
6
+ env[Gin::App::RACK_KEYS[:path_params]]
7
+ end
8
+
9
+
10
+ def forwarded?
11
+ @env.include? "HTTP_X_FORWARDED_HOST"
12
+ end
13
+
14
+
15
+ def ssl?
16
+ scheme == 'https'
17
+ end
18
+
19
+
20
+ def safe?
21
+ get? or head? or options? or trace?
22
+ end
23
+
24
+
25
+ def idempotent?
26
+ safe? or put? or delete?
27
+ end
28
+
29
+
30
+ def params
31
+ unless @params
32
+ super
33
+ @params = process_params @params
34
+ end
35
+
36
+ @params
37
+ end
38
+
39
+
40
+ private
41
+
42
+ M_BOOLEAN = /^true|false$/ #:nodoc:
43
+ M_FLOAT = /^\d+\.\d+$/ #:nodoc:
44
+ M_INTEGER = /^\d+$/ #:nodoc:
45
+
46
+ ##
47
+ # Enable string or symbol key access to the nested params hash.
48
+ # Make String numbers into Numerics.
49
+
50
+ def process_params object
51
+ case object
52
+ when Hash
53
+ new_hash = indifferent_hash
54
+ object.each { |key, value| new_hash[key] = process_params(value) }
55
+ new_hash
56
+ when Array
57
+ object.map { |item| process_params(item) }
58
+ when M_BOOLEAN
59
+ object == "true"
60
+ when M_FLOAT
61
+ object.to_f
62
+ when M_INTEGER
63
+ object.to_i
64
+ else
65
+ object
66
+ end
67
+ end
68
+
69
+
70
+ ##
71
+ # Creates a Hash with indifferent access.
72
+
73
+ def indifferent_hash
74
+ Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
75
+ end
76
+ end