rpv_core 0.2

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 (54) hide show
  1. data/Rakefile +3 -0
  2. data/bin/rpv +68 -0
  3. data/lib/rpv/autoload.rb +36 -0
  4. data/lib/rpv/base_presenter.rb +41 -0
  5. data/lib/rpv/event_publisher.rb +125 -0
  6. data/lib/rpv/generators/app_generator.rb +17 -0
  7. data/lib/rpv/generators/base.rb +130 -0
  8. data/lib/rpv/generators/presenter_generator.rb +28 -0
  9. data/lib/rpv/generators/templates/app/README +12 -0
  10. data/lib/rpv/generators/templates/app/Rakefile +3 -0
  11. data/lib/rpv/generators/templates/app/app/main.rb +4 -0
  12. data/lib/rpv/generators/templates/app/app/setup.rb +11 -0
  13. data/lib/rpv/generators/templates/app/spec/spec_helper.rb +5 -0
  14. data/lib/rpv/generators/templates/app/tasks/rspec.rake +9 -0
  15. data/lib/rpv/generators/templates/presenter/presenter.rb.erb +10 -0
  16. data/lib/rpv/generators/templates/presenter/presenter_spec.rb.erb +22 -0
  17. data/lib/rpv/inflector.rb +68 -0
  18. data/lib/rpv/method.rb +13 -0
  19. data/lib/rpv/method_helper.rb +9 -0
  20. data/lib/rpv/option_extractor.rb +15 -0
  21. data/lib/rpv/spec_helper.rb +118 -0
  22. data/lib/rpv/wiring/base.rb +49 -0
  23. data/lib/rpv/wiring/callable.rb +20 -0
  24. data/lib/rpv/wiring/converting.rb +36 -0
  25. data/lib/rpv/wiring/helpers.rb +23 -0
  26. data/lib/rpv/wiring/simple.rb +19 -0
  27. data/lib/rpv/wiring/unidirectional.rb +38 -0
  28. data/lib/rpv/wiring.rb +4 -0
  29. data/lib/rpv.rb +20 -0
  30. data/spec/autoload_spec.rb +24 -0
  31. data/spec/base_presenter_spec.rb +16 -0
  32. data/spec/event_publisher_spec.rb +121 -0
  33. data/spec/files/autoload/b/some_module.rb +2 -0
  34. data/spec/files/autoload/some_class.rb +3 -0
  35. data/spec/files/bar/presenter.rb.erb +5 -0
  36. data/spec/files/bar/view.rb.erb +3 -0
  37. data/spec/files/foo/Rakefile +0 -0
  38. data/spec/files/foo/app/main.rb.erb +1 -0
  39. data/spec/files/foo/app/models/templates/lala.html.erb +2 -0
  40. data/spec/generators/base_spec.rb +81 -0
  41. data/spec/generators/presenter_spec.rb +27 -0
  42. data/spec/method_helper_spec.rb +19 -0
  43. data/spec/method_spec.rb +12 -0
  44. data/spec/option_extractor_spec.rb +22 -0
  45. data/spec/spec_helper.rb +1 -0
  46. data/spec/spec_helper_spec.rb +15 -0
  47. data/spec/wiring/base_spec.rb +17 -0
  48. data/spec/wiring/callable_spec.rb +50 -0
  49. data/spec/wiring/helpers_spec.rb +29 -0
  50. data/spec/wiring/simple_spec.rb +47 -0
  51. data/spec/wiring/unidirectional_spec.rb +46 -0
  52. data/tasks/rdoc.rake +10 -0
  53. data/tasks/rspec.rake +10 -0
  54. metadata +118 -0
