chanko 1.0.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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