gin 0.0.0 → 1.0.0

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.
@@ -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