lulalala_presenter 0.0.1
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.
- 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
|