catwalk 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +17 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/catwalk.gemspec +27 -0
- data/cucumber.yml +3 -0
- data/features/active_model_compatibility.feature +11 -0
- data/features/basic_fields.feature +11 -0
- data/features/specifying_model_accessor.feature +10 -0
- data/features/step_definitions/model_steps.rb +9 -0
- data/features/step_definitions/presenter_steps.rb +46 -0
- data/features/support/active_model_example.rb +23 -0
- data/features/support/env.rb +2 -0
- data/lib/catwalk.rb +1 -0
- data/lib/catwalk/presenter.rb +35 -0
- data/lib/catwalk/version.rb +3 -0
- data/spec/catwalk/presenter_spec.rb +74 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/active_model_lint.rb +33 -0
- data/spec/support/active_model_proxy_shared_examples.rb +17 -0
- metadata +173 -0
data/.autotest
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
begin
|
2
|
+
require 'autotest/fsevent'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
Autotest.add_hook :initialize do |at|
|
7
|
+
|
8
|
+
at.add_exception /^(?:\.\/)?\.git/
|
9
|
+
at.add_exception /^(?:\.\/)?\.bundle/
|
10
|
+
at.add_exception /^(?:\.\/)?tmp/
|
11
|
+
|
12
|
+
at.add_mapping(/^.autotest$/,true) { |_,_|
|
13
|
+
Dir["spec/**/*_spec.rb"]
|
14
|
+
}
|
15
|
+
|
16
|
+
nil
|
17
|
+
end
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
data/catwalk.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "catwalk/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "catwalk"
|
7
|
+
s.version = Catwalk::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Jon Rowe"]
|
10
|
+
s.email = ["hello@jonrowe.co.uk"]
|
11
|
+
s.homepage = "http://github.com/jonrowe/catwalk"
|
12
|
+
s.summary = %q{Catwalk is a gem for showing off models. It allows you to seperate presentation logic from data models.}
|
13
|
+
s.description = %q{Catwalk is a gem for showing off models. It allows you to seperate presentation logic from data models.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {spec,features}/* .autotest`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_development_dependency 'rspec'
|
21
|
+
s.add_development_dependency 'cucumber'
|
22
|
+
s.add_development_dependency 'ruby-debug19'
|
23
|
+
s.add_development_dependency 'autotest-standalone'
|
24
|
+
s.add_development_dependency 'autotest-fsevent' if RUBY_PLATFORM =~ /darwin/
|
25
|
+
|
26
|
+
s.add_development_dependency 'activemodel'
|
27
|
+
end
|
data/cucumber.yml
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Feature: Active Model compatibility
|
2
|
+
In order to use presenters interchangably with active models
|
3
|
+
As a developer
|
4
|
+
I wish to use catwalk to present my models whilst adhering to ActiveModel::Lint
|
5
|
+
|
6
|
+
Scenario: Basic Active Model functionality
|
7
|
+
Given I have an ActiveModel based model
|
8
|
+
And I have a presenter class
|
9
|
+
When I include Catwalk
|
10
|
+
And I setup my presenter to represent my model
|
11
|
+
Then my presenter should expose the models ActiveModel functionality
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Feature: Presenting basic fields from an active model compatible model
|
2
|
+
In order to seperate my presentation logic from my persistance models
|
3
|
+
As a developer
|
4
|
+
I want to wrap my models in a catwalk presenter
|
5
|
+
|
6
|
+
Scenario: Basic usage
|
7
|
+
Given I have an ActiveModel based model
|
8
|
+
And my model has a attribute named "title"
|
9
|
+
And I have a Catwalk presenter class for my model
|
10
|
+
When I define a field "title"
|
11
|
+
Then my presenter should present "title" from my model
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Feature: Specifying model accessor
|
2
|
+
In order to access the underlying model in my presenter methods
|
3
|
+
As a developer
|
4
|
+
I want to specify an accessor I will use to access the undelying model
|
5
|
+
|
6
|
+
Scenario: Specifiying accessor
|
7
|
+
Given I have an ActiveModel based model
|
8
|
+
And I have a Catwalk presenter class for my model
|
9
|
+
When I set access_as to "my_model"
|
10
|
+
Then my presenter should expose the model via "my_model"
|
@@ -0,0 +1,46 @@
|
|
1
|
+
Given "I have a presenter class" do
|
2
|
+
@presenter_klass = Class.new
|
3
|
+
end
|
4
|
+
|
5
|
+
Given "I have a Catwalk presenter class for my model" do
|
6
|
+
klass = Class.new
|
7
|
+
klass.send :include, Catwalk::Presenter
|
8
|
+
@presenter = klass.new @model
|
9
|
+
end
|
10
|
+
|
11
|
+
When "I include Catwalk" do
|
12
|
+
@presenter_klass.send :include, Catwalk::Presenter
|
13
|
+
end
|
14
|
+
|
15
|
+
When "I setup my presenter to represent my model" do
|
16
|
+
@presenter = @presenter_klass.new(@model)
|
17
|
+
end
|
18
|
+
|
19
|
+
When /^I define a field "([^"]*)"$/ do |field_name|
|
20
|
+
@presenter.class.class_eval do
|
21
|
+
field field_name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
When /^I set access_as to "([^"]*)"$/ do |accessor|
|
26
|
+
@presenter.class.class_eval do
|
27
|
+
access_as accessor
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Then "my presenter should expose the models ActiveModel functionality" do
|
32
|
+
@presenter.to_key.should == @model.to_key
|
33
|
+
@presenter.to_param.should == @model.to_param
|
34
|
+
@presenter.valid?.should == @model.valid?
|
35
|
+
@presenter.persisted?.should == @model.persisted?
|
36
|
+
@presenter.errors.should == @model.errors
|
37
|
+
@presenter.to_model.should == @model
|
38
|
+
end
|
39
|
+
|
40
|
+
Then /^my presenter should present "([^"]*)" from my model$/ do |field_name|
|
41
|
+
@presenter.send(field_name).should == @model.send(field_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
Then /^my presenter should expose the model via "([^"]*)"$/ do |field_name|
|
45
|
+
@presenter.send(field_name).should == @model
|
46
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
class ActiveModelExample
|
4
|
+
extend ActiveModel::Naming
|
5
|
+
|
6
|
+
attr_reader :errors
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@errors = ActiveModel::Errors.new(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_model
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_key; {}; end
|
17
|
+
def to_param; {}; end
|
18
|
+
def valid?; true; end
|
19
|
+
def new_record?; true; end
|
20
|
+
def destroyed?; true; end
|
21
|
+
def persisted?; true; end
|
22
|
+
end
|
23
|
+
|
data/lib/catwalk.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'catwalk/presenter'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Catwalk
|
2
|
+
module Presenter
|
3
|
+
def self.included(base)
|
4
|
+
base.send :extend, ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(model)
|
8
|
+
@model = model
|
9
|
+
end
|
10
|
+
|
11
|
+
define_method(:to_model) { @model }
|
12
|
+
define_method(:to_param) { @model.to_param if persisted? }
|
13
|
+
define_method(:to_key) { @model.to_key if persisted? }
|
14
|
+
define_method(:persisted?) { @model.persisted? }
|
15
|
+
define_method(:valid?) { @model.valid? }
|
16
|
+
define_method(:model_name) { @model.model_name }
|
17
|
+
define_method(:errors) { @model.errors }
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
|
21
|
+
def field(field_name)
|
22
|
+
define_method field_name do
|
23
|
+
@model.send field_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def access_as(accessor)
|
28
|
+
define_method accessor do
|
29
|
+
@model
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Catwalk
|
4
|
+
describe Presenter do
|
5
|
+
|
6
|
+
let(:model) { mock "model" }
|
7
|
+
let(:klass) { Class.new }
|
8
|
+
let(:presenter) { klass.new(model) }
|
9
|
+
|
10
|
+
before do
|
11
|
+
klass.class_eval { include Catwalk::Presenter }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "initialization" do
|
15
|
+
subject { presenter }
|
16
|
+
|
17
|
+
it "should assign an the model to an instance variable accessible via to_model" do
|
18
|
+
subject.to_model.should == model
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "active model compliance" do
|
23
|
+
let(:model_name) { mock 'model_name', human: "Model Name", singular: "model_name", plural: "Model Names", partial_path: '/model' }
|
24
|
+
let(:active_model_errors) { mock "errors", full_messages: [], :[] => [] }
|
25
|
+
let(:model) { mock "model", to_key: {}, to_param: {}, valid?: true, persisted?: true, model_name: model_name, errors: active_model_errors }
|
26
|
+
|
27
|
+
before do
|
28
|
+
model_name.stub(:kind_of?).with(String).and_return(true)
|
29
|
+
end
|
30
|
+
subject { presenter }
|
31
|
+
|
32
|
+
it_should_behave_like "ActiveModel"
|
33
|
+
it_should_behave_like "proxy active_model method", :to_key, from: :model
|
34
|
+
it_should_behave_like "proxy active_model method", :to_param, from: :model
|
35
|
+
it_should_behave_like "proxy active_model method", :valid?, from: :model
|
36
|
+
it_should_behave_like "proxy active_model method", :persisted?, from: :model
|
37
|
+
it_should_behave_like "proxy active_model method", :model_name, from: :model
|
38
|
+
it_should_behave_like "proxy active_model method", :errors, from: :model
|
39
|
+
its(:to_model) { should == model }
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "access_as" do
|
43
|
+
subject do
|
44
|
+
klass.class_eval do
|
45
|
+
access_as :model_accessor
|
46
|
+
end
|
47
|
+
presenter
|
48
|
+
end
|
49
|
+
|
50
|
+
its(:model_accessor) { should == model }
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "field" do
|
54
|
+
let(:model_value) { "a value" }
|
55
|
+
|
56
|
+
before do
|
57
|
+
model.stub(:a_field).and_return(model_value)
|
58
|
+
end
|
59
|
+
|
60
|
+
subject do
|
61
|
+
klass.class_eval do
|
62
|
+
field :a_field
|
63
|
+
end
|
64
|
+
presenter.a_field
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should proxy field to model" do
|
68
|
+
model.should_receive(:a_field).and_return(model_value)
|
69
|
+
subject
|
70
|
+
end
|
71
|
+
it { should == model_value }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# spec/support/active_model_lint.rb
|
2
|
+
# adapted from rspec-rails: http://github.com/rspec/rspec-rails/blob/master/spec/rspec/rails/mocks/mock_model_spec.rb
|
3
|
+
|
4
|
+
shared_examples_for "ActiveModel" do
|
5
|
+
|
6
|
+
it { should respond_to :to_key }
|
7
|
+
it { should respond_to :to_param }
|
8
|
+
it { should respond_to :valid? }
|
9
|
+
it { should respond_to :persisted? }
|
10
|
+
it { should respond_to :model_name }
|
11
|
+
it { should respond_to :errors }
|
12
|
+
it { should respond_to :to_model }
|
13
|
+
|
14
|
+
its(:"model_name") { should be_a String }
|
15
|
+
its(:"model_name.human") { should be_a String }
|
16
|
+
its(:"model_name.partial_path") { should be_a String }
|
17
|
+
its(:"model_name.singular") { should be_a String }
|
18
|
+
its(:"model_name.plural") { should be_a String }
|
19
|
+
|
20
|
+
its(:"errors.full_messages") { should be_a Array }
|
21
|
+
it "should have blank arrays for keys" do
|
22
|
+
subject.errors[:hello].should == []
|
23
|
+
end
|
24
|
+
|
25
|
+
context "where not persisted" do
|
26
|
+
before do
|
27
|
+
subject.stub(:persisted?).and_return(false)
|
28
|
+
end
|
29
|
+
|
30
|
+
its(:to_key) { should be_nil }
|
31
|
+
its(:to_param) { should be_nil }
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
shared_examples_for "proxy active_model method" do |method,opts|
|
2
|
+
let(:target) { send opts[:from] }
|
3
|
+
let(:target_value) { mock "value" }
|
4
|
+
|
5
|
+
before do
|
6
|
+
target.stub(method).and_return(target_value)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should proxy #{method} to #{opts[:from]}" do
|
10
|
+
target.should_receive(method).and_return(target_value)
|
11
|
+
subject.send(method)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "#{method} should == #{opts[:from]}.value" do
|
15
|
+
subject.send(method).should == target_value
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: catwalk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Jon Rowe
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-01-23 00:00:00 +00:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :development
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: cucumber
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: ruby-debug19
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id003
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: autotest-standalone
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
type: :development
|
71
|
+
version_requirements: *id004
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: autotest-fsevent
|
74
|
+
prerelease: false
|
75
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
type: :development
|
84
|
+
version_requirements: *id005
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: activemodel
|
87
|
+
prerelease: false
|
88
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
segments:
|
94
|
+
- 0
|
95
|
+
version: "0"
|
96
|
+
type: :development
|
97
|
+
version_requirements: *id006
|
98
|
+
description: Catwalk is a gem for showing off models. It allows you to seperate presentation logic from data models.
|
99
|
+
email:
|
100
|
+
- hello@jonrowe.co.uk
|
101
|
+
executables: []
|
102
|
+
|
103
|
+
extensions: []
|
104
|
+
|
105
|
+
extra_rdoc_files: []
|
106
|
+
|
107
|
+
files:
|
108
|
+
- .autotest
|
109
|
+
- .gitignore
|
110
|
+
- .rspec
|
111
|
+
- Gemfile
|
112
|
+
- Rakefile
|
113
|
+
- catwalk.gemspec
|
114
|
+
- cucumber.yml
|
115
|
+
- features/active_model_compatibility.feature
|
116
|
+
- features/basic_fields.feature
|
117
|
+
- features/specifying_model_accessor.feature
|
118
|
+
- features/step_definitions/model_steps.rb
|
119
|
+
- features/step_definitions/presenter_steps.rb
|
120
|
+
- features/support/active_model_example.rb
|
121
|
+
- features/support/env.rb
|
122
|
+
- lib/catwalk.rb
|
123
|
+
- lib/catwalk/presenter.rb
|
124
|
+
- lib/catwalk/version.rb
|
125
|
+
- spec/catwalk/presenter_spec.rb
|
126
|
+
- spec/spec_helper.rb
|
127
|
+
- spec/support/active_model_lint.rb
|
128
|
+
- spec/support/active_model_proxy_shared_examples.rb
|
129
|
+
has_rdoc: true
|
130
|
+
homepage: http://github.com/jonrowe/catwalk
|
131
|
+
licenses: []
|
132
|
+
|
133
|
+
post_install_message:
|
134
|
+
rdoc_options: []
|
135
|
+
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
none: false
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
segments:
|
144
|
+
- 0
|
145
|
+
version: "0"
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
+
none: false
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
segments:
|
152
|
+
- 0
|
153
|
+
version: "0"
|
154
|
+
requirements: []
|
155
|
+
|
156
|
+
rubyforge_project:
|
157
|
+
rubygems_version: 1.3.7
|
158
|
+
signing_key:
|
159
|
+
specification_version: 3
|
160
|
+
summary: Catwalk is a gem for showing off models. It allows you to seperate presentation logic from data models.
|
161
|
+
test_files:
|
162
|
+
- .autotest
|
163
|
+
- features/active_model_compatibility.feature
|
164
|
+
- features/basic_fields.feature
|
165
|
+
- features/specifying_model_accessor.feature
|
166
|
+
- features/step_definitions/model_steps.rb
|
167
|
+
- features/step_definitions/presenter_steps.rb
|
168
|
+
- features/support/active_model_example.rb
|
169
|
+
- features/support/env.rb
|
170
|
+
- spec/catwalk/presenter_spec.rb
|
171
|
+
- spec/spec_helper.rb
|
172
|
+
- spec/support/active_model_lint.rb
|
173
|
+
- spec/support/active_model_proxy_shared_examples.rb
|