chanko 1.0.6 → 2.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.
- data/.gitignore +22 -0
- data/.travis.yml +5 -0
- data/Gemfile +26 -0
- data/MIT-LICENSE +22 -0
- data/README.md +168 -0
- data/Rakefile +12 -0
- data/chanko.gemspec +30 -0
- data/lib/chanko.rb +19 -0
- data/lib/chanko/active_if.rb +59 -0
- data/lib/chanko/config.rb +30 -0
- data/lib/chanko/controller.rb +31 -0
- data/lib/chanko/exception_handler.rb +10 -0
- data/lib/chanko/function.rb +85 -0
- data/lib/chanko/helper.rb +29 -0
- data/lib/chanko/invoker.rb +105 -0
- data/lib/chanko/invoker/function_finder.rb +42 -0
- data/lib/chanko/invoker/options.rb +64 -0
- data/lib/chanko/loader.rb +65 -0
- data/lib/chanko/logger.rb +67 -0
- data/lib/chanko/railtie.rb +11 -0
- data/lib/chanko/test.rb +44 -0
- data/lib/chanko/unit.rb +101 -0
- data/lib/chanko/unit/extender.rb +21 -0
- data/lib/chanko/unit/extender/active_record_class_methods.rb +57 -0
- data/lib/chanko/unit/extender/extension.rb +51 -0
- data/lib/chanko/unit/scope_finder.rb +41 -0
- data/lib/chanko/unit_proxy.rb +30 -0
- data/lib/chanko/unit_proxy_provider.rb +27 -0
- data/lib/chanko/version.rb +3 -0
- data/lib/generators/chanko/unit/templates/unit.rb.erb +84 -0
- data/lib/generators/chanko/unit/unit_generator.rb +49 -0
- data/spec/chanko/controller_spec.rb +44 -0
- data/spec/chanko/exception_handler_spec.rb +39 -0
- data/spec/chanko/function_spec.rb +60 -0
- data/spec/chanko/helper_spec.rb +26 -0
- data/spec/chanko/invoker_spec.rb +156 -0
- data/spec/chanko/loader_spec.rb +43 -0
- data/spec/chanko/logger_spec.rb +94 -0
- data/spec/chanko/test_spec.rb +28 -0
- data/spec/chanko/unit/extender_spec.rb +40 -0
- data/spec/chanko/unit/scope_finder_spec.rb +37 -0
- data/spec/chanko/unit_proxy_provider_spec.rb +68 -0
- data/spec/chanko/unit_proxy_spec.rb +23 -0
- data/spec/chanko/unit_spec.rb +181 -0
- data/spec/controllers/application_controller_spec.rb +15 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +14 -0
- data/spec/dummy/app/assets/stylesheets/main.scss +21 -0
- data/spec/dummy/app/assets/stylesheets/reset.scss +14 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/entries_controller.rb +33 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/entry.rb +3 -0
- data/spec/dummy/app/units/entry_deletion/entry_deletion.rb +37 -0
- data/spec/dummy/app/units/entry_deletion/views/_delete_link.html.slim +1 -0
- data/spec/dummy/app/views/entries/edit.html.slim +14 -0
- data/spec/dummy/app/views/entries/index.html.slim +5 -0
- data/spec/dummy/app/views/entries/show.html.slim +8 -0
- data/spec/dummy/app/views/layouts/application.html.slim +16 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +68 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +5 -0
- data/spec/dummy/db/migrate/20130127170331_create_entries.rb +11 -0
- data/spec/dummy/db/schema.rb +24 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/fixtures/units/example_unit/example_unit.rb +77 -0
- data/spec/fixtures/units/example_unit/views/_test.html.erb +1 -0
- data/spec/fixtures/units/inactive_unit/inactive_unit.rb +11 -0
- data/spec/fixtures/units/insensitive_unit/insensitive_unit.rb +3 -0
- data/spec/fixtures/units/sensitive_unit/sensitive_unit.rb +4 -0
- data/spec/spec_helper.rb +27 -0
- metadata +339 -170
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Chanko
|
|
2
|
+
class Function
|
|
3
|
+
attr_reader :block, :unit, :label
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
def units
|
|
7
|
+
@units ||= []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def current_unit
|
|
11
|
+
units.last
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(unit, label, &block)
|
|
16
|
+
@unit = unit
|
|
17
|
+
@label = label
|
|
18
|
+
@block = block
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def invoke(context, options = {})
|
|
22
|
+
with_unit_stack(context) do
|
|
23
|
+
with_unit_view_path(context) do
|
|
24
|
+
capture_exception(context) do
|
|
25
|
+
result = context.instance_eval(&block)
|
|
26
|
+
result = decorate(result, context, options[:type]) if context.view? && result.present?
|
|
27
|
+
result
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def css_classes
|
|
34
|
+
if Config.compatible_css_class
|
|
35
|
+
%W[
|
|
36
|
+
extension
|
|
37
|
+
ext_#{unit.unit_name}
|
|
38
|
+
ext_#{unit.unit_name}-#{label}
|
|
39
|
+
]
|
|
40
|
+
else
|
|
41
|
+
%W[
|
|
42
|
+
unit
|
|
43
|
+
unit__#{unit.unit_name}
|
|
44
|
+
unit__#{unit.unit_name}__#{label}
|
|
45
|
+
]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def with_unit_stack(context)
|
|
52
|
+
context.units << @unit
|
|
53
|
+
self.class.units << @unit
|
|
54
|
+
yield
|
|
55
|
+
ensure
|
|
56
|
+
self.class.units.pop
|
|
57
|
+
context.units.pop
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def with_unit_view_path(context)
|
|
61
|
+
context.view_paths.unshift unit.resolver if context.respond_to?(:view_paths)
|
|
62
|
+
yield
|
|
63
|
+
ensure
|
|
64
|
+
context.view_paths.paths.shift if context.respond_to?(:view_paths)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def capture_exception(context)
|
|
68
|
+
yield
|
|
69
|
+
rescue Exception => exception
|
|
70
|
+
ExceptionHandler.handle(exception, unit)
|
|
71
|
+
context.run_default
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def decorate(str, context, type)
|
|
75
|
+
case type
|
|
76
|
+
when :plain
|
|
77
|
+
str
|
|
78
|
+
when :inline
|
|
79
|
+
context.content_tag(:span, str, :class => css_classes)
|
|
80
|
+
else
|
|
81
|
+
context.content_tag(:div, str, :class => css_classes)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Chanko
|
|
2
|
+
module Helper
|
|
3
|
+
class << self
|
|
4
|
+
def define(unit_name, &block)
|
|
5
|
+
prefix = UnitProxy.generate_prefix(unit_name)
|
|
6
|
+
define_methods_with_prefix(prefix, &block)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def define_methods_with_prefix(prefix, &block)
|
|
10
|
+
define_methods(&block).each do |name|
|
|
11
|
+
change_method_name(name, "#{prefix}#{name}")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def define_methods(&block)
|
|
16
|
+
before = instance_methods(false)
|
|
17
|
+
self.class_eval(&block)
|
|
18
|
+
instance_methods(false) - before
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def change_method_name(from, to)
|
|
22
|
+
class_eval do
|
|
23
|
+
alias_method to, from
|
|
24
|
+
remove_method from
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
require "chanko/invoker/options"
|
|
2
|
+
require "chanko/invoker/function_finder"
|
|
3
|
+
|
|
4
|
+
module Chanko
|
|
5
|
+
module Invoker
|
|
6
|
+
def invoke(*args, &block)
|
|
7
|
+
options = Options.new(*args)
|
|
8
|
+
__with_default_stack(block) do
|
|
9
|
+
__with_unit_locals_stack(options.locals) do
|
|
10
|
+
if function = FunctionFinder.find(self, options)
|
|
11
|
+
function.invoke(self, options.invoke_options)
|
|
12
|
+
else
|
|
13
|
+
run_default
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def units
|
|
20
|
+
@units ||= []
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def view?
|
|
24
|
+
is_a?(ActionView::Base)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def run_default
|
|
28
|
+
__invoke_default_block if __has_default_block?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def method_missing(method_name, *args, &block)
|
|
34
|
+
if shared_method = __find_shared_method(method_name)
|
|
35
|
+
instance_exec(*args, &shared_method)
|
|
36
|
+
elsif args.empty? && __find_unit_local(method_name)
|
|
37
|
+
__fetch_unit_local(method_name)
|
|
38
|
+
else
|
|
39
|
+
super
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def __find_unit_local(method_name)
|
|
44
|
+
__current_unit_locals.has_key?(method_name)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def __fetch_unit_local(method_name)
|
|
48
|
+
__current_unit_locals[method_name]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def __current_unit_locals
|
|
52
|
+
__unit_locals_stack.last || {}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def __unit_locals_stack
|
|
56
|
+
@__unit_locals_stack ||= []
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def __find_shared_method(method_name)
|
|
60
|
+
__current_shared_methods[method_name]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def __current_shared_methods
|
|
64
|
+
__current_unit.try(:shared_methods) || {}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def __current_unit
|
|
68
|
+
units.last
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def __defaults_stack
|
|
72
|
+
@__defaults_stack ||= []
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def __default_block
|
|
76
|
+
__defaults_stack.last
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def __has_default_block?
|
|
80
|
+
!!__default_block
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def __invoke_default_block
|
|
84
|
+
if view?
|
|
85
|
+
capture(&__default_block)
|
|
86
|
+
else
|
|
87
|
+
instance_exec(&__default_block)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def __with_default_stack(default)
|
|
92
|
+
__defaults_stack << default
|
|
93
|
+
yield
|
|
94
|
+
ensure
|
|
95
|
+
__defaults_stack.pop
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def __with_unit_locals_stack(locals)
|
|
99
|
+
__unit_locals_stack << locals
|
|
100
|
+
yield
|
|
101
|
+
ensure
|
|
102
|
+
__unit_locals_stack.pop
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Chanko
|
|
2
|
+
module Invoker
|
|
3
|
+
class FunctionFinder
|
|
4
|
+
def self.find(context, options)
|
|
5
|
+
new(context, options).find
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
attr_reader :context, :options
|
|
9
|
+
|
|
10
|
+
delegate :active_if_options, :as, :label, :unit_name, :to => :options
|
|
11
|
+
|
|
12
|
+
def initialize(context, options)
|
|
13
|
+
@context = context
|
|
14
|
+
@options = options
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def find
|
|
18
|
+
active? && find_function
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def scope
|
|
22
|
+
as || context.class
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def unit
|
|
26
|
+
Loader.load(unit_name)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def find_function
|
|
30
|
+
unit.find_function(scope, label)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def active?
|
|
34
|
+
if unit
|
|
35
|
+
unit.active?(context, active_if_options)
|
|
36
|
+
else
|
|
37
|
+
false
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Chanko
|
|
2
|
+
module Invoker
|
|
3
|
+
class Options
|
|
4
|
+
CANDIDATES = {
|
|
5
|
+
:active_if_options => true,
|
|
6
|
+
:as => true,
|
|
7
|
+
:capture => true,
|
|
8
|
+
:locals => true,
|
|
9
|
+
:type => true,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def initialize(*args)
|
|
13
|
+
@raw_options = args.extract_options!
|
|
14
|
+
@args = args
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def unit_name
|
|
18
|
+
@args[0]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def label
|
|
22
|
+
@args[1]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def locals
|
|
26
|
+
(options[:locals] || {}).symbolize_keys
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def active_if_options
|
|
30
|
+
options[:active_if_options] || {}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def as
|
|
34
|
+
options[:as]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def capture
|
|
38
|
+
options.has_key?(:capture) ? capture[:capture] : true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def type
|
|
42
|
+
options[:type]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def invoke_options
|
|
46
|
+
{ :capture => capture, :type => type }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def options
|
|
50
|
+
@options ||= begin
|
|
51
|
+
if short_hand_options?
|
|
52
|
+
{ :locals => @raw_options }
|
|
53
|
+
else
|
|
54
|
+
@raw_options
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def short_hand_options?
|
|
60
|
+
@raw_options.any? && @raw_options.keys.all? {|key| !CANDIDATES[key] }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require "pathname"
|
|
2
|
+
|
|
3
|
+
module Chanko
|
|
4
|
+
class Loader
|
|
5
|
+
class << self
|
|
6
|
+
def load(unit_name)
|
|
7
|
+
new(unit_name).load
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def cache
|
|
11
|
+
@cache ||= {}
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(name)
|
|
16
|
+
@name = name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def load
|
|
20
|
+
if loaded?
|
|
21
|
+
load_from_cache
|
|
22
|
+
else
|
|
23
|
+
load_from_file
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def loaded?
|
|
28
|
+
cache[@name] != nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def load_from_cache
|
|
32
|
+
cache[@name]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def load_from_file
|
|
36
|
+
add_autoload_path
|
|
37
|
+
cache[@name] = constantize
|
|
38
|
+
rescue Exception => exception
|
|
39
|
+
ExceptionHandler.handle(exception)
|
|
40
|
+
cache[@name] = false
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_autoload_path
|
|
45
|
+
ActiveSupport::Dependencies.autoload_paths << autoload_path
|
|
46
|
+
ActiveSupport::Dependencies.autoload_paths.uniq!
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def autoload_path
|
|
50
|
+
Rails.root.join("#{directory_path}/#@name").to_s
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def directory_path
|
|
54
|
+
Config.units_directory_path
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def constantize
|
|
58
|
+
@name.to_s.camelize.constantize
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def cache
|
|
62
|
+
self.class.cache
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module Chanko
|
|
2
|
+
module Logger
|
|
3
|
+
|
|
4
|
+
class << self
|
|
5
|
+
::Logger::Severity.constants.each do |level|
|
|
6
|
+
method_name = level.downcase
|
|
7
|
+
define_method(method_name) do |message|
|
|
8
|
+
logger.try(method_name, decorate(message)) if Config.enable_logger
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def decorate(message)
|
|
13
|
+
Message.new(message).to_s
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def logger
|
|
17
|
+
Rails.logger
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class Message
|
|
22
|
+
PREFIX = " [Chanko]"
|
|
23
|
+
|
|
24
|
+
def initialize(object)
|
|
25
|
+
@object = object
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_s
|
|
29
|
+
prefix(content)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def prefix(str)
|
|
33
|
+
str.split("\n").map {|line| "#{PREFIX} #{line}" }.join("\n")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def content
|
|
37
|
+
if @object.is_a?(Exception)
|
|
38
|
+
"#{klass}#{body}#{backtrace}"
|
|
39
|
+
else
|
|
40
|
+
@object.to_s
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def body
|
|
45
|
+
unless @object.message.empty?
|
|
46
|
+
" - #@object"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def klass
|
|
51
|
+
@object.class
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def backtrace
|
|
55
|
+
if has_backtrace?
|
|
56
|
+
lines = @object.backtrace[0...Config.backtrace_limit]
|
|
57
|
+
str = lines.map {|line| " #{line}" }.join("\n")
|
|
58
|
+
"\n#{str}"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def has_backtrace?
|
|
63
|
+
@object.backtrace
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|