diff --git a/Readme.markdown b/Readme.markdown index d2e19e3..c0e19c9 100644 --- a/Readme.markdown +++ b/Readme.markdown @@ -6,22 +6,30 @@ ## Quick Start 1. Add `gem 'draper'` to your `Gemfile` and `bundle` -2. Run `rails g draper:install` to create the directory and `ApplicationDecorator` -3. Run `rails g draper:decorator YourModel` -4. Edit `app/decorators/[your_model]_decorator.rb` using: +2. Run `rails g draper:decorator YourModel` +3. Edit `app/decorators/[your_model]_decorator.rb` using: 1. `h` to proxy to Rails/application helpers like `h.current_user` 2. `[your_model]` to access the wrapped object like `article.created_at` -5. Put common decorations in `app/decorators/application.rb` -6. Wrap models in your controller with the decorator using: +4. Wrap models in your controller with the decorator using: 1. `.find` automatic lookup & wrap ex: `ArticleDecorator.find(1)` 2. `.decorate` method with single object or collection, ex: `ArticleDecorator.decorate(Article.all)` 3. `.new` method with single object ex: `ArticleDecorator.new(Article.first)` -7. Output the instance methods in your view templates +5. Output the instance methods in your view templates ex: `@article_decorator.created_at` +If you need common methods in your decorators, create an `app/decorators/application_decorator.rb`: + +``` ruby +class ApplicationDecorator < Draper::Base + # your methods go here +end +``` + +and make your decorators inherit from it. Newly generated decorators will respect this choice and inherit from `ApplicationDecorator`. + ## Watch the RailsCast Ryan Bates has put together an excellent RailsCast on Draper based on the 0.8.0 release: diff --git a/lib/draper.rb b/lib/draper.rb index 318c739..e76c959 100644 --- a/lib/draper.rb +++ b/lib/draper.rb @@ -8,3 +8,14 @@ require 'draper/view_context' require 'draper/decorated_enumerable_proxy' require 'draper/rspec_integration' if defined?(RSpec) and RSpec.respond_to?(:configure) require 'draper/railtie' if defined?(Rails) + +if defined?(Rails) + module ActiveModel + class Railtie < Rails::Railtie + generators do |app| + Rails::Generators.configure!(app.config.generators) + require "generators/resource_override" + end + end + end +end diff --git a/lib/generators/decorator/decorator_generator.rb b/lib/generators/decorator/decorator_generator.rb new file mode 100644 index 0000000..eb5963f --- /dev/null +++ b/lib/generators/decorator/decorator_generator.rb @@ -0,0 +1,28 @@ +module Rails + module Generators + class DecoratorGenerator < NamedBase + source_root File.expand_path("../templates", __FILE__) + check_class_collision :suffix => "Decorator" + + class_option :parent, :type => :string, :desc => "The parent class for the generated decorator" + + def create_decorator_file + template 'decorator.rb', File.join('app/decorators', class_path, "#{file_name}_decorator.rb") + end + + hook_for :test_framework + + private + + def parent_class_name + if options[:parent] + options[:parent] + elsif defined?(:ApplicationDecorator) + "ApplicationDecorator" + else + "Draper::Base" + end + end + end + end +end diff --git a/lib/generators/draper/templates/decorator.rb b/lib/generators/decorator/templates/decorator.rb similarity index 90% rename from lib/generators/draper/templates/decorator.rb rename to lib/generators/decorator/templates/decorator.rb index 0f49a46..1ef2a31 100644 --- a/lib/generators/draper/templates/decorator.rb +++ b/lib/generators/decorator/templates/decorator.rb @@ -1,4 +1,5 @@ -class <%= singular_name.camelize %>Decorator < ApplicationDecorator +<% module_namespacing do -%> +class <%= class_name %>Decorator < ApplicationDecorator decorates :<%= singular_name %> # Accessing Helpers @@ -30,3 +31,4 @@ class <%= singular_name.camelize %>Decorator < ApplicationDecorator # :class => 'timestamp' # end end +<% end -%> diff --git a/lib/generators/draper/decorator_generator.rb b/lib/generators/draper/decorator_generator.rb deleted file mode 100644 index 890c2ce..0000000 --- a/lib/generators/draper/decorator_generator.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Draper - module Generators - class DecoratorGenerator < Rails::Generators::NamedBase - source_root File.expand_path('../templates', __FILE__) - - desc <<-DESC - Description: - Generate a decorator for the given model. - Example: rails g draper:decorator Article - generates: "app/decorators/article_decorator" - "spec/decorators/article_decorator_spec" - DESC - - def create_decorator_file - template 'decorator.rb', File.join('app/decorators', "#{singular_name}_decorator.rb") - end - - hook_for :test_framework - end - end -end diff --git a/lib/generators/draper/install_generator.rb b/lib/generators/draper/install_generator.rb deleted file mode 100644 index d4dfe86..0000000 --- a/lib/generators/draper/install_generator.rb +++ /dev/null @@ -1,20 +0,0 @@ -module Draper - module Generators - class InstallGenerator < Rails::Generators::Base - source_root File.expand_path('../templates', __FILE__) - - desc <<-DESC - Description: - Generate application and spec decorators in your application. - DESC - - def create_decorator_file - template 'application_decorator.rb', File.join('app/decorators', 'application_decorator.rb') - end - - hook_for :test_framework, :as => :decorator do |test_framework| - invoke test_framework, ['application'] - end - end - end -end diff --git a/lib/generators/draper/templates/application_decorator.rb b/lib/generators/draper/templates/application_decorator.rb deleted file mode 100644 index 74151a3..0000000 --- a/lib/generators/draper/templates/application_decorator.rb +++ /dev/null @@ -1,28 +0,0 @@ -class ApplicationDecorator < Draper::Base - # Lazy Helpers - # PRO: Call Rails helpers without the h. proxy - # ex: number_to_currency(model.price) - # CON: Add a bazillion methods into your decorator's namespace - # and probably sacrifice performance/memory - # - # Enable them by uncommenting this line: - # lazy_helpers - - # Shared Decorations - # Consider defining shared methods common to all your models. - # - # Example: standardize the formatting of timestamps - # - # def formatted_timestamp(time) - # h.content_tag :span, time.strftime("%a %m/%d/%y"), - # :class => 'timestamp' - # end - # - # def created_at - # formatted_timestamp(model.created_at) - # end - # - # def updated_at - # formatted_timestamp(model.updated_at) - # end -end diff --git a/lib/generators/draper/templates/application_decorator_spec.rb b/lib/generators/draper/templates/application_decorator_spec.rb deleted file mode 100644 index 729c80a..0000000 --- a/lib/generators/draper/templates/application_decorator_spec.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'spec_helper' - -describe ApplicationDecorator do -end diff --git a/lib/generators/draper/templates/application_decorator_test.rb b/lib/generators/draper/templates/application_decorator_test.rb deleted file mode 100644 index d77ec0a..0000000 --- a/lib/generators/draper/templates/application_decorator_test.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'test_helper' - -class ApplicationDecoratorTest < ActiveSupport::TestCase - def setup - ApplicationController.new.set_current_view_context - end - - # test "the truth" do - # assert true - # end -end diff --git a/lib/generators/resource_override.rb b/lib/generators/resource_override.rb new file mode 100644 index 0000000..40a85ce --- /dev/null +++ b/lib/generators/resource_override.rb @@ -0,0 +1,12 @@ +require "rails/generators" +require "rails/generators/rails/resource/resource_generator" + +module Rails + module Generators + ResourceGenerator.class_eval do + def add_decorator + invoke "decorator" + end + end + end +end diff --git a/lib/generators/rspec/templates/decorator_spec.rb b/lib/generators/rspec/templates/decorator_spec.rb index eb4eedc..6acbd52 100644 --- a/lib/generators/rspec/templates/decorator_spec.rb +++ b/lib/generators/rspec/templates/decorator_spec.rb @@ -1,4 +1,4 @@ require 'spec_helper' -describe <%= singular_name.camelize %>Decorator do +describe <%= class_name %>Decorator do end diff --git a/lib/generators/test_unit/templates/decorator_test.rb b/lib/generators/test_unit/templates/decorator_test.rb index 42a1ef1..164ea01 100644 --- a/lib/generators/test_unit/templates/decorator_test.rb +++ b/lib/generators/test_unit/templates/decorator_test.rb @@ -1,11 +1,7 @@ require 'test_helper' -class <%= singular_name.camelize %>DecoratorTest < ActiveSupport::TestCase +class <%= class_name %>DecoratorTest < ActiveSupport::TestCase def setup ApplicationController.new.set_current_view_context end - - # test "the truth" do - # assert true - # end end diff --git a/spec/generators/draper/decorator/decorator_generator_spec.rb b/spec/generators/decorator/decorator_generator_spec.rb similarity index 94% rename from spec/generators/draper/decorator/decorator_generator_spec.rb rename to spec/generators/decorator/decorator_generator_spec.rb index c035b98..04418a7 100644 --- a/spec/generators/draper/decorator/decorator_generator_spec.rb +++ b/spec/generators/decorator/decorator_generator_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' # Generators are not automatically loaded by Rails -require 'generators/draper/decorator_generator' +require 'generators/decorator/decorator_generator' -describe Draper::Generators::DecoratorGenerator do +describe Rails::Generators::DecoratorGenerator do # Tell the generator where to put its output (what it thinks of as Rails.root) destination File.expand_path("../../../../../tmp", __FILE__) diff --git a/spec/generators/draper/install/install_generator_spec.rb b/spec/generators/draper/install/install_generator_spec.rb deleted file mode 100644 index c8e92d9..0000000 --- a/spec/generators/draper/install/install_generator_spec.rb +++ /dev/null @@ -1,48 +0,0 @@ -require 'spec_helper' - -# Generators are not automatically loaded by Rails -require 'generators/draper/install_generator' - -describe Draper::Generators::InstallGenerator do - # Tell the generator where to put its output (what it thinks of as Rails.root) - destination File.expand_path("../../../../../tmp", __FILE__) - - before { prepare_destination } - - context 'using rspec' do - before do - run_generator ['', "-t=rspec"] - end - - shared_examples_for "ApplicationDecoratorGenerator" do - describe 'app/decorators/application_decorator.rb' do - subject { file('app/decorators/application_decorator.rb') } - it { should exist } - it { should contain "class ApplicationDecorator < Draper::Base" } - end - end - - describe 'spec/decorators/application_decorator_spec.rb' do - subject { file('spec/decorators/application_decorator_spec.rb') } - it { should exist } - it { should contain "describe ApplicationDecorator do" } - end - end - - context "using test_unit" do - before { run_generator ["", "-t=test_unit"] } - - it_should_behave_like "ApplicationDecoratorGenerator" - - describe 'spec/decorators/application_decorator_spec.rb' do - subject { file('spec/decorators/application_decorator_spec.rb') } - it { should_not exist } - end - - describe 'spec/decorators/application_decorator_test.rb' do - subject { file('test/decorators/application_decorator_test.rb') } - it { should exist } - end - end - -end