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,49 @@
1
+ module Chanko
2
+ module Generators
3
+ class UnitGenerator < Rails::Generators::NamedBase
4
+ ASSETS_TYPES = %w[images javascripts stylesheets]
5
+
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ def create_unit_directory
9
+ empty_directory(directory)
10
+ end
11
+
12
+ def create_unit_file
13
+ template("unit.rb.erb", "#{directory}/#{file_name}.rb")
14
+ end
15
+
16
+ def create_views_directory
17
+ create_file("#{directory}/views/.gitkeep", "")
18
+ end
19
+
20
+ ASSETS_TYPES.each do |type|
21
+ define_method("create_#{type}_directory") do
22
+ create_file("#{directory}/#{type}/.gitkeep", "")
23
+ end
24
+ end
25
+
26
+ ASSETS_TYPES.each do |type|
27
+ define_method("create_#{type}_symlink") do
28
+ create_assets_symlink(type)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def create_assets_symlink(type)
35
+ from = "app/assets/#{type}/#{directory_name}/#{file_name}"
36
+ to = "../../../../#{directory}/#{type}"
37
+ create_link(from, to)
38
+ end
39
+
40
+ def directory
41
+ "#{Chanko::Config.units_directory_path}/#{file_name}"
42
+ end
43
+
44
+ def directory_name
45
+ Chanko::Config.units_directory_path.split("/").last
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+
3
+ module Chanko
4
+ describe Controller do
5
+ describe ".unit_action" do
6
+ let(:controller_class) do
7
+ Class.new(ActionController::Base) do
8
+ include Chanko::Controller
9
+ unit_action(:example_unit, :test)
10
+ unit_action(:example_unit, :foo, :bar)
11
+ unit_action(:example_unit, :error)
12
+ ext_action(:example_unit, :alias)
13
+
14
+ def head(code)
15
+ "Bad Request #{code}"
16
+ end
17
+ end
18
+ end
19
+
20
+ let(:controller) do
21
+ controller_class.new
22
+ end
23
+
24
+ it "defines an action to invoke unit function" do
25
+ controller.test.should == "test"
26
+ end
27
+
28
+ it "defines 2 actions at one line" do
29
+ controller.foo.should == "foo"
30
+ controller.bar.should == "bar"
31
+ end
32
+
33
+ it "is aliased with `ext_action`" do
34
+ controller.alias.should == "alias"
35
+ end
36
+
37
+ context "when invoke is fallen back" do
38
+ it "halts with 400 status code" do
39
+ controller.error.should == "Bad Request 400"
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,39 @@
1
+ require "spec_helper"
2
+
3
+ module Chanko
4
+ describe ExceptionHandler do
5
+ let(:sensitive_unit) do
6
+ Loader.load(:sensitive_unit)
7
+ end
8
+
9
+ let(:insensitive_unit) do
10
+ Loader.load(:insensitive_unit)
11
+ end
12
+
13
+ let(:error) do
14
+ Exception.new
15
+ end
16
+
17
+ context "when Config.raise_error is false" do
18
+ it "raises up no error" do
19
+ expect { described_class.handle(error, insensitive_unit) }.not_to raise_error
20
+ end
21
+ end
22
+
23
+ context "when Config.raise_error is true" do
24
+ before do
25
+ Config.raise_error = true
26
+ end
27
+
28
+ it "raises up error" do
29
+ expect { described_class.handle(error, insensitive_unit) }.to raise_error
30
+ end
31
+ end
32
+
33
+ context "when unit.raise_error is configured" do
34
+ it "raises up error" do
35
+ expect { described_class.handle(error, sensitive_unit) }.to raise_error
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,60 @@
1
+ require "spec_helper"
2
+
3
+ module Chanko
4
+ describe Function do
5
+ let(:unit) do
6
+ Loader.load(:example_unit)
7
+ end
8
+
9
+ let(:context) do
10
+ Class.new(ActionView::Base) do
11
+ include Chanko::Invoker
12
+
13
+ def current_unit
14
+ units.last
15
+ end
16
+
17
+ def units
18
+ @units ||= []
19
+ end
20
+
21
+ def path
22
+ view_paths.first.to_s
23
+ end
24
+ end.new
25
+ end
26
+
27
+ let(:context_without_view_paths) do
28
+ Class.new do
29
+ include Chanko::Invoker
30
+
31
+ def units
32
+ @units ||= []
33
+ end
34
+ end.new
35
+ end
36
+
37
+ let(:options) do
38
+ { :type => :plain }
39
+ end
40
+
41
+ describe ".invoke" do
42
+ it "invokes block with given context and stacked unit" do
43
+ described_class.new(unit, :label) { current_unit }.invoke(context, options).should == unit
44
+ end
45
+
46
+ context "when context is a view" do
47
+ it "invokes with unit's view path" do
48
+ described_class.new(unit, :label) { path }.invoke(context, options).should == unit.view_path
49
+ end
50
+ end
51
+
52
+ context "when context does not have view_paths" do
53
+ it "invokes successfully" do
54
+ described_class.new(unit, :label) { "test" }.
55
+ invoke(context_without_view_paths, options).should == "test"
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ module Chanko
4
+ describe Helper do
5
+ describe ".define" do
6
+ after do
7
+ described_class.class_eval do
8
+ remove_method :__example_unit_test rescue nil
9
+ end
10
+ end
11
+
12
+ let(:view) do
13
+ Class.new { include Chanko::Helper }.new
14
+ end
15
+
16
+ it "defines helper methods with special prefix" do
17
+ described_class.define(:example_unit) do
18
+ def test
19
+ "test"
20
+ end
21
+ end
22
+ view.__example_unit_test.should == "test"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,156 @@
1
+ require "spec_helper"
2
+
3
+ module Chanko
4
+ describe Invoker do
5
+ let(:view) do
6
+ Class.new(ActionView::Base) do
7
+ include Chanko::Invoker
8
+ include Chanko::Helper
9
+ include Chanko::UnitProxyProvider
10
+ end.new
11
+ end
12
+
13
+ let(:controller) do
14
+ Class.new(ActionController::Base) do
15
+ include Chanko::Invoker
16
+ include Chanko::Helper
17
+ include Chanko::UnitProxyProvider
18
+ end.new
19
+ end
20
+
21
+ describe "#invoke" do
22
+ it "invokes in the same context with receiver" do
23
+ view.invoke(:example_unit, :self, :type => :plain).should == view
24
+ end
25
+
26
+ it "invokes with locals option" do
27
+ view.invoke(:example_unit, :locals, :locals => { :key => "value" }, :type => :plain).
28
+ should == "value"
29
+ end
30
+
31
+ it "invokes with falsy locals" do
32
+ view.invoke(:example_unit, :falsy, :locals => { :key => nil }, :type => :plain).
33
+ should == true
34
+ end
35
+
36
+ it "invokes with shared method" do
37
+ view.invoke(:example_unit, :shared, :type => :plain).should == "shared args"
38
+ end
39
+
40
+ it "invokes with helper method in view context" do
41
+ view.invoke(:example_unit, :helper, :type => :plain).should == "helper"
42
+ end
43
+
44
+ context "when invoked in view" do
45
+ it "invokes with partial view" do
46
+ view.invoke(:example_unit, :render, :type => :plain).should == "test\n"
47
+ end
48
+ end
49
+
50
+ context "when invoked in controller" do
51
+ it "invokes with unit views path" do
52
+ controller.invoke(:example_unit, :render, :type => :plain).should == "test\n"
53
+ end
54
+ end
55
+
56
+ context "when short-hand style args is passed" do
57
+ it "recognizes args as locals option" do
58
+ view.invoke(:example_unit, :locals, :key => "value").should ==
59
+ '<div class="unit unit__example_unit unit__example_unit__locals">value</div>'
60
+ end
61
+ end
62
+
63
+ context "when type is not specified" do
64
+ it "invokes and returns result surrounded by div" do
65
+ view.invoke(:example_unit, :test).should ==
66
+ '<div class="unit unit__example_unit unit__example_unit__test">test</div>'
67
+ end
68
+ end
69
+
70
+ context "when Config.compatible_css_class is true" do
71
+ before do
72
+ Config.compatible_css_class = true
73
+ end
74
+
75
+ it "invokes and returns result surrounded by div" do
76
+ view.invoke(:example_unit, :test).should ==
77
+ '<div class="extension ext_example_unit ext_example_unit-test">test</div>'
78
+ end
79
+ end
80
+
81
+ context "when type is :plain" do
82
+ it "does not surround result with html element" do
83
+ view.invoke(:example_unit, :test, :type => :plain).should == "test"
84
+ end
85
+ end
86
+
87
+ context "when the result is blank" do
88
+ it "does not surround result with html element" do
89
+ view.invoke(:example_unit, :blank).should == " "
90
+ end
91
+ end
92
+
93
+ context "when type is :inline" do
94
+ it "invokes and returns result surrounded by span" do
95
+ view.invoke(:example_unit, :test, :type => :inline).should ==
96
+ '<span class="unit unit__example_unit unit__example_unit__test">test</span>'
97
+ end
98
+ end
99
+
100
+ context "when context is not a view" do
101
+ it "does not surround result with html tag" do
102
+ controller.invoke(:example_unit, :test).should == "test"
103
+ end
104
+ end
105
+
106
+ context "when run_default is called in function" do
107
+ it "invokes given block as a fallback" do
108
+ controller.invoke(:example_unit, :default) { "default" }.should == "default"
109
+ end
110
+ end
111
+
112
+ context "when run_default is called but no block given" do
113
+ it "invokes given block as a fallback" do
114
+ controller.invoke(:example_unit, :default).should == nil
115
+ end
116
+ end
117
+
118
+ context "when non-existent unit is specified" do
119
+ it "does nothing" do
120
+ view.invoke(:non_existent_unit, :test, :type => :plain).should == nil
121
+ end
122
+ end
123
+
124
+ context "when function is not found" do
125
+ it "runs default but not handled by ExceptionHandler" do
126
+ ExceptionHandler.should_not_receive(:handle)
127
+ view.invoke(:example_unit, :non_existent_function) { "default" }.should == "default"
128
+ end
129
+ end
130
+
131
+ context "when an error is raised in invoking" do
132
+ context "when block is given" do
133
+ context "when context is a view" do
134
+ it "captures given block as a fallback" do
135
+ view.should_receive(:capture).and_call_original
136
+ view.invoke(:example_unit, :error) { "error" }.should == "error"
137
+ end
138
+ end
139
+
140
+ context "when context is not a view" do
141
+ it "calls given block as a fallback" do
142
+ controller.should_not_receive(:capture)
143
+ controller.invoke(:example_unit, :error) { "error" }.should == "error"
144
+ end
145
+ end
146
+ end
147
+
148
+ context "when no block is given" do
149
+ it "rescues the error and does nothing" do
150
+ view.invoke(:example_unit, :error).should == nil
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+
3
+ module Chanko
4
+ describe Loader do
5
+ describe ".load" do
6
+ after do
7
+ described_class.cache.clear
8
+ end
9
+
10
+ context "when existent unit name is passed" do
11
+ it "loads unit in units directory and returns the Module" do
12
+ described_class.load(:example_unit).should == ExampleUnit
13
+ end
14
+ end
15
+
16
+ context "when non-existent unit name is passed" do
17
+ it "returns nil" do
18
+ described_class.load(:non_existent_unit).should == nil
19
+ end
20
+ end
21
+
22
+ context "when loader has ever loaded specified unit" do
23
+ it "load unit from cache" do
24
+ described_class.any_instance.should_receive(:load_from_file).and_call_original
25
+ described_class.load(:example_unit)
26
+ described_class.load(:example_unit)
27
+ end
28
+ end
29
+
30
+ context "when loader has ever loaded specified wrong unit" do
31
+ before do
32
+ described_class.cache.clear
33
+ end
34
+
35
+ it "load unit from cache" do
36
+ described_class.any_instance.should_receive(:load_from_file).and_call_original
37
+ described_class.load(:non_existent_unit)
38
+ described_class.load(:non_existent_unit)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,94 @@
1
+ require "spec_helper"
2
+ require "stringio"
3
+
4
+ module Chanko
5
+ describe Logger do
6
+ around do |example|
7
+ origin, Rails.logger = Rails.logger, ::Logger.new(io)
8
+ example.run
9
+ Rails.logger = origin
10
+ end
11
+
12
+ let(:io) do
13
+ StringIO.new
14
+ end
15
+
16
+ let(:log) do
17
+ io.string.rstrip
18
+ end
19
+
20
+ let(:exception) do
21
+ exception = Exception.new("error message")
22
+ exception.set_backtrace(20.times.map {|i| "test.rb:#{i + 1}:in `method#{i + 1}'" })
23
+ exception
24
+ end
25
+
26
+ let(:lines) do
27
+ <<-EOS.strip_heredoc.split("\n").map {|line| " #{line}" }
28
+ [Chanko] Exception - error message
29
+ [Chanko] test.rb:1:in `method1'
30
+ [Chanko] test.rb:2:in `method2'
31
+ [Chanko] test.rb:3:in `method3'
32
+ [Chanko] test.rb:4:in `method4'
33
+ [Chanko] test.rb:5:in `method5'
34
+ [Chanko] test.rb:6:in `method6'
35
+ [Chanko] test.rb:7:in `method7'
36
+ [Chanko] test.rb:8:in `method8'
37
+ [Chanko] test.rb:9:in `method9'
38
+ [Chanko] test.rb:10:in `method10'
39
+ EOS
40
+ end
41
+
42
+ context "when Config.enable_logger is true" do
43
+ before do
44
+ Config.enable_logger = true
45
+ end
46
+
47
+ context "when given Exception" do
48
+ it "parses and logs it" do
49
+ described_class.debug(exception)
50
+ log.should == lines.join("\n")
51
+ end
52
+
53
+ context "when Config.backtrace_limit is configured" do
54
+ before do
55
+ Config.backtrace_limit = 5
56
+ end
57
+
58
+ it "prints backtrace up to configured depth" do
59
+ described_class.debug(exception)
60
+ log.should == lines[0..5].join("\n")
61
+ end
62
+ end
63
+ end
64
+
65
+ context "when given String" do
66
+ it "adds prefix" do
67
+ described_class.debug("test")
68
+ log.should == " [Chanko] test"
69
+ end
70
+ end
71
+ end
72
+
73
+ context "when Config.enable_logger is false" do
74
+ before do
75
+ Config.enable_logger = false
76
+ end
77
+
78
+ it "logs nothing" do
79
+ described_class.debug("test")
80
+ log.should == ""
81
+ end
82
+ end
83
+
84
+ context "when Rails.logger is nil" do
85
+ before do
86
+ Rails.stub(:logger)
87
+ end
88
+
89
+ it "does notihng" do
90
+ expect { described_class.debug(exception) }.not_to raise_error(NoMethodError)
91
+ end
92
+ end
93
+ end
94
+ end