lulalala_presenter 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/.travis.yml +23 -0
- data/Gemfile +9 -0
- data/MIT-LICENSE +20 -0
- data/README.md +68 -0
- data/Rakefile +12 -0
- data/gemfiles/Gemfile-rails.3.0.x +16 -0
- data/gemfiles/Gemfile-rails.3.1.x +19 -0
- data/gemfiles/Gemfile-rails.3.2.x +20 -0
- data/gemfiles/Gemfile-rails.4.0.x +10 -0
- data/gemfiles/Gemfile-rails.4.1.x +9 -0
- data/gemfiles/Gemfile-rails.4.2.x +9 -0
- data/lib/active_decorator/config.rb +20 -0
- data/lib/active_decorator/helpers.rb +14 -0
- data/lib/active_decorator/monkey/action_controller/base/rescue_from.rb +11 -0
- data/lib/active_decorator/view_context.rb +44 -0
- data/lib/generators/rails/decorator_generator.rb +24 -0
- data/lib/generators/rails/templates/decorator.rb +2 -0
- data/lib/generators/rspec/decorator_generator.rb +9 -0
- data/lib/generators/rspec/templates/decorator_spec.rb +7 -0
- data/lib/generators/test_unit/decorator_generator.rb +9 -0
- data/lib/generators/test_unit/templates/decorator_test.rb +11 -0
- data/lib/lulalala_presenter.rb +4 -0
- data/lib/lulalala_presenter/active_model_bridge.rb +10 -0
- data/lib/lulalala_presenter/base.rb +14 -0
- data/lib/lulalala_presenter/railtie.rb +22 -0
- data/lib/lulalala_presenter/version.rb +3 -0
- data/lulalala_presenter.gemspec +18 -0
- data/spec/configuration_spec.rb +27 -0
- data/spec/controllers/fake_detection_spec.rb +7 -0
- data/spec/fake_app/app/views/authors/index.html.erb +16 -0
- data/spec/fake_app/app/views/authors/show.html.erb +2 -0
- data/spec/fake_app/app/views/authors/show.json.jbuilder +2 -0
- data/spec/fake_app/app/views/book_mailer/thanks.text.erb +1 -0
- data/spec/fake_app/app/views/books/_book.html.erb +2 -0
- data/spec/fake_app/app/views/books/_book.json.jbuilder +2 -0
- data/spec/fake_app/app/views/books/_book_locals.html.erb +2 -0
- data/spec/fake_app/app/views/books/error.html.erb +1 -0
- data/spec/fake_app/app/views/books/index.html.erb +4 -0
- data/spec/fake_app/app/views/books/purchase.html.erb +1 -0
- data/spec/fake_app/app/views/books/show.html.erb +4 -0
- data/spec/fake_app/app/views/movies/show.html.erb +1 -0
- data/spec/fake_app/fake_app.rb +194 -0
- data/spec/features/action_view_helpers_spec.rb +25 -0
- data/spec/features/controller_ivar_spec.rb +37 -0
- data/spec/features/jbuilder_spec.rb +12 -0
- data/spec/features/partial_spec.rb +25 -0
- data/spec/spec_helper.rb +27 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 83daef5e00861530f17904e67b427afb6398f4e6
|
4
|
+
data.tar.gz: 0da518f4274c4172cb51bdc47150062f77253404
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c5267a2f9ecec315bbf7f53e2feb755b9bfe598fc411d974af01ca6b19f59b65852e33d9dd4b59f13cde2dc6d7df3b7d76775dafffb9ce9f6c0e3e73a9807ec5
|
7
|
+
data.tar.gz: 06ef0a6c2b5270754543f25c080c6c332d2eed8b3f8694e48330f45fc601f991dd387edc454f504c8f75ef92243384de973e36414df631c0a8eb0daba75316e3
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
language: ruby
|
2
|
+
|
3
|
+
script: bundle exec rake spec
|
4
|
+
|
5
|
+
rvm:
|
6
|
+
- 2.0.0
|
7
|
+
- 2.1
|
8
|
+
- 2.2.3
|
9
|
+
- ruby-head
|
10
|
+
gemfile:
|
11
|
+
- gemfiles/Gemfile-rails.3.2.x
|
12
|
+
- gemfiles/Gemfile-rails.4.0.x
|
13
|
+
- gemfiles/Gemfile-rails.4.1.x
|
14
|
+
- gemfiles/Gemfile-rails.4.2.x
|
15
|
+
|
16
|
+
sudo: false
|
17
|
+
|
18
|
+
matrix:
|
19
|
+
exclude:
|
20
|
+
- rvm: ruby-head
|
21
|
+
gemfile: gemfiles/Gemfile-rails.3.2.x
|
22
|
+
allow_failures:
|
23
|
+
- rvm: ruby-head
|
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Akira Matsuda
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# LulalalaPresenter - forked from ActiveDecorator
|
2
|
+
|
3
|
+
...where you can put your view helpers if they are **very closely** related to ActiveModel.
|
4
|
+
|
5
|
+
This solves one very important computer science problem: naming your helper methods. All great programmers feels uneasy seeing:
|
6
|
+
|
7
|
+
* `auction_title(@auction)`
|
8
|
+
* `board_title(@board)`
|
9
|
+
* `category_title(@category)`
|
10
|
+
|
11
|
+
and this gem will solve it.
|
12
|
+
|
13
|
+
|
14
|
+
## Usage ##
|
15
|
+
|
16
|
+
1. put `gem 'lulalala_presenter', github:'lulalala/lulalala_presenter'` in Gemfile and then `bundle install`.
|
17
|
+
2. create a presenter class for each AR model you wish to present. For example, a decorator for a model `User` should be named `UserPresenter`.
|
18
|
+
3. access this presenter from the model like this: `record.presenter`, and from there call the helper methods.
|
19
|
+
2. call any ActionView's helper methods using `h`, e.g. `h.content_tag` or `h.link_to`.
|
20
|
+
|
21
|
+
|
22
|
+
## Examples ##
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
# app/models/user.rb
|
26
|
+
class User < ActiveRecord::Base
|
27
|
+
# first_name:string last_name:string website:string
|
28
|
+
end
|
29
|
+
|
30
|
+
# app/presenters/user_presenter.rb
|
31
|
+
module UserPresenter < LulalalaPresenter::Base
|
32
|
+
def full_name
|
33
|
+
"#{model.first_name} #{model.last_name}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def link
|
37
|
+
h.link_to model.full_name, model.website
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# app/controllers/users_controller.rb
|
42
|
+
class UsersController < ApplicationController
|
43
|
+
def index
|
44
|
+
@users = User.all
|
45
|
+
end
|
46
|
+
end
|
47
|
+
```
|
48
|
+
```erb
|
49
|
+
# app/views/users/index.html.erb
|
50
|
+
<% @users.each do |user| %>
|
51
|
+
<%= user.presenter.link %><br>
|
52
|
+
<% end %>
|
53
|
+
```
|
54
|
+
|
55
|
+
## Reason for fork ##
|
56
|
+
|
57
|
+
It's difficult to decorate models automatically. Leaky abstractions can happen easily. Having a presenter class that can be accessed from model would not have that issue at all.
|
58
|
+
Even though more typing is needed, I think it is good for establishing the awareness that presenter helpers are different to model methods.
|
59
|
+
|
60
|
+
## Contribute ##
|
61
|
+
|
62
|
+
* Fork, fix, then send me a pull request.
|
63
|
+
|
64
|
+
|
65
|
+
## Copyright ##
|
66
|
+
|
67
|
+
Copyright (c) 2011 Akira Matsuda. See MIT-LICENSE for further details.
|
68
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
require 'rspec/core'
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
9
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
10
|
+
end
|
11
|
+
|
12
|
+
task :default => :spec
|
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'active_decorator', :path => '..'
|
4
|
+
|
5
|
+
gem 'rails', '~> 3.0.0'
|
6
|
+
gem 'rspec-rails', '~> 2.14.0'
|
7
|
+
gem 'capybara', '~> 2.0.0'
|
8
|
+
# rubyzip >=1 doesn't support ruby 1.8
|
9
|
+
gem 'rubyzip', '< 1.0.0'
|
10
|
+
gem 'sqlite3'
|
11
|
+
gem 'nokogiri', '~> 1.5.0'
|
12
|
+
if RUBY_VERSION <= '1.8.7'
|
13
|
+
gem 'jbuilder', '< 2'
|
14
|
+
else
|
15
|
+
gem 'jbuilder'
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'active_decorator', :path => '..'
|
4
|
+
|
5
|
+
gem 'rails', '~> 3.1.0'
|
6
|
+
gem 'rspec-rails', '~> 2.14.0'
|
7
|
+
if RUBY_VERSION <= '1.8.7'
|
8
|
+
gem 'i18n', '~> 0.6.11'
|
9
|
+
end
|
10
|
+
gem 'capybara', '~> 2.0.0'
|
11
|
+
# rubyzip >=1 doesn't support ruby 1.8
|
12
|
+
gem 'rubyzip', '< 1.0.0'
|
13
|
+
gem 'sqlite3'
|
14
|
+
gem 'nokogiri', '~> 1.5.0'
|
15
|
+
if RUBY_VERSION <= '1.8.7'
|
16
|
+
gem 'jbuilder', '< 2'
|
17
|
+
else
|
18
|
+
gem 'jbuilder'
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'active_decorator', :path => '..'
|
4
|
+
|
5
|
+
gem 'rails', '~> 3.2.0'
|
6
|
+
gem 'rspec-rails', '~> 2.14.0'
|
7
|
+
if RUBY_VERSION <= '1.8.7'
|
8
|
+
gem 'i18n', '~> 0.6.11'
|
9
|
+
end
|
10
|
+
gem 'capybara', '~> 2.0.0'
|
11
|
+
# rubyzip >=1 doesn't support ruby 1.8
|
12
|
+
gem 'rubyzip', '< 1.0.0'
|
13
|
+
gem 'sqlite3'
|
14
|
+
gem 'nokogiri', '~> 1.5.0'
|
15
|
+
if RUBY_VERSION <= '1.8.7'
|
16
|
+
gem 'jbuilder', '< 2'
|
17
|
+
else
|
18
|
+
gem 'jbuilder'
|
19
|
+
end
|
20
|
+
gem 'test-unit'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ActiveDecorator
|
2
|
+
def self.configure(&block)
|
3
|
+
yield @config ||= ActiveDecorator::Configuration.new
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.config
|
7
|
+
@config
|
8
|
+
end
|
9
|
+
|
10
|
+
# need a Class for 3.0
|
11
|
+
class Configuration #:nodoc:
|
12
|
+
include ActiveSupport::Configurable
|
13
|
+
|
14
|
+
config_accessor :decorator_suffix
|
15
|
+
end
|
16
|
+
|
17
|
+
configure do |config|
|
18
|
+
config.decorator_suffix = 'Decorator'
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ActiveDecorator
|
2
|
+
module Helpers
|
3
|
+
def method_missing(method, *args, &block)
|
4
|
+
super
|
5
|
+
#TODO need to make sure who raised the error?
|
6
|
+
rescue NoMethodError, NameError => original_error
|
7
|
+
begin
|
8
|
+
ActiveDecorator::ViewContext.current.send method, *args, &block
|
9
|
+
rescue NoMethodError, NameError
|
10
|
+
raise original_error
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module ActionController
|
2
|
+
class Base
|
3
|
+
def rescue_with_handler_with_decorator_view_context(exception)
|
4
|
+
ActiveDecorator::ViewContext.push(view_context)
|
5
|
+
rescue_with_handler_without_decorator_view_context(exception)
|
6
|
+
ensure
|
7
|
+
ActiveDecorator::ViewContext.pop
|
8
|
+
end
|
9
|
+
alias_method_chain :rescue_with_handler, :decorator_view_context
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ActiveDecorator
|
2
|
+
module ViewContext
|
3
|
+
class << self
|
4
|
+
def current
|
5
|
+
Thread.current[:active_decorator_view_contexts].last
|
6
|
+
end
|
7
|
+
|
8
|
+
def push(view_context)
|
9
|
+
Thread.current[:active_decorator_view_contexts] ||= []
|
10
|
+
Thread.current[:active_decorator_view_contexts] << view_context
|
11
|
+
end
|
12
|
+
|
13
|
+
def pop
|
14
|
+
Thread.current[:active_decorator_view_contexts].pop if Thread.current[:active_decorator_view_contexts]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Filter
|
19
|
+
extend ActiveSupport::Concern
|
20
|
+
|
21
|
+
included do
|
22
|
+
if Rails::VERSION::MAJOR >= 4
|
23
|
+
around_action do |controller, blk|
|
24
|
+
begin
|
25
|
+
ActiveDecorator::ViewContext.push controller.view_context
|
26
|
+
blk.call
|
27
|
+
ensure
|
28
|
+
ActiveDecorator::ViewContext.pop
|
29
|
+
end
|
30
|
+
end
|
31
|
+
else
|
32
|
+
around_filter do |controller, blk|
|
33
|
+
begin
|
34
|
+
ActiveDecorator::ViewContext.push controller.view_context
|
35
|
+
blk.call
|
36
|
+
ensure
|
37
|
+
ActiveDecorator::ViewContext.pop
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rails
|
2
|
+
module Generators
|
3
|
+
class DecoratorGenerator < Rails::Generators::NamedBase
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
|
6
|
+
desc <<DESC
|
7
|
+
Description:
|
8
|
+
Stubs out a decorator module in app/decorators directory.
|
9
|
+
|
10
|
+
Examples:
|
11
|
+
`rails g decorator book`
|
12
|
+
|
13
|
+
This creates:
|
14
|
+
app/decorators/book_decorator.rb
|
15
|
+
DESC
|
16
|
+
|
17
|
+
def create_decorator_file
|
18
|
+
template 'decorator.rb', File.join('app/decorators', class_path, "#{file_name}_decorator.rb")
|
19
|
+
end
|
20
|
+
|
21
|
+
hook_for :test_framework
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Rspec
|
2
|
+
class DecoratorGenerator < ::Rails::Generators::NamedBase
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
4
|
+
|
5
|
+
def create_spec_file
|
6
|
+
template 'decorator_spec.rb', File.join('spec/decorators', class_path, "#{file_name}_decorator_spec.rb")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require '<%= File.exists?('spec/rails_helper.rb') ? 'rails_helper' : 'spec_helper' %>'
|
2
|
+
|
3
|
+
describe <%= singular_name.camelize %>Decorator do
|
4
|
+
let(:<%= singular_name %>) { <%= class_name %>.new.extend <%= singular_name.camelize %>Decorator }
|
5
|
+
subject { <%= singular_name %> }
|
6
|
+
it { should be_a <%= class_name %> }
|
7
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module TestUnit
|
2
|
+
class DecoratorGenerator < ::Rails::Generators::NamedBase
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
4
|
+
|
5
|
+
def create_test_file
|
6
|
+
template 'decorator_test.rb', File.join('test/decorators', class_path, "#{file_name}_decorator_test.rb")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class <%= singular_name.camelize %>DecoratorTest < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
@<%= singular_name %> = <%= class_name %>.new.extend <%= singular_name.camelize %>Decorator
|
6
|
+
end
|
7
|
+
|
8
|
+
# test "the truth" do
|
9
|
+
# assert true
|
10
|
+
# end
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'active_decorator/view_context'
|
2
|
+
require 'lulalala_presenter/active_model_bridge'
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module LulalalaPresenter
|
6
|
+
class Railtie < ::Rails::Railtie
|
7
|
+
initializer 'active_decorator' do
|
8
|
+
ActiveSupport.on_load(:action_controller) do
|
9
|
+
require 'active_decorator/monkey/action_controller/base/rescue_from'
|
10
|
+
ActionController::Base.send :include, ActiveDecorator::ViewContext::Filter
|
11
|
+
end
|
12
|
+
ActiveSupport.on_load(:action_mailer) do
|
13
|
+
if ActionMailer::Base.respond_to? :before_action
|
14
|
+
ActionMailer::Base.send :include, ActiveDecorator::ViewContext::Filter
|
15
|
+
end
|
16
|
+
end
|
17
|
+
ActiveSupport.on_load(:active_record) do
|
18
|
+
ActiveRecord::Base.send :include, LulalalaPresenter::ActiveModelBridge
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "lulalala_presenter/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "lulalala_presenter"
|
7
|
+
s.version = LulalalaPresenter::VERSION
|
8
|
+
s.authors = ["lulalala", "Akira Matsuda"]
|
9
|
+
s.email = ["mark@goodlife.tw", "ronnie@dio.jp"]
|
10
|
+
s.homepage = 'https://github.com/lulalala/lulalala_presenter'
|
11
|
+
s.summary = %q{A simple and Rubyish view helper for Rails}
|
12
|
+
s.description = %q{A simple and Rubyish view helper for Rails}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Comic = Struct.new(:title, :price)
|
2
|
+
|
3
|
+
module ComicPresenter
|
4
|
+
def price
|
5
|
+
"$#{super}"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ActiveDecorator::Configuration do
|
10
|
+
let(:comic) { ActiveDecorator::Decorator.instance.decorate(Comic.new("amatsuda's (Poignant) Guide to ActiveDecorator", 3)) }
|
11
|
+
|
12
|
+
context 'with a custom decorator_suffix' do
|
13
|
+
before do
|
14
|
+
ActiveDecorator.configure do |config|
|
15
|
+
config.decorator_suffix = 'Presenter'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
ActiveDecorator.configure do |config|
|
21
|
+
config.decorator_suffix = 'Decorator'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
specify { comic.price.should == '$3' }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% @authors.each do |author| %>
|
2
|
+
<%= author.name %>
|
3
|
+
<%= author.reverse_name %>
|
4
|
+
|
5
|
+
<% if params[:partial] == 'collection' %>
|
6
|
+
<%= render author.books %>
|
7
|
+
<% elsif params[:partial] == 'locals' %>
|
8
|
+
<% author.books.each do |book| %>
|
9
|
+
<%= render :partial => 'books/book_locals', :locals => {:b => book} %>
|
10
|
+
<% end %>
|
11
|
+
<% else %>
|
12
|
+
<% author.books.each do |book| %>
|
13
|
+
<%= render book %>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
Thank you for purchasing <%= @book.upcased_title %>.
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @book.error %>
|
@@ -0,0 +1 @@
|
|
1
|
+
done
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @movie.name %>
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'action_controller/railtie'
|
3
|
+
require 'action_mailer/railtie'
|
4
|
+
require 'action_view/railtie'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'jbuilder'
|
7
|
+
|
8
|
+
# config
|
9
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
10
|
+
|
11
|
+
module ActiveDecoratorTestApp
|
12
|
+
class Application < Rails::Application
|
13
|
+
config.secret_token = '"confusion" will be my epitaph.'
|
14
|
+
config.session_store :cookie_store, :key => '_myapp_session'
|
15
|
+
config.active_support.deprecation = :log
|
16
|
+
config.eager_load = false
|
17
|
+
config.action_dispatch.show_exceptions = false
|
18
|
+
config.root = File.dirname(__FILE__)
|
19
|
+
|
20
|
+
config.action_mailer.delivery_method = :test
|
21
|
+
end
|
22
|
+
end
|
23
|
+
ActiveDecoratorTestApp::Application.initialize!
|
24
|
+
|
25
|
+
# routes
|
26
|
+
ActiveDecoratorTestApp::Application.routes.draw do
|
27
|
+
resources :authors, :only => [:index, :show] do
|
28
|
+
resources :books, :only => [:index, :show] do
|
29
|
+
member do
|
30
|
+
get :error
|
31
|
+
post :purchase
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
resources :movies, :only => :show
|
36
|
+
end
|
37
|
+
|
38
|
+
# models
|
39
|
+
class Author < ActiveRecord::Base
|
40
|
+
has_many :books
|
41
|
+
end
|
42
|
+
class Book < ActiveRecord::Base
|
43
|
+
belongs_to :author
|
44
|
+
end
|
45
|
+
class Movie < ActiveRecord::Base
|
46
|
+
end
|
47
|
+
|
48
|
+
# helpers
|
49
|
+
module ApplicationHelper; end
|
50
|
+
|
51
|
+
# decorators
|
52
|
+
module AuthorDecorator
|
53
|
+
def reverse_name
|
54
|
+
name.reverse
|
55
|
+
end
|
56
|
+
|
57
|
+
def capitalized_name
|
58
|
+
name.capitalize
|
59
|
+
end
|
60
|
+
end
|
61
|
+
module BookDecorator
|
62
|
+
def reverse_title
|
63
|
+
title.reverse
|
64
|
+
end
|
65
|
+
|
66
|
+
def upcased_title
|
67
|
+
title.upcase
|
68
|
+
end
|
69
|
+
|
70
|
+
def link
|
71
|
+
link_to title, "#{request.protocol}#{request.host_with_port}/assets/sample.png", :class => 'title'
|
72
|
+
end
|
73
|
+
|
74
|
+
def cover_image
|
75
|
+
image_tag 'cover.png'
|
76
|
+
end
|
77
|
+
|
78
|
+
def error
|
79
|
+
"ERROR"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# decorator fake
|
84
|
+
class MovieDecorator; end
|
85
|
+
|
86
|
+
# controllers
|
87
|
+
class ApplicationController < ActionController::Base
|
88
|
+
self.append_view_path File.dirname(__FILE__)
|
89
|
+
end
|
90
|
+
class AuthorsController < ApplicationController
|
91
|
+
def index
|
92
|
+
if Author.respond_to?(:scoped)
|
93
|
+
# ActiveRecord 3.x
|
94
|
+
if params[:variable_type] == 'array'
|
95
|
+
@authors = Author.all
|
96
|
+
elsif params[:variable_type] == 'proxy'
|
97
|
+
@authors = RelationProxy.new(Author.scoped)
|
98
|
+
else
|
99
|
+
@authors = Author.scoped
|
100
|
+
end
|
101
|
+
else
|
102
|
+
# ActiveRecord 4.x
|
103
|
+
if params[:variable_type] == 'array'
|
104
|
+
@authors = Author.all.to_a
|
105
|
+
elsif params[:variable_type] == 'proxy'
|
106
|
+
@authors = RelationProxy.new(Author.all)
|
107
|
+
else
|
108
|
+
@authors = Author.all
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def show
|
114
|
+
@author = Author.find params[:id]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
class BooksController < ApplicationController
|
118
|
+
class CustomError < StandardError; end
|
119
|
+
|
120
|
+
rescue_from CustomError do
|
121
|
+
render "error"
|
122
|
+
end
|
123
|
+
|
124
|
+
def index
|
125
|
+
@author = Author.find params[:author_id]
|
126
|
+
@books = @author.books
|
127
|
+
end
|
128
|
+
|
129
|
+
def show
|
130
|
+
@book = Author.find(params[:author_id]).books.find(params[:id])
|
131
|
+
end
|
132
|
+
|
133
|
+
def error
|
134
|
+
@book = Author.find(params[:author_id]).books.find(params[:id])
|
135
|
+
raise CustomError, "error"
|
136
|
+
end
|
137
|
+
|
138
|
+
def purchase
|
139
|
+
@book = Author.find(params[:author_id]).books.find(params[:id])
|
140
|
+
|
141
|
+
@view_context_before_sending_mail = ActiveDecorator::ViewContext.current
|
142
|
+
BookMailer.thanks(@book).deliver
|
143
|
+
raise 'Wrong ViewContext!' if ActiveDecorator::ViewContext.current != @view_context_before_sending_mail
|
144
|
+
end
|
145
|
+
end
|
146
|
+
class MoviesController < ApplicationController
|
147
|
+
def show
|
148
|
+
@movie = Movie.find params[:id]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# mailers
|
153
|
+
class BookMailer < ActionMailer::Base
|
154
|
+
def thanks(book)
|
155
|
+
@book = book
|
156
|
+
mail :from => 'nobody@example.com', :to => 'test@example.com', :subject => 'Thanks'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# migrations
|
161
|
+
class CreateAllTables < ActiveRecord::Migration
|
162
|
+
def self.up
|
163
|
+
create_table(:authors) {|t| t.string :name}
|
164
|
+
create_table(:books) {|t| t.string :title; t.references :author}
|
165
|
+
create_table(:movies) {|t| t.string :name}
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Proxy for ActiveRecord::Relation
|
170
|
+
if RUBY_VERSION >= '1.9.0'
|
171
|
+
class RelationProxy < BasicObject
|
172
|
+
attr_accessor :ar_relation
|
173
|
+
|
174
|
+
def initialize(ar_relation)
|
175
|
+
@ar_relation = ar_relation
|
176
|
+
end
|
177
|
+
|
178
|
+
def method_missing(method, *args, &block)
|
179
|
+
@ar_relation.public_send(method, *args, &block)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
else
|
183
|
+
class RelationProxy < Object
|
184
|
+
attr_accessor :ar_relation
|
185
|
+
|
186
|
+
def initialize(ar_relation)
|
187
|
+
@ar_relation = ar_relation
|
188
|
+
end
|
189
|
+
|
190
|
+
def method_missing(method, *args, &block)
|
191
|
+
@ar_relation.send(method, *args, &block)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
feature 'fallback to helpers' do
|
2
|
+
background do
|
3
|
+
aamine = Author.create! :name => 'aamine'
|
4
|
+
@rhg = aamine.books.create! :title => 'RHG'
|
5
|
+
end
|
6
|
+
|
7
|
+
scenario 'invoking action_view helper methods' do
|
8
|
+
visit "/authors/#{@rhg.author.id}/books/#{@rhg.id}"
|
9
|
+
within 'a.title' do
|
10
|
+
page.should have_content 'RHG'
|
11
|
+
end
|
12
|
+
page.should have_css('img')
|
13
|
+
end
|
14
|
+
|
15
|
+
scenario 'invoking action_view helper methods in rescue_from view' do
|
16
|
+
visit "/authors/#{@rhg.author.id}/books/#{@rhg.id}/error"
|
17
|
+
page.should have_content('ERROR')
|
18
|
+
end
|
19
|
+
|
20
|
+
scenario 'make sure that action_view + action_mailer works' do
|
21
|
+
visit "/authors/#{@rhg.author.id}/books/#{@rhg.id}"
|
22
|
+
click_link 'purchase'
|
23
|
+
page.should have_content 'done'
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
feature 'decorating controller ivar' do
|
2
|
+
background do
|
3
|
+
@matz = Author.create! :name => 'matz'
|
4
|
+
@matz.books.create! :title => 'the world of code'
|
5
|
+
Author.create! :name => 'takahashim'
|
6
|
+
end
|
7
|
+
|
8
|
+
scenario 'decorating a model object in ivar' do
|
9
|
+
visit "/authors/#{@matz.id}"
|
10
|
+
page.should have_content 'matz'
|
11
|
+
page.should have_content 'matz'.capitalize
|
12
|
+
end
|
13
|
+
|
14
|
+
scenario 'decorating model scope in ivar' do
|
15
|
+
visit '/authors'
|
16
|
+
page.should have_content 'takahashim'
|
17
|
+
page.should have_content 'takahashim'.reverse
|
18
|
+
end
|
19
|
+
|
20
|
+
scenario "decorating models' array in ivar" do
|
21
|
+
visit '/authors?variable_type=array'
|
22
|
+
page.should have_content 'takahashim'
|
23
|
+
page.should have_content 'takahashim'.reverse
|
24
|
+
end
|
25
|
+
|
26
|
+
scenario "decorating models' proxy object in ivar" do
|
27
|
+
visit '/authors?variable_type=proxy'
|
28
|
+
page.should have_content 'takahashim'
|
29
|
+
page.should have_content 'takahashim'.reverse
|
30
|
+
end
|
31
|
+
|
32
|
+
scenario 'decorating model association proxy in ivar' do
|
33
|
+
visit "/authors/#{@matz.id}/books"
|
34
|
+
page.should have_content 'the world of code'
|
35
|
+
page.should have_content 'the world of code'.reverse
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
feature 'decorating partial object in Jbuilder' do
|
2
|
+
background do
|
3
|
+
Author.create! :name => 'aamine'
|
4
|
+
nari = Author.create! :name => 'nari'
|
5
|
+
nari.books.create! :title => 'the gc book'
|
6
|
+
end
|
7
|
+
|
8
|
+
scenario 'decorating objects in Jbuilder partials' do
|
9
|
+
visit "/authors/#{Author.last.id}.json"
|
10
|
+
page.source.should eq '{"name":"nari","books":[{"title":"the gc book","reverse_title":"koob cg eht"}]}'
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
feature 'decorating partial object' do
|
2
|
+
background do
|
3
|
+
Author.create! :name => 'aamine'
|
4
|
+
nari = Author.create! :name => 'nari'
|
5
|
+
nari.books.create! :title => 'the gc book'
|
6
|
+
end
|
7
|
+
|
8
|
+
scenario 'decorating implicit @object' do
|
9
|
+
visit '/authors'
|
10
|
+
page.should have_content 'the gc book'
|
11
|
+
page.should have_content 'the gc book'.reverse
|
12
|
+
end
|
13
|
+
|
14
|
+
scenario 'decorating implicit @collection' do
|
15
|
+
visit '/authors?partial=collection'
|
16
|
+
page.should have_content 'the gc book'
|
17
|
+
page.should have_content 'the gc book'.reverse
|
18
|
+
end
|
19
|
+
|
20
|
+
scenario 'decorating objects in @locals' do
|
21
|
+
visit '/authors?partial=locals'
|
22
|
+
page.should have_content 'the gc book'
|
23
|
+
page.should have_content 'the gc book'.upcase
|
24
|
+
end
|
25
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
# load Rails first
|
4
|
+
require 'rails'
|
5
|
+
require 'active_decorator'
|
6
|
+
# needs to load the app before loading rspec/rails => capybara
|
7
|
+
require 'fake_app/fake_app'
|
8
|
+
require 'rspec/rails'
|
9
|
+
# Requires supporting files with custom matchers and macros, etc,
|
10
|
+
# in ./support/ and its subdirectories.
|
11
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.expect_with :rspec do |c|
|
15
|
+
c.syntax = [:should, :expect]
|
16
|
+
end
|
17
|
+
|
18
|
+
config.before :all do
|
19
|
+
CreateAllTables.up unless ActiveRecord::Base.connection.table_exists? 'authors'
|
20
|
+
end
|
21
|
+
|
22
|
+
config.before :each do
|
23
|
+
Book.delete_all
|
24
|
+
Author.delete_all
|
25
|
+
Movie.delete_all
|
26
|
+
end
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lulalala_presenter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- lulalala
|
8
|
+
- Akira Matsuda
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-11-14 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A simple and Rubyish view helper for Rails
|
15
|
+
email:
|
16
|
+
- mark@goodlife.tw
|
17
|
+
- ronnie@dio.jp
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- ".gitignore"
|
23
|
+
- ".rspec"
|
24
|
+
- ".travis.yml"
|
25
|
+
- Gemfile
|
26
|
+
- MIT-LICENSE
|
27
|
+
- README.md
|
28
|
+
- Rakefile
|
29
|
+
- gemfiles/Gemfile-rails.3.0.x
|
30
|
+
- gemfiles/Gemfile-rails.3.1.x
|
31
|
+
- gemfiles/Gemfile-rails.3.2.x
|
32
|
+
- gemfiles/Gemfile-rails.4.0.x
|
33
|
+
- gemfiles/Gemfile-rails.4.1.x
|
34
|
+
- gemfiles/Gemfile-rails.4.2.x
|
35
|
+
- lib/active_decorator/config.rb
|
36
|
+
- lib/active_decorator/helpers.rb
|
37
|
+
- lib/active_decorator/monkey/action_controller/base/rescue_from.rb
|
38
|
+
- lib/active_decorator/view_context.rb
|
39
|
+
- lib/generators/rails/decorator_generator.rb
|
40
|
+
- lib/generators/rails/templates/decorator.rb
|
41
|
+
- lib/generators/rspec/decorator_generator.rb
|
42
|
+
- lib/generators/rspec/templates/decorator_spec.rb
|
43
|
+
- lib/generators/test_unit/decorator_generator.rb
|
44
|
+
- lib/generators/test_unit/templates/decorator_test.rb
|
45
|
+
- lib/lulalala_presenter.rb
|
46
|
+
- lib/lulalala_presenter/active_model_bridge.rb
|
47
|
+
- lib/lulalala_presenter/base.rb
|
48
|
+
- lib/lulalala_presenter/railtie.rb
|
49
|
+
- lib/lulalala_presenter/version.rb
|
50
|
+
- lulalala_presenter.gemspec
|
51
|
+
- spec/configuration_spec.rb
|
52
|
+
- spec/controllers/fake_detection_spec.rb
|
53
|
+
- spec/fake_app/app/views/authors/index.html.erb
|
54
|
+
- spec/fake_app/app/views/authors/show.html.erb
|
55
|
+
- spec/fake_app/app/views/authors/show.json.jbuilder
|
56
|
+
- spec/fake_app/app/views/book_mailer/thanks.text.erb
|
57
|
+
- spec/fake_app/app/views/books/_book.html.erb
|
58
|
+
- spec/fake_app/app/views/books/_book.json.jbuilder
|
59
|
+
- spec/fake_app/app/views/books/_book_locals.html.erb
|
60
|
+
- spec/fake_app/app/views/books/error.html.erb
|
61
|
+
- spec/fake_app/app/views/books/index.html.erb
|
62
|
+
- spec/fake_app/app/views/books/purchase.html.erb
|
63
|
+
- spec/fake_app/app/views/books/show.html.erb
|
64
|
+
- spec/fake_app/app/views/movies/show.html.erb
|
65
|
+
- spec/fake_app/fake_app.rb
|
66
|
+
- spec/features/action_view_helpers_spec.rb
|
67
|
+
- spec/features/controller_ivar_spec.rb
|
68
|
+
- spec/features/jbuilder_spec.rb
|
69
|
+
- spec/features/partial_spec.rb
|
70
|
+
- spec/spec_helper.rb
|
71
|
+
homepage: https://github.com/lulalala/lulalala_presenter
|
72
|
+
licenses: []
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 2.4.5
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: A simple and Rubyish view helper for Rails
|
94
|
+
test_files:
|
95
|
+
- spec/configuration_spec.rb
|
96
|
+
- spec/controllers/fake_detection_spec.rb
|
97
|
+
- spec/fake_app/app/views/authors/index.html.erb
|
98
|
+
- spec/fake_app/app/views/authors/show.html.erb
|
99
|
+
- spec/fake_app/app/views/authors/show.json.jbuilder
|
100
|
+
- spec/fake_app/app/views/book_mailer/thanks.text.erb
|
101
|
+
- spec/fake_app/app/views/books/_book.html.erb
|
102
|
+
- spec/fake_app/app/views/books/_book.json.jbuilder
|
103
|
+
- spec/fake_app/app/views/books/_book_locals.html.erb
|
104
|
+
- spec/fake_app/app/views/books/error.html.erb
|
105
|
+
- spec/fake_app/app/views/books/index.html.erb
|
106
|
+
- spec/fake_app/app/views/books/purchase.html.erb
|
107
|
+
- spec/fake_app/app/views/books/show.html.erb
|
108
|
+
- spec/fake_app/app/views/movies/show.html.erb
|
109
|
+
- spec/fake_app/fake_app.rb
|
110
|
+
- spec/features/action_view_helpers_spec.rb
|
111
|
+
- spec/features/controller_ivar_spec.rb
|
112
|
+
- spec/features/jbuilder_spec.rb
|
113
|
+
- spec/features/partial_spec.rb
|
114
|
+
- spec/spec_helper.rb
|