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.
Files changed (95) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +5 -0
  3. data/Gemfile +26 -0
  4. data/MIT-LICENSE +22 -0
  5. data/README.md +168 -0
  6. data/Rakefile +12 -0
  7. data/chanko.gemspec +30 -0
  8. data/lib/chanko.rb +19 -0
  9. data/lib/chanko/active_if.rb +59 -0
  10. data/lib/chanko/config.rb +30 -0
  11. data/lib/chanko/controller.rb +31 -0
  12. data/lib/chanko/exception_handler.rb +10 -0
  13. data/lib/chanko/function.rb +85 -0
  14. data/lib/chanko/helper.rb +29 -0
  15. data/lib/chanko/invoker.rb +105 -0
  16. data/lib/chanko/invoker/function_finder.rb +42 -0
  17. data/lib/chanko/invoker/options.rb +64 -0
  18. data/lib/chanko/loader.rb +65 -0
  19. data/lib/chanko/logger.rb +67 -0
  20. data/lib/chanko/railtie.rb +11 -0
  21. data/lib/chanko/test.rb +44 -0
  22. data/lib/chanko/unit.rb +101 -0
  23. data/lib/chanko/unit/extender.rb +21 -0
  24. data/lib/chanko/unit/extender/active_record_class_methods.rb +57 -0
  25. data/lib/chanko/unit/extender/extension.rb +51 -0
  26. data/lib/chanko/unit/scope_finder.rb +41 -0
  27. data/lib/chanko/unit_proxy.rb +30 -0
  28. data/lib/chanko/unit_proxy_provider.rb +27 -0
  29. data/lib/chanko/version.rb +3 -0
  30. data/lib/generators/chanko/unit/templates/unit.rb.erb +84 -0
  31. data/lib/generators/chanko/unit/unit_generator.rb +49 -0
  32. data/spec/chanko/controller_spec.rb +44 -0
  33. data/spec/chanko/exception_handler_spec.rb +39 -0
  34. data/spec/chanko/function_spec.rb +60 -0
  35. data/spec/chanko/helper_spec.rb +26 -0
  36. data/spec/chanko/invoker_spec.rb +156 -0
  37. data/spec/chanko/loader_spec.rb +43 -0
  38. data/spec/chanko/logger_spec.rb +94 -0
  39. data/spec/chanko/test_spec.rb +28 -0
  40. data/spec/chanko/unit/extender_spec.rb +40 -0
  41. data/spec/chanko/unit/scope_finder_spec.rb +37 -0
  42. data/spec/chanko/unit_proxy_provider_spec.rb +68 -0
  43. data/spec/chanko/unit_proxy_spec.rb +23 -0
  44. data/spec/chanko/unit_spec.rb +181 -0
  45. data/spec/controllers/application_controller_spec.rb +15 -0
  46. data/spec/dummy/README.rdoc +261 -0
  47. data/spec/dummy/Rakefile +7 -0
  48. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  49. data/spec/dummy/app/assets/stylesheets/application.css +14 -0
  50. data/spec/dummy/app/assets/stylesheets/main.scss +21 -0
  51. data/spec/dummy/app/assets/stylesheets/reset.scss +14 -0
  52. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  53. data/spec/dummy/app/controllers/entries_controller.rb +33 -0
  54. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  55. data/spec/dummy/app/mailers/.gitkeep +0 -0
  56. data/spec/dummy/app/models/.gitkeep +0 -0
  57. data/spec/dummy/app/models/entry.rb +3 -0
  58. data/spec/dummy/app/units/entry_deletion/entry_deletion.rb +37 -0
  59. data/spec/dummy/app/units/entry_deletion/views/_delete_link.html.slim +1 -0
  60. data/spec/dummy/app/views/entries/edit.html.slim +14 -0
  61. data/spec/dummy/app/views/entries/index.html.slim +5 -0
  62. data/spec/dummy/app/views/entries/show.html.slim +8 -0
  63. data/spec/dummy/app/views/layouts/application.html.slim +16 -0
  64. data/spec/dummy/config.ru +4 -0
  65. data/spec/dummy/config/application.rb +68 -0
  66. data/spec/dummy/config/boot.rb +10 -0
  67. data/spec/dummy/config/database.yml +25 -0
  68. data/spec/dummy/config/environment.rb +5 -0
  69. data/spec/dummy/config/environments/development.rb +37 -0
  70. data/spec/dummy/config/environments/production.rb +67 -0
  71. data/spec/dummy/config/environments/test.rb +37 -0
  72. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  73. data/spec/dummy/config/initializers/inflections.rb +15 -0
  74. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  75. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  76. data/spec/dummy/config/initializers/session_store.rb +8 -0
  77. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  78. data/spec/dummy/config/locales/en.yml +5 -0
  79. data/spec/dummy/config/routes.rb +5 -0
  80. data/spec/dummy/db/migrate/20130127170331_create_entries.rb +11 -0
  81. data/spec/dummy/db/schema.rb +24 -0
  82. data/spec/dummy/lib/assets/.gitkeep +0 -0
  83. data/spec/dummy/log/.gitkeep +0 -0
  84. data/spec/dummy/public/404.html +26 -0
  85. data/spec/dummy/public/422.html +26 -0
  86. data/spec/dummy/public/500.html +25 -0
  87. data/spec/dummy/public/favicon.ico +0 -0
  88. data/spec/dummy/script/rails +6 -0
  89. data/spec/fixtures/units/example_unit/example_unit.rb +77 -0
  90. data/spec/fixtures/units/example_unit/views/_test.html.erb +1 -0
  91. data/spec/fixtures/units/inactive_unit/inactive_unit.rb +11 -0
  92. data/spec/fixtures/units/insensitive_unit/insensitive_unit.rb +3 -0
  93. data/spec/fixtures/units/sensitive_unit/sensitive_unit.rb +4 -0
  94. data/spec/spec_helper.rb +27 -0
  95. metadata +339 -170
