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.
- data/Rakefile +3 -0
- data/bin/rpv +68 -0
- data/lib/rpv/autoload.rb +36 -0
- data/lib/rpv/base_presenter.rb +41 -0
- data/lib/rpv/event_publisher.rb +125 -0
- data/lib/rpv/generators/app_generator.rb +17 -0
- data/lib/rpv/generators/base.rb +130 -0
- data/lib/rpv/generators/presenter_generator.rb +28 -0
- data/lib/rpv/generators/templates/app/README +12 -0
- data/lib/rpv/generators/templates/app/Rakefile +3 -0
- data/lib/rpv/generators/templates/app/app/main.rb +4 -0
- data/lib/rpv/generators/templates/app/app/setup.rb +11 -0
- data/lib/rpv/generators/templates/app/spec/spec_helper.rb +5 -0
- data/lib/rpv/generators/templates/app/tasks/rspec.rake +9 -0
- data/lib/rpv/generators/templates/presenter/presenter.rb.erb +10 -0
- data/lib/rpv/generators/templates/presenter/presenter_spec.rb.erb +22 -0
- data/lib/rpv/inflector.rb +68 -0
- data/lib/rpv/method.rb +13 -0
- data/lib/rpv/method_helper.rb +9 -0
- data/lib/rpv/option_extractor.rb +15 -0
- data/lib/rpv/spec_helper.rb +118 -0
- data/lib/rpv/wiring/base.rb +49 -0
- data/lib/rpv/wiring/callable.rb +20 -0
- data/lib/rpv/wiring/converting.rb +36 -0
- data/lib/rpv/wiring/helpers.rb +23 -0
- data/lib/rpv/wiring/simple.rb +19 -0
- data/lib/rpv/wiring/unidirectional.rb +38 -0
- data/lib/rpv/wiring.rb +4 -0
- data/lib/rpv.rb +20 -0
- data/spec/autoload_spec.rb +24 -0
- data/spec/base_presenter_spec.rb +16 -0
- data/spec/event_publisher_spec.rb +121 -0
- data/spec/files/autoload/b/some_module.rb +2 -0
- data/spec/files/autoload/some_class.rb +3 -0
- data/spec/files/bar/presenter.rb.erb +5 -0
- data/spec/files/bar/view.rb.erb +3 -0
- data/spec/files/foo/Rakefile +0 -0
- data/spec/files/foo/app/main.rb.erb +1 -0
- data/spec/files/foo/app/models/templates/lala.html.erb +2 -0
- data/spec/generators/base_spec.rb +81 -0
- data/spec/generators/presenter_spec.rb +27 -0
- data/spec/method_helper_spec.rb +19 -0
- data/spec/method_spec.rb +12 -0
- data/spec/option_extractor_spec.rb +22 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/spec_helper_spec.rb +15 -0
- data/spec/wiring/base_spec.rb +17 -0
- data/spec/wiring/callable_spec.rb +50 -0
- data/spec/wiring/helpers_spec.rb +29 -0
- data/spec/wiring/simple_spec.rb +47 -0
- data/spec/wiring/unidirectional_spec.rb +46 -0
- data/tasks/rdoc.rake +10 -0
- data/tasks/rspec.rake +10 -0
- 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
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
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= main %>
|
@@ -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
|
data/spec/method_spec.rb
ADDED
@@ -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
|