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,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