@@ -0,0 +1,11 @@
1
+ module Chanko
2
+ class Railtie < Rails::Railtie
3
+ initializer "chanko" do |app|
4
+ ::ActionView::Base.send(:include, Helper, Invoker, UnitProxyProvider)
5
+ ::ActionController::Base.send(:include, Controller, Invoker, UnitProxyProvider)
6
+ ::ActiveRecord::Base.send(:include, UnitProxyProvider)
7
+ ::ActiveRecord::Relation.send(:include, UnitProxyProvider)
8
+ ::ActiveRecord::Associations::CollectionAssociation.send(:include, UnitProxyProvider)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,44 @@
1
+ module Chanko
2
+ module Test
3
+ class << self
4
+ def activations
5
+ @activations ||= {}
6
+ end
7
+
8
+ def included(base)
9
+ base.send :include, UnitProxyProvider
10
+ end
11
+ end
12
+
13
+ def enable_unit(unit_name)
14
+ Test.activations[unit_name] = true
15
+ end
16
+ alias_method :enable_ext, :enable_unit
17
+
18
+ def disable_unit(unit_name)
19
+ Test.activations[unit_name] = false
20
+ end
21
+ alias_method :disable_ext, :disable_unit
22
+ end
23
+
24
+ module Unit
25
+ module ClassMethods
26
+ def active_with_activations?(*args)
27
+ case Test.activations[unit_name]
28
+ when true
29
+ true
30
+ when false
31
+ false
32
+ else
33
+ active_without_activations?(*args)
34
+ end
35
+ end
36
+ alias_method_chain :active?, :activations
37
+ end
38
+ end
39
+ end
40
+
41
+ RSpec.configure do |config|
42
+ config.include Chanko::Test
43
+ config.after { Chanko::Test.activations.clear }
44
+ end
@@ -0,0 +1,101 @@
1
+ require "chanko/unit/extender"
2
+ require "chanko/unit/scope_finder"
3
+
4
+ module Chanko
5
+ module Unit
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ active_if { true }
10
+ end
11
+
12
+ module ClassMethods
13
+ attr_accessor :current_scope
14
+
15
+ def scope(identifier)
16
+ self.current_scope = ScopeFinder.find(identifier)
17
+ scopes[current_scope] ||= {}
18
+ yield
19
+ ensure
20
+ self.current_scope = nil
21
+ end
22
+
23
+ def function(label, &block)
24
+ functions[label] = Function.new(self, label, &block)
25
+ end
26
+ alias_method :callback, :function
27
+
28
+ def shared(label, &block)
29
+ shared_methods[label] = block
30
+ end
31
+
32
+ def helpers(&block)
33
+ Helper.define(unit_name, &block)
34
+ end
35
+
36
+ def models(&block)
37
+ extender.instance_eval(&block)
38
+ end
39
+
40
+ def active_if(*conditions, &block)
41
+ @active_if = ActiveIf.new(*conditions, &block)
42
+ end
43
+
44
+ def active?(context, options = {})
45
+ @active_if.active?(context, options.merge(:unit => self))
46
+ end
47
+
48
+ def any(*labels)
49
+ ActiveIf::Any.new(*labels)
50
+ end
51
+
52
+ def raise_error
53
+ @raise_error = true
54
+ end
55
+ alias_method :propagates_errors, :raise_error
56
+
57
+ def raise_error?
58
+ @raise_error
59
+ end
60
+
61
+ def unit_name
62
+ @unit_name ||= name.underscore.to_sym
63
+ end
64
+
65
+ def to_prefix
66
+ UnitProxy.generate_prefix(unit_name)
67
+ end
68
+
69
+ def view_path
70
+ "#{Config.units_directory_path}/#{unit_name}/views"
71
+ end
72
+
73
+ def find_function(identifier, label)
74
+ scope = ScopeFinder.find(identifier)
75
+ target = scope.ancestors.find {|klass| scopes[klass] }
76
+ functions = scopes[target]
77
+ functions[label] if functions
78
+ end
79
+
80
+ def functions
81
+ scopes[current_scope]
82
+ end
83
+
84
+ def scopes
85
+ @scopes ||= {}
86
+ end
87
+
88
+ def shared_methods
89
+ @shared_methods ||= {}
90
+ end
91
+
92
+ def resolver
93
+ @resolver ||= Config.resolver.new(view_path)
94
+ end
95
+
96
+ def extender
97
+ @extender ||= Extender.new(to_prefix)
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,21 @@
1
+ require "chanko/unit/extender/active_record_class_methods"
2
+ require "chanko/unit/extender/extension"
3
+
4
+ module Chanko
5
+ module Unit
6
+ class Extender
7
+ def initialize(prefix = nil)
8
+ @prefix = prefix
9
+ end
10
+
11
+ def expand(mod, &block)
12
+ mod = mod.to_s.camelize.constantize unless mod.is_a?(Module)
13
+ extension = Extension.new(mod, @prefix, &block)
14
+ mod.class_eval do
15
+ include extension.instance_methods_module
16
+ extend extension.class_methods_module
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,57 @@
1
+ module Chanko
2
+ module Unit
3
+ class Extender
4
+ module ActiveRecordClassMethods
5
+ delegate(
6
+ :apply_modules,
7
+ :arel,
8
+ :array_of_strings?,
9
+ :build_arel,
10
+ :build_joins,
11
+ :build_select,
12
+ :build_where,
13
+ :create_with,
14
+ :custom_join_sql,
15
+ :eager_load,
16
+ :extending,
17
+ :from,
18
+ :group,
19
+ :having,
20
+ :includes,
21
+ :joins,
22
+ :limit,
23
+ :lock,
24
+ :offset,
25
+ :order,
26
+ :preload,
27
+ :readonly,
28
+ :reorder,
29
+ :reverse_order,
30
+ :reverse_sql_order,
31
+ :scope,
32
+ :select,
33
+ :where,
34
+ :to => :@mod
35
+ )
36
+
37
+ %w[belongs_to has_many has_one].each do |method_name|
38
+ class_eval <<-EOS
39
+ def #{method_name}(*args, &block)
40
+ label = args.shift.to_s
41
+ name = @prefix + label
42
+ options = args.extract_options!
43
+ options = options.reverse_merge(:class_name => label.singularize.camelize)
44
+ args << options
45
+ @mod.#{method_name}(name.to_sym, *args, &block)
46
+ end
47
+ EOS
48
+ end
49
+
50
+ def scope(*args, &block)
51
+ name = @prefix + args.shift.to_s
52
+ @mod.scope(name, *args)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,51 @@
1
+ module Chanko
2
+ module Unit
3
+ class Extender
4
+ class Extension < Module
5
+ include ActiveRecordClassMethods
6
+
7
+ def initialize(mod, prefix = nil, &block)
8
+ @mod = mod
9
+ @prefix = prefix
10
+ @block = block
11
+ define_methods_with_prefix(instance_methods_module, &block)
12
+ end
13
+
14
+ def class_methods(&block)
15
+ define_methods_with_prefix(class_methods_module, &block)
16
+ end
17
+
18
+ def instance_methods_module
19
+ self
20
+ end
21
+
22
+ def class_methods_module
23
+ @class_methods_module ||= Module.new
24
+ end
25
+
26
+ private
27
+
28
+ def define_methods_with_prefix(container, &block)
29
+ define_methods(container, &block).each do |added_method_name|
30
+ change_method_name_with_prefix(container, added_method_name) if @prefix.present?
31
+ end
32
+ end
33
+
34
+ def define_methods(container, &block)
35
+ before = container.instance_methods(false)
36
+ container.class_eval(&block)
37
+ container.instance_methods(false) - before
38
+ end
39
+
40
+ def change_method_name_with_prefix(container, method_name)
41
+ from = method_name
42
+ to = "#@prefix#{method_name}"
43
+ container.class_eval do
44
+ alias_method to, from
45
+ remove_method from
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,41 @@
1
+ module Chanko
2
+ module Unit
3
+ class ScopeFinder
4
+ LABEL_SCOPE_MAP = {
5
+ :controller => ActionController::Base,
6
+ :model => ActiveRecord::Base,
7
+ :view => ActionView::Base,
8
+ }
9
+
10
+ def self.find(*args)
11
+ new(*args).find
12
+ end
13
+
14
+ def initialize(identifier)
15
+ @identifier = identifier
16
+ end
17
+
18
+ def find
19
+ case
20
+ when class?
21
+ @identifier
22
+ when label
23
+ label
24
+ else
25
+ @identifier.to_s.constantize
26
+ end
27
+ rescue NameError
28
+ end
29
+
30
+ private
31
+
32
+ def class?
33
+ @identifier.is_a?(Class)
34
+ end
35
+
36
+ def label
37
+ LABEL_SCOPE_MAP[@identifier]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,30 @@
1
+ require "delegate"
2
+
3
+ module Chanko
4
+ class UnitProxy
5
+ attr_reader :unit
6
+
7
+ def self.generate_prefix(unit_name)
8
+ "__#{unit_name}_"
9
+ end
10
+
11
+ def initialize(unit, context)
12
+ @unit = unit
13
+ @context = context
14
+ end
15
+
16
+ def active?(options = {})
17
+ @unit.active?(@context, options)
18
+ end
19
+
20
+ private
21
+
22
+ def prefix
23
+ self.class.generate_prefix(@unit.unit_name)
24
+ end
25
+
26
+ def method_missing(method_name, *args, &block)
27
+ @context.send("#{prefix}#{method_name}", *args, &block)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ module Chanko
2
+ module UnitProxyProvider
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ extend UnitProxyProvider
7
+ end
8
+
9
+ # Define #unit method in this class when #unit is called in first time.
10
+ # Change Config.proxy_method_name if you want to change this method name.
11
+ def method_missing(method_name, *args, &block)
12
+ if Array.wrap(Config.proxy_method_name).include?(method_name)
13
+ UnitProxyProvider.class_eval do
14
+ define_method(method_name) do |*_args|
15
+ name = _args.first || Function.current_unit.try(:unit_name)
16
+ if name && unit = Loader.load(name)
17
+ UnitProxy.new(unit, self)
18
+ end
19
+ end
20
+ end
21
+ send(method_name, args.first)
22
+ else
23
+ super
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module Chanko
2
+ VERSION = "2.0.0"
3
+ end
@@ -0,0 +1,84 @@
1
+ module <%= class_name %>
2
+ include Chanko::Unit
3
+
4
+ # ## active_if
5
+ # This block is used to decide if this unit is active or not.
6
+ # `context` is the receiver object of `invoke`.
7
+ # `options` is passed via `invoke(:foo, :bar, :active_if_options => { ... })`.
8
+ # By default, this is set as `active_if { true }`.
9
+ #
10
+ # ```
11
+ # active_if do |context, options|
12
+ # true
13
+ # end
14
+ # ```
15
+
16
+ # ## raise_error
17
+ # `raise_error` is used to force an unit to raise up errors occured in invoking.
18
+ # You can force to raise up errors also by `Config.raise_error`.
19
+ #
20
+ # ```
21
+ # raise_error
22
+ # ```
23
+
24
+ # ## function
25
+ # In controller or view context, you can call functions defined by `function`
26
+ # via `invoke(:<%= file_name %>, :function_name)`.
27
+ #
28
+ # ```
29
+ # scope(:controller) do
30
+ # function(:function_name) do
31
+ # "Chanko!"
32
+ # end
33
+ # end
34
+ # ```
35
+
36
+ # ## render
37
+ # In addition, the view path "<%= "#{directory}/views" %>" is added into view_paths.
38
+ # So you can render <%= "#{directory}/views/_example.html.erb" %> in invoking.
39
+ #
40
+ # ```
41
+ # scope(:view) do
42
+ # function(:function_name) do
43
+ # render "/example", :foo => "bar"
44
+ # end
45
+ # end
46
+ # ```
47
+
48
+ # ## models
49
+ # In models block, you can expand model features by `expand` method.
50
+ # The expanded methods are available via unit proxy like `User.unit.active`,
51
+ # and `User.find(params[:id]).unit.active?`, and so on.
52
+ #
53
+ # ```
54
+ # models do
55
+ # expand(:User) do
56
+ # scope :active, lambda { where(:deleted_at => nil) }
57
+ #
58
+ # def active?
59
+ # deleted_at.nil?
60
+ # end
61
+ # end
62
+ # end
63
+ # ```
64
+
65
+ # ## shared
66
+ # You can call methods defined by `shared` in invoking.
67
+ #
68
+ # ```
69
+ # shared(:hello) do |world|
70
+ # "Hello, #{world}"
71
+ # end
72
+ # ```
73
+
74
+ # ## helpers
75
+ # You can call helpers in view via unit proxy like `unit.helper_method`
76
+ #
77
+ # ```
78
+ # helpers do
79
+ # def helper_method
80
+ # "helper method"
81
+ # end
82
+ # end
83
+ # ```
84
+ end