Permalink
Browse files

More docs, cleaned up Rakefile dependencies

  • Loading branch information...
Joe Ferris
Joe Ferris committed Dec 2, 2009
1 parent 9246f4d commit 0b05fb51d1e2a02c68b68c338344981451615c8e
Showing with 146 additions and 41 deletions.
  1. +31 −38 Rakefile
  2. +57 −0 lib/effigy/rails.rb
  3. +36 −0 lib/effigy/rails/template_handler.rb
  4. +22 −3 lib/effigy/rails/view.rb
View
@@ -2,35 +2,25 @@ require 'rubygems'
require 'rake'
require 'rake/gempackagetask'
require 'spec/rake/spectask'
desc 'Default: run the specs and metrics.'
task :default => [:spec, :metrics]
Spec::Rake::SpecTask.new do |t|
t.spec_opts = ['--color', '--format', 'progress']
t.libs = %w(spec)
t.ruby_opts = ['-rrubygems']
end
begin
require 'spec/rake/spectask'
task :rails_root do
rails_root = File.join('tmp', 'rails_root')
unless File.exist?(rails_root)
FileUtils.mkdir_p(File.dirname(rails_root))
command = "rails #{rails_root}"
output = `#{command} 2>&1`
if $? == 0
FileUtils.ln_s(FileUtils.pwd, File.join(rails_root, 'vendor', 'plugins'))
else
$stderr.puts "Command failed with status #{$?}:"
$stderr.puts command
$stderr.puts output
end
Spec::Rake::SpecTask.new do |t|
t.spec_opts = ['--color', '--format', 'progress']
t.libs = %w(spec)
t.ruby_opts = ['-rrubygems']
end
end
task :spec => :rails_root
task :spec => :rails_root
rescue LoadError => exception
puts "Missing dependencies for specs"
task :spec do
raise exception
end
end
desc "Remove build files"
task :clean do
@@ -60,34 +50,37 @@ begin
end
Jeweler::GemcutterTasks.new
rescue LoadError
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
puts "Missing dependencies for jeweler"
end
begin
require 'reek/adapters/rake_task'
namespace :metrics do
desc "Run reek"
task "reek" do
namespace :metrics do
desc "Run reek"
begin
require 'reek/adapters/rake_task'
task :reek do
files = FileList['lib/**/*.rb', 'rails/**/*.rb'].to_a.join(' ')
system("reek -q #{files}")
end
rescue LoadError => exception
puts "Missing dependencies for metrics."
task :reek do
puts exception.inspect
end
end
desc "Run all metrics"
task :metrics => ['metrics:reek']
rescue LoadError => e
puts e.inspect
puts "Missing dependencies for metrics."
end
desc "Run all metrics"
task :metrics => ['metrics:reek']
begin
require 'yard'
YARD::Rake::YardocTask.new do |t|
t.files = ['lib/**/*.rb', 'rails/**/*.rb']
end
rescue LoadError => e
puts e.inspect
rescue LoadError => exception
puts "Missing dependencies for yard."
task :yard do
raise exception
end
end
View
@@ -3,4 +3,61 @@
require 'effigy/rails/view'
require 'effigy/rails/template_handler'
module Effigy
# Rails-specific functionality.
#
# Effigy includes Rails generators for generating effigy view and template
# files within Rails projects, as well as a Rails-specific view superclass
# that provides functionality like assigns, layouts, and partials.
#
# Example:
#
# <pre>
# # app/controllers/magic_controller.rb
# class MagicController < ApplicationController
# def index
# @spell = 'hocus pocus'
# end
# end
# </pre>
#
# <pre>
# # app/views/magic/index.html.effigy
# class MagicIndexView < Effigy::Rails::View
# def transform
# text('h1', @spell)
# end
# end
# </pre>
#
# <pre>
# # app/templates/magic/index.html
# <h1>Spell name goes here</h1>
# </pre>
#
# View this example in your browser and you'll see "hocus pocus."
#
# == Generators
#
# Example:
# ./script/generate effigy_view users new edit index
#
# This will generate Effigy views and templates for the "new," "edit," and
# "index," actions of UsersController, such as
# app/views/users/new.html.effigy, and app/templates/users/new.html.
#
# == Rendering Effigy views from Rails
#
# Effigy includes a Rails template handler, so you can render effigy views as normal.
# Rendering the "index" action from "UsersController" will look for a
# UsersIndexView class in app/views/users/index.html.effigy, and use it to
# transform app/templates/users/index.html.
#
# == Effigy Rails views
#
# See {Effigy::Rails::View} for extra methods available to Rails views.
module Rails
end
end
ActionView::Template.register_template_handler :effigy, Effigy::Rails::TemplateHandler
@@ -1,8 +1,24 @@
module Effigy
module Rails
# Adds hooks to Rails to discover Effigy views and templates.
#
# View files should be added to the app/views/<controller> directory with
# an .effigy suffix. Template files should be added to
# app/templates/<controller> with no suffix.
#
# For example, the view and template for PostsController#new would be
# app/views/posts/new.html.effigy and app/templates/posts/new.html,
# respectively.
#
# You can use the packaged generators to create these files.
#
# See {Effigy::Rails} for more information about generators.
class TemplateHandler < ActionView::TemplateHandler
include ActionView::TemplateHandlers::Compilable
# Compiles the given view. Calls by ActionView when loading the view.
# @return [String] Ruby code that can be evaluated to get the rendered
# contents of this view
def compile(view)
@view = view
load_view_class
@@ -22,26 +38,43 @@ def compile(view)
RUBY
end
# @return [String] the name of the view, such as "index"
def view_name
@view.name
end
# @return [String] the path from the view root to the view file. For
# example, "RAILS_ROOT/app/views/users/index.html.effigy" would be
# "users."
def base_path
@view.base_path
end
# Loads the view class from the discovered view file. View classes should
# be named after the controller and action, such as UsersIndexView.
#
# See {#view_class_name} for more information about class names.
def load_view_class
load(@view.filename)
end
# Generates a class name for this view. Normal views are prefixed with
# the controller namd and suffixed with "View," such as "PostsEditView"
# for app/views/posts/edit.html.effigy. Partials are prefixed with the
# controller and suffixed with "Partial," such as "PostsPostPartial" for
# app/views/posts/_post.html.effigy. Layouts are suffixed with "Layout,"
# such as "ApplicationLayout" for
# app/views/layouts/application.html.effigy.
def view_class_name
view_class_components.join('_').camelize.sub(/^Layouts/, '')
end
# @return [Array] the components that make up the class name for this view
def view_class_components
[base_path, view_name.sub(/^_/, ''), view_class_suffix]
end
# @return [String] the suffix for this view based on the type of view
def view_class_suffix
if layout?
'layout'
@@ -52,14 +85,17 @@ def view_class_suffix
end
end
# @return [Boolean] true-ish if this view is a layout, false-ish otherwise
def layout?
base_path =~ /^layouts/
end
# @return [Boolean] true-ish if this view is a partial, false-ish otherwise
def partial?
@view.name =~ /^_/
end
# @return [String] the contents of the template file for this view
def template_source
template_path = @view.load_path.path.sub(/\/views$/, '/templates')
template_file_name = File.join(template_path, base_path, "#{view_name}.#{@view.format}")
View
@@ -1,10 +1,25 @@
module Effigy
module Rails
# Provides Rails-specific methods to Effigy views. Rather than
# instantiating this class directly, it is recommended that you create view
# and template files and allow {Effigy::Rails::TemplateHandler} to discover
# and compile views.
#
# Instance variables from controller actions will be copied to the view.
class View < ::Effigy::View
# [ActionView::Base] the instance that is rendering this view
# [ActionView::Base] the instance that is rendering this view. This
# instance is used to render partials and access other information about
# the action being rendered.
attr_reader :action_view
# The passed block will be called to access content captured by
# content_for, such as layout contents.
#
# @param [ActionView::Base] action_view the instance that is rendering
# this view. See the action_view attribute.
# @param [Hash] assigns a hash of instance variables to be copied. Names
# should include the "@" prefix.
def initialize(action_view, assigns, &layout_block)
@action_view = action_view
@@ -21,13 +36,17 @@ def initialize(action_view, assigns, &layout_block)
# @param [Hash] options
# @option options [Hash] :locals a hash of extra variables to be assigned
# on the partial view
# @return [String] the rendered contents from the partial
def partial(name, options = {})
options[:partial] = name
action_view.render(options)
end
protected
# Returns the captured content of the given name. Use "layout" as a name
# to access the contents for the layout.
#
# @param [Symbol] capture the name of the captured content to return
# @return [String] the captured content of the given name
def content_for(capture)
@layout_block.call(capture)
end

0 comments on commit 0b05fb5

Please sign in to comment.