rocketio 0.3.0 → 0.4.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.
@@ -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