rocketio 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "rocketio"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start
data/bin/setup DELETED
@@ -1,7 +0,0 @@
1
- #!/bin/bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
-
5
- bundle install
6
-
7
- # Do any other automated setup that you need to do here
@@ -1,167 +0,0 @@
1
- module RocketIO
2
- class Controller
3
-
4
- # if called without arguments render a template with lowercased name of current request method, e.g. get for GET, post for POST etc.
5
- # at first it will look between defined templates.
6
- # then it will search a file.
7
- # it will try each extension the effective engine has registered, e.g. .erb, .rhtml for ERB.
8
- # it will search in the folder the controller was defined in(NOT in path_to_templates, which is used for defined templates only).
9
- # so put each controller in a separate folder to avoid templates clash.
10
- #
11
- # if no file found a TemplateError will be raised.
12
- # if a block given it will use the the string returned by the block as template
13
- # and wont search for defined nor file templates.
14
- #
15
- # by default ERB engine will be used (@see engine).
16
- #
17
- # for layout it will take one given through options or one defined at class level.
18
- # if none given, it will render without layout.
19
- # to use a layout path_to_layouts should be defined at class level.
20
- #
21
- # by default it will use current instance as scope.
22
- # to render in a isolated scope, set it via :scope option
23
- #
24
- # to pass some local variables use :locals option
25
- #
26
- # @example render ./get.erb without layout
27
- # class Pages < RocketIO::Controller
28
- #
29
- # def get
30
- # render
31
- # end
32
- # end
33
- #
34
- # @example render ./get.erb with :master layout
35
- # class Pages < RocketIO::Controller
36
- # layout :master
37
- #
38
- # def get
39
- # render
40
- # end
41
- # end
42
- #
43
- # @example render ./get.erb with explicit :master layout
44
- # class Pages < RocketIO::Controller
45
- #
46
- # def get
47
- # render(layout: :master)
48
- # end
49
- # end
50
- #
51
- # @example render within isolated scope
52
- # class Pages < RocketIO::Controller
53
- #
54
- # def get
55
- # render(scope: Object.new)
56
- # end
57
- # end
58
- #
59
- # @example render with custom locals
60
- # class Pages < RocketIO::Controller
61
- #
62
- # def get
63
- # render(locals: {x: 'y'})
64
- # end
65
- # end
66
- #
67
- def render template = nil, opts = {}
68
- opts, template = template, nil if template.is_a?(::Hash)
69
- engine, engine_opts = resolve_engine(opts)
70
- template = block_given? ? yield : resolve_template(template, engine)
71
- scope = opts.fetch(:scope, self)
72
- locals = template_vars.merge(opts.fetch(:locals, RocketIO::EMPTY_HASH)).freeze
73
- layout = opts.fetch(:layout, self.layout)
74
- template = compile_template(template, engine, engine_opts).render(scope, locals)
75
- layout ? render_layout(layout, opts) {template} : template
76
- end
77
-
78
- # render a template that yields the given block.
79
- # that's it, a layout is a template that yields given string.
80
- #
81
- # layout can be specified two ways:
82
- # - as layout name
83
- # - as string
84
- #
85
- # if both given a ArgumentError error raised.
86
- # if :template option given, no layout lookups will occur.
87
- #
88
- # otherwise...
89
- # if no layout name given, it will use the one set at class level.
90
- # if no layout set at class level and no layout given, it will raise a RuntimeError.
91
- #
92
- # then it will search for given layout between defined ones.
93
- # if none found, it will search a file in `path_to_layouts` folder.
94
- # it will try each extension registered with effective engine.
95
- # if no file found it will raise a TemplateError.
96
- #
97
- # block is required and should return the string to be yielded.
98
- #
99
- def render_layout template = nil, opts = {}, &block
100
- template && opts[:template] && raise(ArgumentError, 'Both layout name and :template option given. Please use either one.')
101
-
102
- opts, template = template, nil if template.is_a?(::Hash)
103
- engine, engine_opts = resolve_engine(opts)
104
- template = if template
105
- resolve_layout(template, engine)
106
- else
107
- opts[:template] || begin
108
- self.layout || raise(RocketIO::LayoutError, 'No default layout set and no explicit layout given')
109
- resolve_layout(self.layout, engine)
110
- end
111
- end
112
-
113
- scope = opts.fetch(:scope, self)
114
- locals = template_vars.merge(opts.fetch(:locals, RocketIO::EMPTY_HASH)).freeze
115
- compile_template(template, engine, engine_opts)
116
- .render(scope, locals, &(block || RocketIO::EMPTY_STRING_PROC))
117
- end
118
-
119
- private
120
- def resolve_template template, engine
121
- template ||= requested_method
122
- return __send__(templates[template]) if templates[template]
123
- read_template(find_template(dirname, template, engine))
124
- end
125
-
126
- def resolve_layout layout, engine
127
- return __send__(layouts[layout]) if layouts[layout]
128
- read_template(find_template(dirname, layout, engine))
129
- end
130
-
131
- def resolve_engine opts = nil
132
- return engine_const(engine_class(opts[:engine])) if opts && opts[:engine]
133
- [engine_const(engine[0]), engine[1]]
134
- end
135
-
136
- def read_template file
137
- RocketIO::READ_TEMPLATES[[file, ::File.mtime(file).to_i]] ||= ::File.read(file)
138
- end
139
-
140
- def find_template path, template, engine
141
- RocketIO::FOUND_TEMPLATES[[path, template, engine]] ||= begin
142
- extensions = ::Tilt.default_mapping.extensions_for(engine)
143
- file = nil
144
- extensions.each do |ext|
145
- try = RocketIO::TEMPLATE_PATH_FORMAT % [path, template, ext]
146
- next unless File.exists?(try)
147
- file = try
148
- break
149
- end
150
- file || raise(RocketIO::TemplateError, '"%s" template not found in "%s".
151
- Tried extensions: %s' % [template, path, extensions.join(', ')])
152
- end
153
- end
154
-
155
- def compile_template template, engine, engine_opts = nil
156
- RocketIO::COMPILED_TEMPLATES[[template.hash, engine, engine_opts]] ||= begin
157
- engine.new(0, *engine_opts) { template }
158
- end
159
- end
160
- end
161
- end
162
-
163
- require 'rocketio/controller/render/engine'
164
- require 'rocketio/controller/render/layout'
165
- require 'rocketio/controller/render/layouts'
166
- require 'rocketio/controller/render/templates'
167
- require 'rocketio/controller/render/template_vars'
@@ -1,76 +0,0 @@
1
- module RocketIO
2
- class Controller
3
-
4
- # if no engine set, templates will be rendered using ERB engine.
5
- # any engine supported by [Tilt](github.com/rtomayko/tilt) can be used.
6
- # to set engine use symbolized constant name, e.g. :Slim, :Haml
7
- # engine name is Case Sensitive and there should be a Tilt::{ENGINE}Template class defined
8
- # e.g. `engine :Slim` will look for Tilt::SlimTemplate
9
- # and `engine RDiscount` will look for Tilt::RDiscountTemplate
10
- #
11
- # @note if a block given it will be executed at instance level
12
- # and result used for engine. To have any options passed at engine initialization
13
- # the block should return an array having engine as first element
14
- # and options as consequent elements.
15
- #
16
- # @note if given block returns no engine, inherited engine will be used
17
- #
18
- # @example use static engine
19
- # engine :Slim
20
- #
21
- # @example use static engine with options
22
- # engine :Slim, pretty_print: true
23
- #
24
- # @example use dynamically set engine
25
- # engine do
26
- # some_condition ? :SomeEngine : AnotherEngine
27
- # end
28
- #
29
- # @example use dynamically set engine with options
30
- # engine do
31
- # some_condition ? [:SomeEngine, :opt1, :opt2] : AnotherEngine
32
- # end
33
- #
34
- # @example Search will use ERB when requested by a bot and Slim otherwise
35
- #
36
- # class BaseController < RocketIO
37
- # engine :Slim
38
- # end
39
- #
40
- # class Search < BaseController
41
- # engine do
42
- # if request.user_agent =~ /i'm a bot/
43
- # # requested by a bot, using ERB
44
- # :ERB
45
- # end
46
- # # requested by a user, returning no engine for inherited engine to be used
47
- # end
48
- # end
49
- #
50
- # @param engine engine name.
51
- # @param *engine_options any arguments to be passed at engine initialization
52
- # @param block to be executed at instance level
53
- #
54
- def self.engine engine = nil, *engine_options, &block
55
- @__engine__ = block || [RocketIO.engine_class(engine), engine_options.freeze].freeze
56
- define_engine_methods
57
- end
58
-
59
- def self.define_engine_methods source = self
60
- return unless engine = source.instance_variable_get(:@__engine__)
61
- if Proc === engine
62
- selfengine = allocate.engine
63
- api.delete define_method(:__rocketio_engine__, &engine)
64
- api.delete define_method(:engine) {
65
- engine, *engine_options = __rocketio_engine__
66
- return selfengine unless engine
67
- [RocketIO.engine_class(engine), engine_options.freeze].freeze
68
- }
69
- else
70
- api.delete define_method(:engine) {engine}
71
- end
72
- end
73
-
74
- def engine; RocketIO::DEFAULT_ENGINE end
75
- end
76
- end
@@ -1,27 +0,0 @@
1
- module RocketIO
2
- class Controller
3
-
4
- # by default templates will be rendered without layout.
5
- # to make them render inside a layout use `layout :layout_name` at class level.
6
- # to use a layout it should be defined at first (@see define_layout)
7
- #
8
- # @note to disable layout set it to false: `layout false`
9
- #
10
- # @param layout name of a defined layout
11
- #
12
- def self.layout layout
13
- @__layout__ = layout
14
- define_layout_methods
15
- end
16
-
17
- def self.define_layout_methods source = self
18
- return unless source.instance_variables.include?(:@__layout__)
19
- layout = source.instance_variable_get(:@__layout__)
20
- api.delete define_method(:layout) {layout}
21
- end
22
-
23
- # by default no layout used, so this method returns nil.
24
- # controllers that uses a layout will override this method.
25
- def layout; end
26
- end
27
- end
@@ -1,85 +0,0 @@
1
- module RocketIO
2
- class Controller
3
-
4
- # if only name given it will search for a file with same name in controller's dirname.
5
- #
6
- # if file name differs from layout name pass it as :file option.
7
- # file path should be relative to controller's dirname.
8
- # also a block accepted for :file option. the block will be executed at controllers's instance level
9
- # and should return path to layout file.
10
- # file name should NOT include extension.
11
- #
12
- # if a block given NO file will be searched and returned value will be used as layout.
13
- #
14
- # @note files will be searched relative to controller's dirname,
15
- # that's it, the folder controller was defined in and operates from.
16
- #
17
- # @note when searching for file multiple extensions will be tried,
18
- # that's it, all extensions controller's engine actually supports.
19
- #
20
- # @note controllers that inherits named layouts will always search for files in own dirname.
21
- # controllers that inherits :file layouts will search files in the original controller's dirname.
22
- #
23
- # @example define :master layout.
24
- # ./master.erb file will be used
25
- #
26
- # define_layout :master
27
- #
28
- # @example define :master layout.
29
- # ../layouts/master.erb file will be used
30
- #
31
- # define_layout :master, file: '../layouts/master'
32
- #
33
- # @example define :master layout.
34
- # ./admin file to be used when user logged in and ./user otherwise
35
- #
36
- # define_layout :master, file: -> {user? ? 'admin' : 'user'}
37
- #
38
- # @example define :master layout using a block that returns the layout string.
39
- # no file will be used.
40
- #
41
- # define_layout(:master) do
42
- # layout = Layouts.find_by(id: params[:layout_id]) || halt(400, 'Template not found')
43
- # layout.source
44
- # end
45
- #
46
- # @param name
47
- # @param file
48
- # @param block
49
- #
50
- def self.define_layout name, file: nil, &block
51
- file && block && raise(::ArgumentError, 'both file and block given, please use either one')
52
- (@__layouts__ ||= {})[name.to_sym] = {block: block, root: dirname, file: file, name: name}.freeze
53
- define_layouts_methods
54
- end
55
-
56
- def self.define_layouts_methods source = self
57
- return unless source.instance_variables.include?(:@__layouts__)
58
- layouts = source.instance_variable_get(:@__layouts__).each_with_object(allocate.layouts.dup) do |(name,setup),o|
59
- o[name] = :"__#{name}_layout__"
60
- if setup[:block]
61
- # block given, do not search for file, use returned value instead
62
- api.delete define_method(o[name], &setup[:block])
63
- elsif setup[:file]
64
- # file given, search the file in original controller dirname
65
- meth_name = :"__#{name}_layout_file__"
66
- meth_proc = setup[:file].is_a?(::Proc) ? setup[:file] : -> {setup[:file]}
67
- api.delete define_method(meth_name, &meth_proc)
68
- api.delete define_method(o[name]) {
69
- engine, * = resolve_engine
70
- read_template(find_template(setup[:root], __send__(meth_name), engine))
71
- }
72
- else
73
- # only name given, search for a file with same name in controller's dirname
74
- api.delete define_method(o[name]) {
75
- engine, * = resolve_engine
76
- read_template(find_template(self.dirname, setup[:name], engine))
77
- }
78
- end
79
- end.freeze
80
- api.delete define_method(:layouts) {layouts}
81
- end
82
-
83
- def layouts; RocketIO::EMPTY_HASH end
84
- end
85
- end
@@ -1,34 +0,0 @@
1
- module RocketIO
2
- class Controller
3
-
4
- # define variables to be used on templates alongside provided locals.
5
- #
6
- # @param name
7
- # @param value
8
- #
9
- def self.define_template_var name, value = nil, &block
10
- value || block || raise(ArgumentError, 'A value or a block expected')
11
- (@__template_vars__ ||= {})[name.to_sym] = (block || value).freeze
12
- define_template_vars_methods
13
- end
14
-
15
- def self.define_template_vars_methods source = self
16
- return unless source.instance_variables.include?(:@__template_vars__)
17
- vars = source.instance_variable_get(:@__template_vars__).each_with_object(allocate.__template_vars__.dup) do |(name,value),o|
18
- o[name] = :"__#{name}_template_var__"
19
- if value.is_a?(Proc)
20
- api.delete define_method(o[name], &value)
21
- else
22
- api.delete define_method(o[name]) {value}
23
- end
24
- end.freeze
25
- api.delete define_method(:__template_vars__) {vars}
26
- end
27
-
28
- def __template_vars__; RocketIO::EMPTY_HASH end
29
-
30
- def template_vars
31
- __template_vars__.each_with_object({}) {|(k,v),o| o[k] = __send__(v)}
32
- end
33
- end
34
- end
@@ -1,83 +0,0 @@
1
- module RocketIO
2
- class Controller
3
-
4
- # if only name given it will search for a file with same name in controller's dirname
5
- #
6
- # if file name differs from template name pass it as :file option.
7
- # file path should be relative to controller's dirname.
8
- # also a block accepted for :file option. the block will be executed at controllers's instance level
9
- # and should return path to template file.
10
- # file name should NOT include extension.
11
- #
12
- # if a block given NO file will be searched and returned value will be used as template.
13
- #
14
- # @note files will be searched relative to controller's dirname,
15
- # that's it, the folder controller was defined in and operates from.
16
- #
17
- # @note when searching for file multiple extensions will be tried,
18
- # that's it, all extensions controller's engine actually supports.
19
- #
20
- # @note controllers that inherits named templates will always search for files in own dirname.
21
- # controllers that inherits :file templates will search files in the original controller's dirname.
22
- #
23
- # @example define :items template.
24
- # ./items.erb file will be used
25
- # define_template :items
26
- #
27
- # @example define :items template.
28
- # ../shared_templates/items.erb file will be used
29
- # define_template :items, file: '../shared_templates/items'
30
- #
31
- # @example define :items template.
32
- # ./admin-items.erb file to be used when user logged in and ./items.erb otherwise
33
- #
34
- # define_template :items, file: -> {user? ? 'admin-items' : 'items'}
35
- #
36
- # @example define :items template using a block that returns the template string.
37
- # no file will be used.
38
- #
39
- # define_template(:items) do
40
- # template = Templates.find_by(id: params[:template_id]) || halt(400, 'Template not found')
41
- # template.source
42
- # end
43
- #
44
- # @param name
45
- # @param file
46
- # @param block
47
- #
48
- def self.define_template name, file: nil, &block
49
- file && block && raise(ArgumentError, 'both file and block given, please use either one')
50
- (@__templates__ ||= {})[name.to_sym] = {block: block, root: dirname, file: file, name: name}.freeze
51
- define_templates_methods
52
- end
53
-
54
- def self.define_templates_methods source = self
55
- return unless source.instance_variables.include?(:@__templates__)
56
- templates = source.instance_variable_get(:@__templates__).each_with_object(allocate.templates.dup) do |(name,setup),o|
57
- o[name] = :"__#{name}_template__"
58
- if setup[:block]
59
- # block given, do not search for file, use returned value instead
60
- api.delete define_method(o[name], &setup[:block])
61
- elsif setup[:file]
62
- # file given, search the file in original controller dirname
63
- meth_name = :"__#{name}_template_file__"
64
- meth_proc = setup[:file].is_a?(Proc) ? setup[:file] : -> {setup[:file]}
65
- api.delete define_method(meth_name, &meth_proc)
66
- api.delete define_method(o[name]) {
67
- engine, * = resolve_engine
68
- read_template(find_template(setup[:root], __send__(meth_name), engine))
69
- }
70
- else
71
- # only name given, search for a file with same name in controller's dirname
72
- api.delete define_method(o[name]) {
73
- engine, * = resolve_engine
74
- read_template(find_template(self.dirname, setup[:name], engine))
75
- }
76
- end
77
- end.freeze
78
- api.delete define_method(:templates) {templates}
79
- end
80
-
81
- def templates; RocketIO::EMPTY_HASH end
82
- end
83
- end