@@ -0,0 +1,19 @@
1
+ require "rpv/wiring/converting"
2
+
3
+ module RPV
4
+ module Wiring
5
+ class Simple < Converting
6
+ def initialize(args = {})
7
+ super
8
+ end
9
+
10
+ def convert_from_view(value)
11
+ value
12
+ end
13
+
14
+ def convert_to_view(value)
15
+ value
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ module RPV
2
+ module Wiring
3
+ # Wraps any other wiring in order to do updates only into one direction.
4
+ # Valid directions are :model_only, :presenter_only, :view_only
5
+ class Unidirectional
6
+ def initialize(wiring, direction)
7
+ @wiring, @direction = wiring, direction
8
+ end
9
+
10
+ def update_model(*args)
11
+ @wiring.update_model(*args) if @direction == :model_only
12
+ end
13
+
14
+ def update_presenter(*args)
15
+ @wiring.update_presenter(*args) if @direction == :presenter_only
16
+ end
17
+
18
+ def update_view(*args)
19
+ @wiring.update_view(*args) if @direction == :view_only
20
+ end
21
+
22
+ # Match the view method against a hash of constraints (like { :only => /^bar\.(.*)/, :except => /(.*)\.text$/ })
23
+ def view_match(args = {})
24
+ @wiring.view_match(args)
25
+ end
26
+
27
+ # Match the presenter method against a hash of constraints (like { :only => /^bar\.(.*)/, :except => /(.*)\.text$/ })
28
+ def presenter_match(args = {})
29
+ @wiring.presenter_match(args)
30
+ end
31
+
32
+ # Match the model method against a hash of constraints (like { :only => /^bar\.(.*)/, :except => /(.*)\.text$/ })
33
+ def model_match(args = {})
34
+ @wiring.model_match(args)
35
+ end
36
+ end
37
+ end
38
+ end
data/lib/rpv/wiring.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'rpv/wiring/simple'
2
+ require 'rpv/wiring/converting'
3
+ require 'rpv/wiring/callable'
4
+ require 'rpv/wiring/unidirectional'
data/lib/rpv.rb ADDED
@@ -0,0 +1,20 @@
1
+ require "rpv/inflector"
2
+ require "rpv/base_presenter"
3
+ require "rpv/event_publisher"
4
+
5
+ module RPV
6
+ module Generators
7
+ Requires = []
8
+
9
+ def self.require_all
10
+ Requires.each { |r| require r }
11
+ end
12
+
13
+ def self.all
14
+ require_all
15
+ Requires.map { |r| eval(r.camelize.gsub(/Rpv/, "RPV")) }
16
+ end
17
+ end
18
+ end
19
+
20
+ RPV::Generators::Requires << 'rpv/generators/presenter_generator'
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ require 'rpv/autoload'
4
+
5
+ describe "RPV::Autoload" do
6
+ before(:all) do
7
+ RPV::Autoload.setup_paths File.dirname(__FILE__) + '/files/autoload'
8
+ end
9
+
10
+ it "should add the base dir and all beneath it to LOAD_PATH" do
11
+ $LOAD_PATH.select { |p| p =~ /spec\/files\/autoload$/ }.size.should == 1
12
+ $LOAD_PATH.select { |p| p =~ /spec\/files\/autoload/ }.size.should == 3
13
+ end
14
+
15
+ it "should try to require the right files" do
16
+ a = SomeClass.new
17
+ b = SomeModule
18
+ end
19
+
20
+ it "should raise an exception if a file is missing" do
21
+ lambda { NonExistingClass.new }.should raise_error(NameError)
22
+ end
23
+ end
24
+
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ require 'rpv/base_presenter'
4
+
5
+ describe "BasePresenter" do
6
+ it "should add wires" do
7
+ c = Class.new(RPV::BasePresenter)
8
+ c.send(:wires, "foo")
9
+ c.send(:wires).size.should == 1
10
+ end
11
+
12
+ it "should not fail to update if there are no wires" do
13
+ c = Class.new(RPV::BasePresenter)
14
+ c.new.update_model
15
+ end
16
+ end
@@ -0,0 +1,121 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'rpv/event_publisher'
3
+
4
+ class Foo
5
+ include RPV::EventPublisher
6
+ fires :event_a, :event_b
7
+
8
+ def do_fire(event, *args)
9
+ fire event, *args
10
+ end
11
+ end
12
+
13
+ describe "EventPublisher" do
14
+ it "should add events" do
15
+ Foo.events.should include :event_a
16
+ end
17
+
18
+ it "should alias an event" do
19
+ Foo.class_eval("alias_event :event_a, :alias")
20
+ f = Foo.new
21
+ called = false
22
+ f.subscribe :alias do
23
+ called = true
24
+ end
25
+ f.do_fire :event_a
26
+ called.should be_true
27
+ end
28
+
29
+ it "should create aliases using a regex" do
30
+ Foo.class_eval("alias_events /^event_(.+)$/, '$1_happend'")
31
+ Foo.event_aliases[:a_happend].should == [:event_a]
32
+ Foo.event_aliases[:b_happend].should == [:event_b]
33
+
34
+ Foo.class_eval("alias_events /^event_.+$/, 'something_happend'")
35
+ Foo.event_aliases[:something_happend].should == [:event_a, :event_b]
36
+ end
37
+
38
+ it "should create aliases later" do
39
+ #for published events, which are not available without an instance
40
+ pending
41
+ end
42
+
43
+ it "should call a block" do
44
+ f = Foo.new
45
+ called = false
46
+ f.subscribe :event_a do
47
+ called = true
48
+ end
49
+ f.do_fire :event_a
50
+ called.should be_true
51
+ end
52
+
53
+ it "should pass an argument to the block" do
54
+ f = Foo.new
55
+ called = false
56
+ f.subscribe :event_a do |arg|
57
+ called = true
58
+ arg.should == "hello"
59
+ end
60
+ f.do_fire :event_a, "hello"
61
+ called.should be_true
62
+ end
63
+
64
+ it "should call a method" do
65
+ r = mock_block("receiver") do |m|
66
+ m.should_receive(:foo).with(no_args())
67
+ end
68
+ f = Foo.new
69
+ f.subscribe :event_a, RPV::Method.new(r, :foo)
70
+ f.do_fire :event_a
71
+ end
72
+
73
+ it "should pass an argument to the method" do
74
+ r = mock_block("receiver") do |m|
75
+ m.should_receive(:foo).with("hello")
76
+ end
77
+ f = Foo.new
78
+ f.subscribe :event_a, RPV::Method.new(r, :foo)
79
+ f.do_fire :event_a, 'hello'
80
+ end
81
+
82
+ it "should pass any number of arguments to a receiver" do
83
+ r = mock_block("receiver") do |m|
84
+ m.should_receive(:foo).with("hello", "i", "have", "lots", :to, "tell")
85
+ end
86
+ f = Foo.new
87
+ f.subscribe :event_a, RPV::Method.new(r, :foo)
88
+ f.do_fire :event_a, "hello", "i", "have", "lots", :to, "tell"
89
+ end
90
+
91
+ it "should allow multiple subscriptions on an event" do
92
+ r = mock_block("receiver") do |m|
93
+ m.should_receive(:foo)
94
+ m.should_receive(:bar)
95
+ end
96
+ f = Foo.new
97
+ f.subscribe :event_a, RPV::Method.new(r, :foo)
98
+ f.subscribe :event_a, RPV::Method.new(r, :bar)
99
+ f.do_fire :event_a
100
+ end
101
+
102
+ it "should allow to subscribe by regex" do
103
+ r = mock_block("receiver") do |m|
104
+ m.should_receive(:foo).twice
105
+ end
106
+ f = Foo.new
107
+ f.subscribe /^event_.+$/, RPV::Method.new(r, :foo)
108
+ f.do_fire :event_a
109
+ f.do_fire :event_b
110
+ end
111
+
112
+ it "should allow to subscribe to multiple events" do
113
+ r = mock_block("receiver") do |m|
114
+ m.should_receive(:foo).twice
115
+ end
116
+ f = Foo.new
117
+ f.subscribe [:event_a, :event_b, :event_a], RPV::Method.new(r, :foo)
118
+ f.do_fire :event_a
119
+ f.do_fire :event_b
120
+ end
121
+ end
@@ -0,0 +1,2 @@
1
+ module SomeModule
2
+ end
@@ -0,0 +1,3 @@
1
+ class SomeClass
2
+
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'rpv/base_presenter'
2
+
3
+ class <%= class_name %>Presenter < RPV::BasePresenter
4
+
5
+ end
@@ -0,0 +1,3 @@
1
+ class <%= class_name %>View
2
+
3
+ end
File without changes
@@ -0,0 +1 @@
1
+ <%= main %>
@@ -0,0 +1,2 @@
1
+ A template that should not be parsed.
2
+ <%= non_existing_variable %>
@@ -0,0 +1,81 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper.rb"
2
+ require 'fileutils'
3
+
4
+ require "rpv/generators/base"
5
+
6
+ # An application generator
7
+ class FooGenerator < RPV::Generators::Base
8
+ argument :main
9
+ copy_all
10
+ copy 'app/**/*' #redundant, in order to check if stuff is copied only once
11
+ parse 'app/main.rb.erb' #this file will be parsed and saved to 'app/main.rb'
12
+
13
+ def initialize
14
+ @template_path = File.expand_path(File.dirname(__FILE__) + '/../files/foo')
15
+ end
16
+ end
17
+
18
+ # Generates a view and a presenter
19
+ class BarGenerator < RPV::Generators::Base
20
+ argument :name
21
+ parse 'presenter.rb.erb', 'app/presenters/#{name}_presenter.rb'
22
+ parse 'view.rb.erb', 'app/views/#{name}_view.rb'
23
+
24
+ def initialize
25
+ @template_path = File.expand_path(File.dirname(__FILE__) + '/../files/bar')
26
+ end
27
+
28
+ def parse_args
29
+ @arguments[:name] = @arguments[:name].underscore
30
+ @arguments[:class_name] = @arguments[:name].camelize
31
+ end
32
+ end
33
+
34
+ describe "base generator" do
35
+ before(:all) do
36
+ FileUtils.mkdir_p 'spec/tmp'
37
+ end
38
+
39
+ it "should copy files" do
40
+ g = FooGenerator.new
41
+ FileUtils.cd 'spec/tmp' do
42
+ FileUtils.rm_r 'app1' if File.exists? 'app1'
43
+ g.execute(:to_path => 'app1', :main => "lala")
44
+ end
45
+ File.exists?('spec/tmp/app1').should be_true
46
+ File.exists?('spec/tmp/app1/app/models/templates/lala.html.erb').should be_true
47
+ File.exists?('spec/tmp/app1/app/main.rb').should be_true
48
+ File.read('spec/tmp/app1/app/main.rb').should == "lala\n"
49
+ end
50
+
51
+ it "should eval new paths for parsed files" do
52
+ g = BarGenerator.new
53
+ FileUtils.cd 'spec/tmp' do
54
+ FileUtils.rm_r 'app' if File.exists? 'app'
55
+ g.execute(:to_path => '', :name => "lala")
56
+ end
57
+ File.exists?('spec/tmp/app/presenters').should be_true
58
+ File.exists?('spec/tmp/app/views').should be_true
59
+ File.exists?('spec/tmp/app/presenters/lala_presenter.rb').should be_true
60
+ File.exists?('spec/tmp/app/views/lala_view.rb').should be_true
61
+ File.read('spec/tmp/app/presenters/lala_presenter.rb').should =~ /LalaPresenter/
62
+ File.read('spec/tmp/app/views/lala_view.rb').should =~ /LalaView/
63
+ end
64
+
65
+ it "should ask before overwriting files" do
66
+ g = RPV::Generators::Base.new
67
+ file = "huhu/lala/1.rb"
68
+ g.should_receive(:puts).twice.with("File #{file} exists. Overwrite? (y(es)/n(o)/a(ll)) ")
69
+ STDIN.should_receive(:gets).twice.and_return("y\n", "a\n")
70
+ g.overwrite?(file).should be_true
71
+ g.overwrite?(file).should be_true
72
+ g.overwrite?(file).should be_true #the second time we answered a(ll), so now we should not be asked again
73
+ end
74
+
75
+ it "should generate relative paths" do
76
+ g = RPV::Generators::Base.new
77
+ g.relative_path("/home/user/foo/bar.rb", "/home/user").should == "foo/bar.rb"
78
+ g.relative_path("/home/user/foo/bar.rb", "/home/user/").should == "foo/bar.rb"
79
+ g.relative_path("/home/user/code/home/foo/bar.rb", "/home").should == "user/code/home/foo/bar.rb"
80
+ end
81
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper.rb"
2
+ require 'fileutils'
3
+
4
+ require "rpv/generators/presenter_generator"
5
+
6
+ describe "presenter generator" do
7
+ before(:all) do
8
+ FileUtils.mkdir_p 'spec/tmp'
9
+ end
10
+
11
+ after(:all) do
12
+ FileUtils.rm_r 'spec/tmp'
13
+ end
14
+
15
+ it "should create a presenter and a spec" do
16
+ g = RPV::Generators::PresenterGenerator.new
17
+ FileUtils.cd 'spec/tmp' do
18
+ FileUtils.rm_r 'app' if File.exists? 'app'
19
+ FileUtils.rm_r 'spec' if File.exists? 'spec'
20
+ g.execute(:to_path => '.', :name => "foo")
21
+ end
22
+ File.exists?('spec/tmp/app/presenters/foo_presenter.rb').should be_true
23
+ File.exists?('spec/tmp/spec/presenters/foo_presenter_spec.rb').should be_true
24
+ File.read('spec/tmp/app/presenters/foo_presenter.rb').should =~ /class FooPresenter/
25
+ File.read('spec/tmp/spec/presenters/foo_presenter_spec.rb').should =~ /describe FooPresenter/
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'rpv/method_helper'
3
+
4
+ describe "MethodHelper" do
5
+ it "should return a Method" do
6
+ instance = Class.new {
7
+ include RPV::MethodHelper
8
+
9
+ def some_method(foo)
10
+ foo.to_s
11
+ end
12
+ }.new
13
+
14
+ m = instance.method("foo")
15
+ m.should be_a(RPV::Method)
16
+ m.method.should == :foo
17
+ m.object.should == instance
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'rpv/method'
3
+
4
+ describe "Method" do
5
+ it "should call a method passing all args" do
6
+ receiver = mock_block("receiver") do |m|
7
+ m.should_receive(:foo).with(1, "asdf")
8
+ end
9
+ m = RPV::Method.new(receiver, :foo)
10
+ m.call(1, "asdf")
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'rpv/option_extractor'
3
+
4
+ describe "OptionExtractor" do
5
+ it "should extract given options from args" do
6
+ instance = Class.new {
7
+ include RPV::OptionExtractor
8
+
9
+ def foo(*args)
10
+ @foo, @bar, @foo_bar = extract_options(args, :foo, :bar, :foo_bar)
11
+ [@foo, @bar, @foo_bar]
12
+ end
13
+
14
+ def bar(*args)
15
+ @lala = extract_options(args, :lala)
16
+ @lala
17
+ end
18
+ }.new
19
+ instance.foo("some", "arguments", :bar => 1, :foo => 0).should == [0, 1, nil]
20
+ instance.bar(:lala => 1).should == 1
21
+ end
22
+ end