Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Updated with latest version of website + markdown

  • Loading branch information...
commit b50df183567400983c77c46a3f188cd24fd394bd 1 parent 4421dfd
@DAddYE DAddYE authored
Showing with 7,189 additions and 7,850 deletions.
  1. +7 −0 Gemfile
  2. +5 −80 README.md
  3. +75 −0 Rakefile
  4. +0 −61 guides/3rd-party-plugins.textile
  5. +528 −0 guides/adding-new-components.md
  6. +0 −645 guides/adding-new-components.textile
  7. +729 −0 guides/application-helpers.md
  8. +0 −675 guides/application-helpers.textile
  9. +66 −0 guides/asynchronous-concurrency-with-padrino.md
  10. +124 −0 guides/basic-projects.md
  11. +0 −132 guides/basic-projects.textile
  12. +626 −0 guides/blog-tutorial.md
  13. +0 −707 guides/blog-tutorial.textile
  14. +8 −0 guides/caching-support.md
  15. +0 −7 guides/caching-support.textile
  16. +404 −0 guides/controllers.md
  17. +0 −448 guides/controllers.textile
  18. +132 −0 guides/development-commands.md
  19. +0 −158 guides/development-commands.textile
  20. +26 −0 guides/examples.md
  21. +0 −19 guides/examples.textile
  22. +0 −26 guides/exception-handling.textile
  23. +28 −0 guides/extensions.md
  24. +0 −26 guides/extensions.textile
  25. +384 −0 guides/generators.md
  26. +0 −407 guides/generators.textile
  27. +169 −0 guides/getting-started.md
  28. +0 −197 guides/getting-started.textile
  29. +52 −0 guides/home.md
  30. +0 −57 guides/home.textile
  31. +18 −0 guides/installation.md
  32. +0 −15 guides/installation.textile
  33. +120 −0 guides/localization.md
  34. +0 −140 guides/localization.textile
  35. +38 −0 guides/mounting-applications.md
  36. +0 −43 guides/mounting-applications.textile
  37. +111 −0 guides/padrino-admin.md
  38. +0 −123 guides/padrino-admin.textile
  39. +346 −0 guides/padrino-cache.md
  40. +0 −415 guides/padrino-cache.textile
  41. +195 −0 guides/padrino-mailer.md
  42. +0 −233 guides/padrino-mailer.textile
  43. +176 −0 guides/rake-tasks.md
  44. +0 −177 guides/rake-tasks.textile
  45. +89 −0 guides/running-padrino-on-jruby.md
  46. +0 −193 guides/running-padrino-on-jruby.textile
  47. +135 −0 guides/standalone-usage-in-sinatra.md
  48. +0 −140 guides/standalone-usage-in-sinatra.textile
  49. +103 −0 guides/the-bleeding-edge.md
  50. +0 −102 guides/the-bleeding-edge.textile
  51. +8 −0 pages/admin.md
  52. +0 −6 pages/admin.textile
  53. +27 −0 pages/agnostic.md
  54. +0 −26 pages/agnostic.textile
  55. +23 −0 pages/comprehensive.md
  56. +0 −31 pages/comprehensive.textile
  57. +65 −0 pages/contribute.md
  58. +0 −61 pages/contribute.textile
  59. +24 −0 pages/drop-in-admin.md
  60. +0 −22 pages/drop-in-admin.textile
  61. +13 −0 pages/home-code.md
  62. +0 −11 pages/home-code.textile
  63. +20 −0 pages/home.md
  64. +0 −19 pages/home.textile
  65. +19 −0 pages/lightweight.md
  66. +0 −20 pages/lightweight.textile
  67. +24 −0 pages/mic.md
  68. +0 −20 pages/mic.textile
  69. +12 −0 pages/sinatra-core.md
  70. +0 −15 pages/sinatra-core.textile
  71. +8 −0 pages/slogan.md
  72. +0 −6 pages/slogan.textile
  73. +12 −0 pages/team.md
  74. +0 −13 pages/team.textile
  75. +315 −0 pages/why.md
  76. +0 −340 pages/why.textile
  77. +24 −92 posts/addressing-concerns-about-padrino.md
  78. +17 −0 posts/code-tv-padrino-code-school.md
  79. +14 −0 posts/darío-cravero-joins-the-padrino-core-team.md
  80. +17 −21 posts/euruko-2011-is-coming-who-s-up-for-a-meeting.md
  81. +22 −24 posts/fikus-cms.md
  82. +26 −0 posts/hosting-our-first-padrino-meetup-in-san-francisco.md
  83. +10 −10 posts/introducing-padrino.md
  84. +22 −0 posts/json-gem-vulnerability.md
  85. +56 −120 posts/looking-at-projects-using-padrino.md
  86. +11 −18 posts/o-reilly-sinatra-up-and-running-book.md
  87. +103 −180 posts/padrino-0-10-0-routing-upgrades-rbx-and-jruby-support-and-minor-breaking-changes.md
  88. +30 −61 posts/padrino-0-10-1-mongo-cache-store-routing-translation-and-bug-fixes.md
  89. +31 −58 posts/padrino-0-10-2-activesupport-3-1-travisci-support-routing-and-misc-bug-fixes-galore.md
  90. +104 −0 posts/padrino-0-10-3-sinatra-1-3-documentation-minitest-improved-logger-and-more.md
  91. +39 −0 posts/padrino-0-10-4-hot-fix-release-yard-documentation-and-more.md
  92. +74 −0 posts/padrino-0-10-6-activesupport-3-2-minirecord-html5-helpers-and-bug-fixes.md
  93. +34 −0 posts/padrino-0-10-7-reloader-jruby-helpers-and-other-bug-fixes.md
  94. +269 −0 posts/padrino-0-11-0-released-padrino-lives.md
  95. +109 −181 posts/padrino-0-9-10-released-built-for-speed.md
  96. +121 −184 posts/padrino-0-9-11-release-overview.md
  97. +17 −32 posts/padrino-0-9-13-gets-pushed-early.md
  98. +16 −20 posts/padrino-0-9-14-important-hotfixes.md
  99. +28 −41 posts/padrino-0-9-15-release-new-core-member.md
  100. +26 −21 posts/padrino-0-9-16-important-hotfixes-to-the-admin.md
  101. +11 −6 posts/padrino-0-9-17.md
  102. +11 −6 posts/padrino-0-9-18-fixes.md
  103. +38 −19 posts/padrino-0-9-19-sinatra-1-1-compat-screencast.md
  104. +23 −42 posts/padrino-0-9-20-now-works-with-sinatra-1-2.md
  105. +50 −64 posts/padrino-0-9-21-nested-forms-translations-and-more.md
  106. +23 −41 posts/padrino-0-9-22-quick-followup-release.md
  107. +11 −2 posts/padrino-0-9-23-sinatra-1-2-compatibility.md
  108. +131 −254 posts/padrino-0-9-25-slim-and-erubis-caching-and-fixes.md
  109. +23 −50 posts/padrino-0-9-26-hotfix-release.md
  110. +45 −72 posts/padrino-0-9-27-project-settings-routing-compatibility-and-bug-fixes.md
  111. +14 −19 posts/padrino-0-9-28-reloader-compatibility-and-bug-fixes.md
  112. +42 −95 posts/padrino-0-9-29-stability-compatibility-and-bug-fix-release.md
  113. +10 −14 posts/padrino-0-9-9-released-with-screencast.md
  114. +105 −155 posts/padrino-and-omniauth-overview.md
  115. +12 −23 posts/padrino-gets-interviewed-by-thechangelog.md
  116. +23 −45 posts/padrino-moving-forward.md
  117. +10 −3 posts/padrino-slides.md
  118. +12 −15 posts/padrino-user-resources-and-screencasts.md
  119. +11 −19 posts/padrino-weekly-issue-1-announcing-padrino-weekly-changelog-podcast-0-9-11-13-released.md
  120. +9 −11 posts/padrino-weekly-issue-2-simple-apps-website-now-open-source.md
  121. +18 −16 posts/padrino-welcomes-new-core-contributors.md
  122. +39 −0 posts/sleep-well-yaml-vulnerabilites-and-padrino.md
  123. +18 −0 posts/thank-you-steve.md
  124. +16 −0 posts/upgrade-rack-immediately.md
View
7 Gemfile
@@ -0,0 +1,7 @@
+# A sample Gemfile
+source "https://rubygems.org"
+
+gem 'bson_ext'
+gem 'net-ssh-gateway'
+gem 'mongo'
+gem 'pandoc-ruby'
View
85 README.md
@@ -7,87 +7,12 @@ Feel free to fork it, apply your corrections or make a useful translation.
* Word wrap must be set to 110
* Encoding UTF-8
-## Internal Links
+## Syntax
-```
-[[Page Title]]
-```
+[GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown)
-## Code Highlighting:
+## Author(s)
-```
-pre[ruby], pre[html], pre[bash], pre[erb]
-```
+* [DAddYE](https://github.com/daddye), articles, guides, code.
-## Phrase modifiers:
-
-```
-_emphasis_
-*strong*
-__italic__
-**bold**
-??citation??
-- deleted text -
-+ inserted text +
-^ superscript ^
-~ subscript ~
-%span%
-@code@
-```
-
-## Block modifiers:
-
-```
-h n . heading
-bq. Blockquote
-fn n . Footnote
-p. Paragraph
-bc. Block code
-pre. Pre-formatted
-# Numeric list
-* Bulleted list
-```
-
-## Links:
-
-```
-"linktext":http://...
-```
-
-## Punctuation:
-
-```
-"quotes" → “quotes”
-'quotes' → ‘quotes’
-it's → it's
-em -- dash → it’s
-en - dash → en em — dash
-2 x 4 → 2 2 × 4
-foo(tm) → foo™
-foo(r) → foo®
-foo(c) → foo©
-```
-
-## Alignment:
-
-```
-> right
-< left
-= center
-<> justify
-```
-
-## Tables:
-
-```
-|_. a|_. table|_. header|
-|a|table|row|
-|a|table|row|
-```
-
-## Images:
-
-```
-!imageurl!
-!imageurl!:http://...
-```
+*add_you_here*
View
75 Rakefile
@@ -0,0 +1,75 @@
+require 'bundler/setup'
+require 'mongo'
+require 'net/ssh/gateway'
+require 'yaml'
+require 'pandoc-ruby'
+
+def on_remote(&block)
+ gateway = Net::SSH::Gateway.new('lps2.lipsiasoft.com', 'root')
+
+ # Open port 27018 to forward to 127.0.0.1:27017
+ # on the remote host provided above
+ gateway.open('127.0.0.1', 27017, 27018)
+
+ # Connect to local port set in previous statement
+ conn = Mongo::Connection.new('127.0.0.1', 27018)
+ @_db = conn['padrino_www']
+
+ # Invoke block with current db
+ yield @_db
+
+ # Just printing out stats to show that it works
+ # p conn.db('padrino_www').stats
+ensure
+ gateway.shutdown!
+end
+
+def db
+ @_db
+end
+
+def category_name(id)
+ cat = db['categories'].find_one(_id: id)
+ cat['name'] if cat
+end
+
+def convert(code, *args)
+ args.push({ from: :html, to: 'markdown_github+fenced_code_blocks', columns: 110 }, 'atx-headers', 'normalize')
+ PandocRuby.convert(code, *args)
+end
+
+def gen(kind, doc)
+ account = db['accounts'].find_one(_id: doc['author_id'])
+ categories = doc['category_ids'] ? doc['category_ids'].map(&method(:category_name)) : []
+ metadata = {}
+ metadata['date'] = Date.parse(doc['created_at'].to_s)
+ metadata['author'] = account['name']
+ metadata['email'] = account['email']
+ metadata['categories'] = categories.join(', ') unless categories.empty?
+ metadata['tags'] = doc['tags'] if doc['tags']
+ metadata['title'] = doc['title'].strip.gsub(/\r|\n/, '')
+
+ file = "./#{kind}/#{doc['permalink']}.md"
+ puts " writing #{file} ..."
+
+ File.open(file, 'w') do |f|
+ f.write YAML.dump(metadata)
+ f.puts '---'
+ f.puts
+ if doc['summary_html'] && !doc['summary_html'].empty?
+ f.write convert(doc['summary_html'])
+ f.write "\n\n<break>\n\n" unless doc['body_html'].nil? || doc['body_html'].empty?
+ end
+ f.write convert(doc['body_html'])
+ end
+end
+
+desc 'Download new stuff'
+task :download do
+ on_remote do
+ %w[posts guides pages].each do |kind|
+ puts "Downloading #{kind} ..."
+ db[kind].find.each { |doc| gen(kind, doc) }
+ end
+ end
+end
View
61 guides/3rd-party-plugins.textile
@@ -1,61 +0,0 @@
----
-:author: Foo Bar
-:title: 3rd Party Plugins
----
-Padrino is a modular framework. As such, you can leverage other libraries such as Sinatra libraries which
-complement Padrino quite well.
-
-h2. Rendering JSON with sinatra-contrib
-
-First you must reference ["sinatra-contrib":https://github.com/sinatra/sinatra-contrib] in your Gemfile:
-
-<pre lang="ruby"><code>
-#Gemfile
-source :rubygems
-
-# Server requirements
-# gem 'thin' # or mongrel
-# gem 'trinidad', :platform => 'jruby'
-
-# Project requirements
-gem 'rake'
-gem 'sinatra-flash', :require => 'sinatra/flash'
-
-# Component requirements
-gem 'haml'
-
-# Test requirements
-
-# Padrino Stable Gem
-gem 'padrino', :path => '~/Desktop/code/padrino-framework'
-
-# Or Padrino Edge
-# gem 'padrino', :git => 'git://github.com/padrino/padrino-framework.git'
-
-# Or Individual Gems
-# %w(core gen helpers cache mailer admin).each do |g|
-# gem 'padrino-' + g, '0.10.7'
-# end
-
-gem 'sinatra-contrib'
-</code></pre>
-
-
-You may use the #json method after you have registered the sinatra helper:
-
-<pre lang="ruby"><code>
-class MyJsonApp < Padrino::Application
- register Padrino::Rendering
- register Padrino::Mailer
- register Padrino::Helpers
-
-
- helpers Sinatra::JSON
-
- enable :sessions
- get '/' do
- hash = {foo: 'bar'}
- json hash
- end
-end
-</code></pre>
View
528 guides/adding-new-components.md
@@ -0,0 +1,528 @@
+---
+date: 2010-04-06
+author: Nathan
+email: nesquena@gmail.com
+title: Adding New Components
+---
+
+Padrino is an agnostic web framework. This means that the framework has been built from the ground up to easily allow support for any arbitrary number of different developer choices with respect to object permanance, stylesheet templaters, javascript libraries, testing libraries, mocking libraries and rendering engines. For a detailed overview of the available components, check out the [generators guide](/guides/generators).
+
+Although Padrino is fundamentally agnostic, in practice only a very limited set of available components have actually been integrated into the Padrino generator and admin dashboard. The set of available components is determined by libraries actually used or noted by the core developers and the existing community. However, adding additional components to Padrino is not only possible but highly recommended. In fact, this is possibly *the best* way for a developer to get started [contributing to Padrino](http://www.padrinorb.com/pages/contribute).
+
+This guide will outline in detail how to properly contribute new components to Padrino and get them included into the next Padrino generator as quickly and efficiently as possible.
+
+
+## Persistence Engine
+
+Contributing an object persistence library is probably the most involved component to integrate with Padrino. For this guide, let us pretend that we would like to integrate `Datamapper` into Padrino. First, let’s add `Datamapper` to the project generator’s available components in [padrino-gen/generators/project.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L28):
+
+ # padrino-gen/lib/padrino-gen/generators/project.rb
+ component_option :orm, "database engine", :choices => [:activerecord, :datamapper]
+
+Here, we needed to append `:datamapper` as an option for the `:orm` component\_option in the project generator. Once we have defined datamapper as an option for the orm component, let’s actually define the specific integration tasks for the generator in [padrino-gen/generators/components/orms/datamapper.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/orms/datamapper.rb):
+
+ # padrino-gen/lib/padrino-gen/generators/components/orms/datamapper.rb
+ # These are the steps to setup the persistence layer in the initial project
+ # such as requiring certain gems, constructing the database.rb configuration file
+ # and creating the models folder for the application
+ def setup_orm
+ require_dependencies 'data_objects', 'do_sqlite3', 'datamapper'
+ create_file("config/database.rb", DM)
+ empty_directory('app/models')
+ end
+
+ # These are the steps to generate the actual model file
+ # when the model generator is executed.
+ #
+ # create_model_file("account", ["username:string", "password:string"])
+ def create_model_file(name, fields)
+ # ...truncated...
+ create_file(model_path, model_contents)
+ end
+
+ # These are the steps to generate the model migration file
+ # when the model generator is executed.
+ #
+ # create_model_migration("create_accounts", "account", ["username:string"])
+ def create_model_migration(migration_name, name, columns)
+ # ...truncated...
+ end
+
+ # These are the steps to generate the db migration file
+ # when the migration generator is executed.
+ #
+ # create_migration_file("AddEmailToAccount", "AddEmailToAccount", ["email:string"])
+ def create_migration_file(migration_name, name, columns)
+ # ...truncated...
+ end
+
+Next, if the persistence engine needs to include useful rake tasks (to migrate or modify the database for instance), you can add these to the `padrino-tasks` folder in the `padrino-gen` gem. For Datamapper, there are a number of tasks that should be available in [padrino-tasks/datamapper.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/padrino-tasks/datamapper.rb):
+
+ # padrino-gen/lib/padrino-gen/padrino-tasks/datamapper.rb
+ if defined?(DataMapper)
+ namespace :dm do
+ namespace :migrate do
+ task :load => :environment do
+ # ...truncated...
+ end
+
+ desc "Migrate up using migrations"
+ task :up, :version, :needs => :load do |t, args|
+ # ...truncated...
+ end
+ end
+ end
+ end
+
+Next, let’s add the appropriate unit tests to ensure our new component works as intended in [padrino-gen/test/test\_project\_generator.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L129):
+
+ # padrino-gen/test/test_project_generator.rb
+ should "properly generate default for datamapper" do
+ buffer = silence_logger {@project.start(['sample_project', '--root=/tmp', '--orm=datamapper'])}
+ assert_match /Applying.*?datamapper.*?orm/, buffer
+ assert_match_in_file(/gem 'data_objects'/, '/tmp/sample_project/Gemfile')
+ assert_match_in_file(/gem 'datamapper'/, '/tmp/sample_project/Gemfile')
+ assert_match_in_file(/DataMapper.setup/, '/tmp/sample_project/config/database.rb')
+ assert_dir_exists('/tmp/sample_project/app/models')
+ end
+
+Finally for the generator integration, we should add the available option to the [generator README file](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc):
+
+ # padrino-gen/README.rdoc
+ orm:: none (default), mongomapper, mongoid, activerecord, sequel, couchrest, datamapper
+
+and with that update to the README, persistence support for the generator is complete. However, to be fully compliant, support for Padrino Admin should also be added. This will allow the admin dashboard to work properly with your persistence engine of choice and is **highly** recommended.
+
+Adding `padrino-admin` support for your persistence engine is actually fairly straightforward. First, let’s add `Datamapper` to the set of supported admin orm engines in [padrino-admin/generators/actions.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-admin/lib/padrino-admin/generators/actions.rb#L17):
+
+ # padrino-admin/lib/padrino-admin/generators/actions.rb
+ def supported_orm
+ [:activerecord, :mongomapper, :mongoid, :couchrest, :datamapper]
+ end
+
+Next, we need to define the interaction methods available by our persistence engine on our models in [padrino-admin/generators/orm.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-admin/lib/padrino-admin/generators/orm.rb):
+
+ # padrino-admin/lib/padrino-admin/generators/orm.rb
+ module Padrino
+ module Admin
+ module Generators
+ class OrmError < StandardError; end
+ class Orm
+ attr_reader :klass_name, :klass, :name_plural, :name_singular, :orm
+
+ def initialize(name, orm, columns=nil, column_fields=nil)
+ # ...truncated...
+ end
+
+ # Defines access to a model's columns
+ def columns
+ @columns ||= case orm
+ when :activerecord then @klass.columns
+ when :datamapper then @klass.properties
+ else raise OrmError, "Adapter #{orm} is not yet supported!"
+ end
+ end
+
+ # Defines access to retrieving all existing records for a model.
+ def all
+ "#{klass_name}.all"
+ end
+
+ # Defines access for querying records for a model.
+ def find(params=nil)
+ case orm
+ when :activerecord then "#{klass_name}.find(#{params})"
+ when :datamapper then "#{klass_name}.get(#{params})"
+ else raise OrmError, "Adapter #{orm} is not yet supported!"
+ end
+ end
+
+ # Defines how to build a new record for a model.
+ def build(params=nil)
+ if params
+ "#{klass_name}.new(#{params})"
+ else
+ "#{klass_name}.new"
+ end
+ end
+
+ # Defines how to save a new record for a model.
+ def save
+ "#{name_singular}.save"
+ end
+
+ # Defines how to update attributes of a record for a model.
+ def update_attributes(params=nil)
+ case orm
+ when :activerecord then "#{name_singular}.update_attributes(#{params})"
+ when :datamapper then "#{name_singular}.update(#{params})"
+ else raise OrmError, "Adapter #{orm} is not yet supported!"
+ end
+ end
+
+ # Defines how to destroy a record for a model.
+ def destroy
+ "#{name_singular}.destroy"
+ end
+ end # Orm
+ end # Generators
+ end # Admin
+ end # Padrino
+
+Next, we need to describe how the `Account` model should be defined for our persistence engine within [padrino-admin/generators/templates/account/datamapper.rb.tt](http://github.com/padrino/padrino-framework/blob/master/padrino-admin/lib/padrino-admin/generators/templates/account/datamapper.rb.tt):
+
+ # padrino-admin/lib/padrino-admin/generators/templates/account/datamapper.rb.tt
+ class Account
+ include DataMapper::Resource
+ include DataMapper::Validate
+ attr_accessor :password, :password_confirmation
+
+ # Define Properties
+ property :id, Serial
+ property :name, String
+ # ...truncated...
+
+ # Define Validations
+ validates_present :email, :role
+ # ...truncated...
+
+ # Callbacks
+ before :save, :generate_password
+
+ ##
+ # This method is for authentication purpose
+ #
+ def self.authenticate(email, password)
+ account = first(:conditions => { :email => email }) if email.present?
+ account && account.password_clean == password ? account : nil
+ end
+
+ ##
+ # This method is used from AuthenticationHelper
+ #
+ def self.find_by_id(id)
+ get(id) rescue nil
+ end
+
+ ##
+ # This method is used for retrive the original password.
+ #
+ def password_clean
+ crypted_password.decrypt(salt)
+ end
+
+ private
+ def generate_password
+ return if password.blank?
+ self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{email}--") if new?
+ self.crypted_password = password.encrypt(self.salt)
+ end
+
+ def password_required
+ crypted_password.blank? || !password.blank?
+ end
+ end
+
+Finally, let’s update the `padrino-admin` README file at [padrino-admin/README.rdoc](http://github.com/padrino/padrino-framework/blob/master/padrino-admin/README.rdoc) to reflect our newly support component:
+
+ # padrino-admin/README.rdoc
+ Orm Agnostic:: Data Adapters for Datamapper, Activerecord, Mongomapper, Mongoid, Couchrest
+
+This completes the full integration of a persistence engine into Padrino. Once all of this has been finished in your github fork, send us a pull request and assuming you followed these instructions properly and the engine actually works when generated, we will include the component into the next Padrino version crediting you for the contribution!
+
+
+## Javascript Library
+
+Contributing an additional javascript library to Padrino is actually quite straightforward. For this guide, let’s assume we want to add `extcore` as a javascript component integrated into Padrino. First, let’s add `extcore` to the project generator’s available components in [padrino-gen/generators/project.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L31):
+
+ # padrino-gen/lib/padrino-gen/generators/project.rb
+ component_option :script, "javascript library", :choices => [:jquery, :prototype, :extcore]
+
+Next, let’s define the actual integration of the javascript into the generator in [padrino-gen/generators/components/scripts/extcore.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/scripts/extcore.rb):
+
+ # padrino-gen/lib/padrino-gen/generators/components/scripts/extcore.rb
+ def setup_script
+ copy_file('templates/scripts/ext-core.js', destination_root("/public/javascripts/ext-core.js"))
+ create_file(destination_root('/public/javascripts/application.js'), "// Put scripts here")
+ end
+
+This will copy the script into the `public/javascripts` folder of a newly generated project and construct the `application.js` file. Next, let’s copy the latest version of the javascript library to the templates folder:
+
+ # padrino-gen/lib/padrino-gen/generators/templates/scripts/ext-core.js
+ # ...truncated javascript library code here...
+
+Let’s also add a test to ensure the new javascript component generates as expected in [padrino-gen/test/test\_project\_generator.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L198):
+
+ # padrino-gen/test/test_project_generator.rb
+ should "properly generate for ext-core" do
+ buffer = silence_logger{@project.start(['sample_project', '--root=/tmp', '--script=extcore'])}
+ assert_match /Applying.*?extcore.*?script/, buffer
+ assert_file_exists('/tmp/sample_project/public/javascripts/ext-core.js')
+ assert_file_exists('/tmp/sample_project/public/javascripts/application.js'
+ end
+
+and finally let’s update the README for `padrino-gen` to reflect the new component in [padrino-gen/README.rdoc](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc):
+
+ # padrino-gen/README.rdoc
+ script:: none (default), jquery, prototype, mootools, rightjs, extcore
+
+This completes the full integration of a javascript library into Padrino. Once all of this has been finished in your github fork, send us a pull request and assuming you followed these instructions properly and the library actually works when generated, we will include the component into the next Padrino version crediting you for the contribution!
+
+An example of the [actual commit](http://github.com/padrino/padrino-framework/commit/43fb57dd39fa9d860873c14840e68281e314abb8) of the `extcore` javascript library is a great example of how to contribute to Padrino.
+
+In addition to this, you can also provide a UJS adapter which provides ‘remote’ and ‘method’ support to a project using a particular javascript framework. For more information about UJS, check out the [UJS Helpers](http://www.padrinorb.com/guides/application-helpers#unobtrusive-javascript-helpers) guide.
+
+To support UJS in a given javascript framework, simply create a new file such as ‘jquery-ujs’ in your [padrino-static](https://github.com/padrino/padrino-static) fork and then follow the UJS [adapter template](https://github.com/padrino/padrino-static/blob/master/ujs/jquery-ujs.js) used by the existing implementation.
+
+ // ujs/jquery-ujs.js
+ /* Remote Form Support
+ * form_for @user, '/user', :remote => true
+ **/
+ $("form[data-remote=true]").live('submit', function(e) {
+ // ...
+ });
+ /* Confirmation Support
+ * link_to 'sign out', '/logout', :confirm => "Log out?"
+ * Link Remote Support
+ * link_to 'add item', '/create', :remote => true
+ * Link Method Support
+ * link_to 'delete item', '/destroy', :method => :delete
+ **/
+
+ /* JSAdapter */
+ var JSAdapter = {
+ // Sends an xhr request to the specified url with given verb and params
+ // JSAdapter.sendRequest(element, { verb: 'put', url : '...', params: {} });
+ sendRequest : function(element, options) {
+ // ...
+ },
+ // Triggers a particular method verb to be triggered in a form posting to the url
+ // JSAdapter.sendMethod(element);
+ sendMethod : function(element) {
+ // ...
+ }
+ };
+
+Generally the only changes need to be made in the `JSAdapter` js module specifically to implement the `sendRequest` and `sendMethod` functions that are used by all the events to power the UJS functionality.
+
+Once that unobtrusive adapter has been implemented, you can finish by adding the UJS file to the generator in Padrino:
+
+ # padrino-gen/lib/padrino-gen/generators/components/scripts/extcore.rb
+ def setup_script
+ get('https://github.com/padrino/padrino-static/raw/master/js/jquery.js',
+ destination_root("/public/javascripts/jquery.js"))
+ get('https://github.com/padrino/padrino-static/raw/master/ujs/jquery-ujs.js',
+ destination_root("/public/javascripts/jquery-ujs.js"))
+ create_file(destination_root('/public/javascripts/application.js'),
+ "// Put your application scripts here")
+ end
+
+and update the tests:
+
+ # padrino-gen/test/test_project_generator.rb
+ context "the generator for script component" do
+ should "properly generate for jquery" do
+ # ...
+ assert_match(/Applying.*?jquery.*?script/, buffer)
+ assert_file_exists("#{@apptmp}/sample_project/public/javascripts/jquery.js")
+ assert_file_exists("#{@apptmp}/sample_project/public/javascripts/jquery-ujs.js")
+ assert_file_exists("#{@apptmp}/sample_project/public/javascripts/application.js")
+ end
+ # ...
+ end
+
+ 
+
+## Testing Library
+
+Contributing an additional testing library to Padrino is actually quite straightforward. For this guide, let’s assume we want to add `shoulda` as a testing component integrated into Padrino. First, let’s add `shoulda` to the project generator’s available components in [padrino-gen/generators/project.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L29):
+
+ # padrino-gen/lib/padrino-gen/generators/project.rb
+ component_option :test, "testing framework", :choices => [:rspec, :shoulda]
+
+Next, let’s define the actual integration of the testing library into the generator in [padrino-gen/generators/components/tests/shoulda\_test.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/tests/shoulda_test.rb):
+
+ # padrino-gen/lib/padrino-gen/generators/components/tests/shoulda_test.rb
+ SHOULDA_SETUP = (<<-TEST).gsub(/^ {10}/, '')
+ PADRINO_ENV = 'test' unless defined?(PADRINO_ENV)
+ require File.expand_path(File.dirname(__FILE__) + "/../config/boot")
+
+ class Test::Unit::TestCase
+ include Rack::Test::Methods
+
+ def app
+ CLASS_NAME
+ end
+ end
+ TEST
+
+ def setup_test
+ require_dependencies 'shoulda', :group => 'test'
+ insert_test_suite_setup SHOULDA_SETUP
+ create_file destination_root("test/test.rake"), SHOULDA_RAKE
+ end
+
+ # Generates a controller test given the controllers name
+ def generate_controller_test(name)
+ # ...truncated...
+ end
+
+ def generate_model_test(name)
+ # ...truncated...
+ end
+
+Let’s also add a test to ensure the new testing component generates as expected in [padrino-gen/test/test\_project\_generator.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L234):
+
+ # padrino-gen/test/test_project_generator.rb
+ should "properly generate for shoulda" do
+ buffer = silence_logger {@project.start(['sample_project', '--root=/tmp', '--test=shoulda', '--script=none'])}
+ assert_match /Applying.*?shoulda.*?test/, buffer
+ assert_match_in_file(/gem 'shoulda'/, '/tmp/sample_project/Gemfile')
+ assert_match_in_file(/Test::Unit::TestCase/, '/tmp/sample_project/test/test_config.rb')
+ assert_file_exists('/tmp/sample_project/test/test.rake')
+ end
+
+and finally let’s update the README for `padrino-gen` to reflect the new component in [padrino-gen/README.rdoc](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc):
+
+ # padrino-gen/README.rdoc
+ test:: rspec (default), bacon, shoulda, cucumber, testspec, riot
+
+ 
+
+## Rendering Engine
+
+Contributing a rendering engine to Padrino is actually quite straightforward. For this guide, let’s assume we want to add `haml` as a rendering engine integrated into Padrino. First, let’s add `haml` to the project generator’s available components in [padrino-gen/generators/project.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L32):
+
+ # padrino-gen/lib/padrino-gen/generators/project.rb
+ ccomponent_option :renderer, "template engine", :choices => [:haml, :erb]
+
+Next, let’s define the actual integration of the rendering engine into the generator in [padrino-gen/generators/components/renderers/haml.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/renderers/haml.rb):
+
+ # padrino-gen/lib/padrino-gen/generators/components/renderers/haml.rb
+ def setup_renderer
+ require_dependencies 'haml'
+ end
+
+Let’s also add a test to ensure the new rendering component generates as expected in [padrino-gen/test/test\_project\_generator.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L161):
+
+ # padrino-gen/test/test_project_generator.rb
+ should "properly generate for haml" do
+ buffer = silence_logger {@project.start(['sample_project', '--root=/tmp', '--renderer=haml','--script=none'])}
+ assert_match /Applying.*?haml.*?renderer/, buffer
+ assert_match_in_file(/gem 'haml'/, '/tmp/sample_project/Gemfile')
+ end
+
+and finally let’s update the README for `padrino-gen` to reflect the new component in [padrino-gen/README.rdoc](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc):
+
+ # padrino-gen/README.rdoc
+ renderer:: erb (default), haml
+
+When adding support for a new rendering engine, you are highly encouraged to also include support for this engine within the `padrino-admin` gem. This admin gem constructs views and forms based on templates provided for each supported renderer.
+
+When adding a new renderer, be sure to add templates for each of the necessary admin views. The necessary templates and structure can be found in the [padrino-admin/generators/templates/haml](http://github.com/padrino/padrino-framework/tree/master/padrino-admin/lib/padrino-admin/generators/templates/haml/) views folder. Be sure to implement all of these if you want the integrated rendering engine to work with the admin dashboard.
+
+Finally, let’s update the `padrino-admin` README file at [padrino-admin/README.rdoc](http://github.com/padrino/padrino-framework/blob/master/padrino-admin/README.rdoc) to reflect our newly support component:
+
+ # padrino-admin/README.rdoc
+ Template Agnostic:: Erb and Haml Renderer
+
+This completes the full integration of a rendering engine into Padrino. Once all of this has been finished in your github fork, send us a pull request and assuming you followed these instructions properly and the engine actually works when generated, we will include the component into the next Padrino version crediting you for the contribution!
+
+ 
+
+## Mocking Library
+
+Contributing an additional mocking library to Padrino is actually quite straightforward. For this guide, let’s assume we want to add `mocha` as a mocking component integrated into Padrino. First, let’s add `mocha` to the project generator’s available components in [padrino-gen/generators/project.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L30):
+
+ # padrino-gen/lib/padrino-gen/generators/project.rb
+ component_option :mock, "mocking library", :choices => [:mocha, :rr]
+
+Next, let’s define the actual integration of the mocking library into the generator in [padrino-gen/generators/components/mocks/mocha.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/mocks/mocha.rb):
+
+ # padrino-gen/lib/padrino-gen/generators/components/mocks/mocha.rb
+ def setup_mock
+ require_dependencies 'mocha', :group => 'test'
+ insert_mocking_include "Mocha::API"
+ end
+
+Let’s also add a test to ensure the new mocking component generates as expected in [padrino-gen/test/test\_project\_generator.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L93):
+
+ # padrino-gen/test/test_project_generator.rb
+ should "properly generate for mocha and rspec" do
+ buffer = silence_logger {@project.start(['sample_project', '--root=/tmp', '--mock=mocha'])}
+ assert_match /Applying.*?mocha.*?mock/, buffer
+ assert_match_in_file(/gem 'mocha'/, '/tmp/sample_project/Gemfile')
+ assert_match_in_file(/conf.mock_with :mocha/m, '/tmp/sample_project/spec/spec_helper.rb')
+ end
+
+and finally let’s update the README for `padrino-gen` to reflect the new component in [padrino-gen/README.rdoc](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc):
+
+ # padrino-gen/README.rdoc
+ mock:: none (default), mocha, rr
+
+This completes the full integration of a mocking library into Padrino. Once all of this has been finished in your github fork, send us a pull request and assuming you followed these instructions properly and the library actually works when generated, we will include the component into the next Padrino version crediting you for the contribution!
+
+ 
+
+## Stylesheet Engine
+
+Contributing an additional stylesheet engine to Padrino is actually quite straightforward. For this guide, let’s assume we want to add `less` as a stylesheet engine component integrated into Padrino. First, let’s add `less` to the project generator’s available components in [padrino-gen/generators/project.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L33):
+
+ # padrino-gen/lib/padrino-gen/generators/project.rb
+ component_option :stylesheet, "stylesheet engine", :choices => [:sass, :less]
+
+Next, let’s define the actual integration of the stylesheet engine into the generator in [padrino-gen/generators/components/stylesheets/less.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/stylesheets/less.rb):
+
+ # padrino-gen/lib/padrino-gen/generators/components/stylesheets/less.rb
+ LESS_INIT = (<<-LESS).gsub(/^ {6}/, '')
+ require 'rack/less'
+ Rack::Less.configure do |config|
+ config.compress = true
+ end
+ app.use Rack::Less, :root => app.root, :source => 'stylesheets/',
+ :public => 'public/', :hosted_at => '/stylesheets'
+ LESS
+
+ def setup_stylesheet
+ require_dependencies 'less', 'rack-less'
+ initializer :less, LESS_INIT
+ empty_directory destination_root('/app/stylesheets')
+ end
+
+Let’s also add a test to ensure the new stylesheet engine component generates as expected in [padrino-gen/test/test\_project\_generator.rb](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L278):
+
+ # padrino-gen/test/test_project_generator.rb
+ should "properly generate for less" do
+ buffer = silence_logger { @project.start(['sample_project', '--root=/tmp', '--stylesheet=less']) }
+ assert_match_in_file(/gem 'less'/, '/tmp/sample_project/Gemfile')
+ assert_match_in_file(/gem 'rack-less'/, '/tmp/sample_project/Gemfile')
+ assert_match_in_file(/module LessInitializer.*Rack::Less/m, '/tmp/sample_project/lib/less_init.rb')
+ assert_match_in_file(/register LessInitializer/m, '/tmp/sample_project/app/app.rb')
+ assert_dir_exists('/tmp/sample_project/app/stylesheets')
+ end
+
+and finally let’s update the README for `padrino-gen` to reflect the new component in [padrino-gen/README.rdoc](http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc):
+
+ # padrino-gen/README.rdoc
+ stylesheet:: sass (default), less
+
+This completes the full integration of a stylesheet engine into Padrino. Once all of this has been finished in your github fork, send us a pull request and assuming you followed these instructions properly and the engine actually works when generated, we will include the component into the next Padrino version crediting you for the contribution!
+
+ 
+
+## Locale Translations
+
+In addition to components, we also encourage developers to send us their locale translations allowing Padrino to support a wide variety of different languages.
+
+In order to add locale translations, simply port the following yml files to your favorite language. For this example, let’s port over Padrino to Russian. The following yml files must be translated:
+
+- [padrino-core/locale/ru.yml](http://github.com/padrino/padrino-framework/blob/master/padrino-core/lib/padrino-core/locale/ru.yml)
+- [padrino-helpers/locale/ru.yml](http://github.com/padrino/padrino-framework/blob/master/padrino-helpers/lib/padrino-helpers/locale/ru.yml)
+- [padrino-admin/locale/admin/ru.yml](http://github.com/padrino/padrino-framework/blob/master/padrino-admin/lib/padrino-admin/locale/admin/ru.yml)
+- [padrino-admin/locale/orm/ru.yml](http://github.com/padrino/padrino-framework/blob/master/padrino-admin/lib/padrino-admin/locale/orm/ru.yml)
+
+This completes the full integration of a new locale into Padrino. Once all of this has been finished in your github fork, send us a pull request and assuming you followed these instructions properly and the language has proper translations, we will include the locale into the next Padrino version crediting you for the contribution!
+
+An example of the [actual commit](http://github.com/padrino/padrino-framework/commit/64465d1835cf32996bc36bb14ed9fd1c21e3cd76) of the Russian locale translations are a great example of how to contribute to Padrino.
View
645 guides/adding-new-components.textile
@@ -1,645 +0,0 @@
----
-:author: Foo Bar
-:title: Adding New Components
----
-Padrino is an agnostic web framework. This means that the framework has been built from the ground up to
-easily allow support for any arbitrary number of different developer choices with respect to object
-permanance, stylesheet templaters, javascript libraries, testing libraries, mocking libraries and rendering
-engines. For a detailed overview of the available components, check out the [[Generators|generators guide]].
-
-Although Padrino is fundamentally agnostic, in practice only a very limited set of available components have
-actually been integrated into the Padrino generator and admin dashboard. The set of available components is
-determined by libraries actually used or noted by the core developers and the existing community. However,
-adding additional components to Padrino is not only possible but highly recommended. In fact, this is possibly
-__the best__ way for a developer to get started ["contributing to
-Padrino":http://www.padrinorb.com/pages/contribute].
-
-This guide will outline in detail how to properly contribute new components to Padrino and get them included
-into the next Padrino generator as quickly and efficiently as possible.
-
-h2. Persistence Engine
-
-Contributing an object persistence library is probably the most involved component to integrate with Padrino.
-For this guide, let us pretend that we would like to integrate @Datamapper@ into Padrino. First, let's add
-@Datamapper@ to the project generator's available components in
-["padrino-gen/generators/project.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L28]:
-
-pre[ruby]. # padrino-gen/lib/padrino-gen/generators/project.rb
-component_option :orm, "database engine", :choices => [:activerecord, :datamapper]
-
-Here, we needed to append @:datamapper@ as an option for the @:orm@ component_option in the project generator.
-Once we have defined datamapper as an option for the orm component, let's actually define the specific
-integration tasks for the generator in
-["padrino-gen/generators/components/orms/datamapper.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/orms/datamapper.rb]:
-
-<pre lang="ruby"><code>
-# padrino-gen/lib/padrino-gen/generators/components/orms/datamapper.rb
-# These are the steps to setup the persistence layer in the initial project
-# such as requiring certain gems, constructing the database.rb configuration file
-# and creating the models folder for the application
-def setup_orm
-require_dependencies 'data_objects', 'do_sqlite3', 'datamapper'
-create_file("config/database.rb", DM)
-empty_directory('app/models')
-end
-
-# These are the steps to generate the actual model file
-# when the model generator is executed.
-#
-# create_model_file("account", ["username:string", "password:string"])
-def create_model_file(name, fields)
-# ...truncated...
-create_file(model_path, model_contents)
-end
-
-# These are the steps to generate the model migration file
-# when the model generator is executed.
-#
-# create_model_migration("create_accounts", "account", ["username:string"])
-def create_model_migration(migration_name, name, columns)
-# ...truncated...
-end
-
-# These are the steps to generate the db migration file
-# when the migration generator is executed.
-#
-# create_migration_file("AddEmailToAccount", "AddEmailToAccount", ["email:string"])
-def create_migration_file(migration_name, name, columns)
-# ...truncated...
-end
-</code></pre>
-
-Next, if the persistence engine needs to include useful rake tasks (to migrate or modify the database for
-instance), you can add these to the @padrino-tasks@ folder in the @padrino-gen@ gem. For Datamapper, there are
-a number of tasks that should be available in
-["padrino-tasks/datamapper.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/padrino-tasks/datamapper.rb]:
-
-<pre lang="ruby"><code>
-# padrino-gen/lib/padrino-gen/padrino-tasks/datamapper.rb
-if defined?(DataMapper)
-namespace :dm do
-namespace :migrate do
-task :load => :environment do
-# ...truncated...
-end
-
-desc "Migrate up using migrations"
-task :up, :version, :needs => :load do |t, args|
-# ...truncated...
-end
-end
-end
-end
-</code></pre>
-
-Next, let's add the appropriate unit tests to ensure our new component works as intended in
-["padrino-gen/test/test_project_generator.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L129]:
-
-<pre lang="ruby"><code>
-# padrino-gen/test/test_project_generator.rb
-should "properly generate default for datamapper" do
-buffer = silence_logger {@project.start(['sample_project', '--root=/tmp', '--orm=datamapper'])}
-assert_match /Applying.*?datamapper.*?orm/, buffer
-assert_match_in_file(/gem 'data_objects'/, '/tmp/sample_project/Gemfile')
-assert_match_in_file(/gem 'datamapper'/, '/tmp/sample_project/Gemfile')
-assert_match_in_file(/DataMapper.setup/, '/tmp/sample_project/config/database.rb')
-assert_dir_exists('/tmp/sample_project/app/models')
-end
-</code></pre>
-
-Finally for the generator integration, we should add the available option to the ["generator README
-file":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc]:
-
-pre. # padrino-gen/README.rdoc
-orm:: none (default), mongomapper, mongoid, activerecord, sequel, couchrest, datamapper
-
-and with that update to the README, persistence support for the generator is complete. However, to be fully
-compliant, support for Padrino Admin should also be added. This will allow the admin dashboard to work
-properly with your persistence engine of choice and is *highly* recommended.
-
-Adding @padrino-admin@ support for your persistence engine is actually fairly straightforward. First, let's
-add @Datamapper@ to the set of supported admin orm engines in
-["padrino-admin/generators/actions.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-admin/lib/padrino-admin/generators/actions.rb#L17]:
-
-pre[ruby]. # padrino-admin/lib/padrino-admin/generators/actions.rb
-def supported_orm
-[:activerecord, :mongomapper, :mongoid, :couchrest, :datamapper]
-end
-
-Next, we need to define the interaction methods available by our persistence engine on our models in
-["padrino-admin/generators/orm.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-admin/lib/padrino-admin/generators/orm.rb]:
-
-<pre lang="ruby"><code>
-# padrino-admin/lib/padrino-admin/generators/orm.rb
-module Padrino
-module Admin
-module Generators
-class OrmError < StandardError; end
-class Orm
-attr_reader :klass_name, :klass, :name_plural, :name_singular, :orm
-
-def initialize(name, orm, columns=nil, column_fields=nil)
-# ...truncated...
-end
-
-# Defines access to a model's columns
-def columns
-@columns ||= case orm
-when :activerecord then @klass.columns
-when :datamapper then @klass.properties
-else raise OrmError, "Adapter #{orm} is not yet supported!"
-end
-end
-
-# Defines access to retrieving all existing records for a model.
-def all
-"#{klass_name}.all"
-end
-
-# Defines access for querying records for a model.
-def find(params=nil)
-case orm
-when :activerecord then "#{klass_name}.find(#{params})"
-when :datamapper then "#{klass_name}.get(#{params})"
-else raise OrmError, "Adapter #{orm} is not yet supported!"
-end
-end
-
-# Defines how to build a new record for a model.
-def build(params=nil)
-if params
-"#{klass_name}.new(#{params})"
-else
-"#{klass_name}.new"
-end
-end
-
-# Defines how to save a new record for a model.
-def save
-"#{name_singular}.save"
-end
-
-# Defines how to update attributes of a record for a model.
-def update_attributes(params=nil)
-case orm
-when :activerecord then "#{name_singular}.update_attributes(#{params})"
-when :datamapper then "#{name_singular}.update(#{params})"
-else raise OrmError, "Adapter #{orm} is not yet supported!"
-end
-end
-
-# Defines how to destroy a record for a model.
-def destroy
-"#{name_singular}.destroy"
-end
-end # Orm
-end # Generators
-end # Admin
-end # Padrino
-</code></pre>
-
-Next, we need to describe how the @Account@ model should be defined for our persistence engine within
-["padrino-admin/generators/templates/account/datamapper.rb.tt":http://github.com/padrino/padrino-framework/blob/master/padrino-admin/lib/padrino-admin/generators/templates/account/datamapper.rb.tt]:
-
-<pre lang="ruby"><code>
-# padrino-admin/lib/padrino-admin/generators/templates/account/datamapper.rb.tt
-class Account
-include DataMapper::Resource
-include DataMapper::Validate
-attr_accessor :password, :password_confirmation
-
-# Define Properties
-property :id, Serial
-property :name, String
-# ...truncated...
-
-# Define Validations
-validates_present :email, :role
-# ...truncated...
-
-# Callbacks
-before :save, :generate_password
-
-##
-# This method is for authentication purpose
-#
-def self.authenticate(email, password)
-account = first(:conditions => { :email => email }) if email.present?
-account && account.password_clean == password ? account : nil
-end
-
-##
-# This method is used from AuthenticationHelper
-#
-def self.find_by_id(id)
-get(id) rescue nil
-end
-
-##
-# This method is used for retrive the original password.
-#
-def password_clean
-crypted_password.decrypt(salt)
-end
-
-private
-def generate_password
-return if password.blank?
-self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{email}--") if new?
-self.crypted_password = password.encrypt(self.salt)
-end
-
-def password_required
-crypted_password.blank? || !password.blank?
-end
-end
-</code></pre>
-
-Finally, let's update the @padrino-admin@ README file at
-["padrino-admin/README.rdoc":http://github.com/padrino/padrino-framework/blob/master/padrino-admin/README.rdoc]
-to reflect our newly support component:
-
-pre. # padrino-admin/README.rdoc
-Orm Agnostic:: Data Adapters for Datamapper, Activerecord, Mongomapper, Mongoid, Couchrest
-
-This completes the full integration of a persistence engine into Padrino. Once all of this has been finished
-in your github fork, send us a pull request and assuming you followed these instructions properly and the
-engine actually works when generated, we will include the component into the next Padrino version crediting
-you for the contribution!
-
-h2. Javascript Library
-
-Contributing an additional javascript library to Padrino is actually quite straightforward. For this guide,
-let's assume we want to add @extcore@ as a javascript component integrated into Padrino. First, let's add
-@extcore@ to the project generator's available components in
-["padrino-gen/generators/project.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L31]:
-
-pre[ruby]. # padrino-gen/lib/padrino-gen/generators/project.rb
-component_option :script, "javascript library", :choices => [:jquery, :prototype, :extcore]
-
-Next, let's define the actual integration of the javascript into the generator in
-["padrino-gen/generators/components/scripts/extcore.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/scripts/extcore.rb]:
-
-pre[ruby]. # padrino-gen/lib/padrino-gen/generators/components/scripts/extcore.rb
-def setup_script
-copy_file('templates/scripts/ext-core.js', destination_root("/public/javascripts/ext-core.js"))
-create_file(destination_root('/public/javascripts/application.js'), "// Put scripts here")
-end
-
-This will copy the script into the @public/javascripts@ folder of a newly generated project and construct the
-@application.js@ file. Next, let's copy the latest version of the javascript library to the templates folder:
-
-<pre lang="ruby"><code>
-# padrino-gen/lib/padrino-gen/generators/templates/scripts/ext-core.js
-# ...truncated javascript library code here...
-</code></pre>
-
-Let's also add a test to ensure the new javascript component generates as expected in
-["padrino-gen/test/test_project_generator.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L198]:
-
-<pre lang="ruby"><code>
-# padrino-gen/test/test_project_generator.rb
-should "properly generate for ext-core" do
-buffer = silence_logger{@project.start(['sample_project', '--root=/tmp', '--script=extcore'])}
-assert_match /Applying.*?extcore.*?script/, buffer
-assert_file_exists('/tmp/sample_project/public/javascripts/ext-core.js')
-assert_file_exists('/tmp/sample_project/public/javascripts/application.js'
-end
-</code></pre>
-
-and finally let's update the README for @padrino-gen@ to reflect the new component in
-["padrino-gen/README.rdoc":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc]:
-
-<pre lang="ruby"><code># padrino-gen/README.rdoc
-script:: none (default), jquery, prototype, mootools, rightjs, extcore
-</code></pre>
-
-This completes the full integration of a javascript library into Padrino. Once all of this has been finished
-in your github fork, send us a pull request and assuming you followed these instructions properly and the
-library actually works when generated, we will include the component into the next Padrino version crediting
-you for the contribution!
-
-An example of the ["actual
-commit":http://github.com/padrino/padrino-framework/commit/43fb57dd39fa9d860873c14840e68281e314abb8] of the
-@extcore@ javascript library is a great example of how to contribute to Padrino.
-
-In addition to this, you can also provide a UJS adapter which provides 'remote' and 'method' support to a
-project using a particular javascript framework. For more information about UJS, check out the "UJS
-Helpers":http://www.padrinorb.com/guides/application-helpers#unobtrusive-javascript-helpers guide.
-
-To support UJS in a given javascript framework, simply create a new file such as 'jquery-ujs' in your
-"padrino-static":https://github.com/padrino/padrino-static fork and then follow the UJS "adapter
-template":https://github.com/padrino/padrino-static/blob/master/ujs/jquery-ujs.js used by the existing
-implementation.
-
-<pre lang="js"><code>// ujs/jquery-ujs.js
-/* Remote Form Support
-* form_for @user, '/user', :remote => true
-**/
-$("form[data-remote=true]").live('submit', function(e) {
-// ...
-});
-/* Confirmation Support
-* link_to 'sign out', '/logout', :confirm => "Log out?"
-* Link Remote Support
-* link_to 'add item', '/create', :remote => true
-* Link Method Support
-* link_to 'delete item', '/destroy', :method => :delete
-**/
-
-/* JSAdapter */
-var JSAdapter = {
-// Sends an xhr request to the specified url with given verb and params
-// JSAdapter.sendRequest(element, { verb: 'put', url : '...', params: {} });
-sendRequest : function(element, options) {
-// ...
-},
-// Triggers a particular method verb to be triggered in a form posting to the url
-// JSAdapter.sendMethod(element);
-sendMethod : function(element) {
-// ...
-}
-};
-</code></pre>
-
-Generally the only changes need to be made in the @JSAdapter@ js module specifically to implement the
-@sendRequest@ and @sendMethod@ functions that are used by all the events to power the UJS functionality.
-
-Once that unobtrusive adapter has been implemented, you can finish by adding the UJS file to the generator in
-Padrino:
-
-pre[ruby]. # padrino-gen/lib/padrino-gen/generators/components/scripts/extcore.rb
-def setup_script
-get('https://github.com/padrino/padrino-static/raw/master/js/jquery.js',
-destination_root("/public/javascripts/jquery.js"))
-get('https://github.com/padrino/padrino-static/raw/master/ujs/jquery-ujs.js',
-destination_root("/public/javascripts/jquery-ujs.js"))
-create_file(destination_root('/public/javascripts/application.js'),
-"// Put your application scripts here")
-end
-
-and update the tests:
-
-pre[ruby]. # padrino-gen/test/test_project_generator.rb
-context "the generator for script component" do
-should "properly generate for jquery" do
-# ...
-assert_match(/Applying.*?jquery.*?script/, buffer)
-assert_file_exists("#{@apptmp}/sample_project/public/javascripts/jquery.js")
-assert_file_exists("#{@apptmp}/sample_project/public/javascripts/jquery-ujs.js")
-assert_file_exists("#{@apptmp}/sample_project/public/javascripts/application.js")
-end
-# ...
-end
-
-h2. Testing Library
-
-Contributing an additional testing library to Padrino is actually quite straightforward. For this guide, let's
-assume we want to add @shoulda@ as a testing component integrated into Padrino. First, let's add @shoulda@ to
-the project generator's available components in
-["padrino-gen/generators/project.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L29]:
-
-pre[ruby]. # padrino-gen/lib/padrino-gen/generators/project.rb
-component_option :test, "testing framework", :choices => [:rspec, :shoulda]
-
-Next, let's define the actual integration of the testing library into the generator in
-["padrino-gen/generators/components/tests/shoulda_test.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/tests/shoulda_test.rb]:
-
-<pre lang="ruby"><code># padrino-gen/lib/padrino-gen/generators/components/tests/shoulda_test.rb
-SHOULDA_SETUP = (<<-TEST).gsub(/^ {10}/, '')
-PADRINO_ENV = 'test' unless defined?(PADRINO_ENV)
-require File.expand_path(File.dirname(__FILE__) + "/../config/boot")
-
-class Test::Unit::TestCase
-include Rack::Test::Methods
-
-def app
-CLASS_NAME
-end
-end
-TEST
-
-def setup_test
-require_dependencies 'shoulda', :group => 'test'
-insert_test_suite_setup SHOULDA_SETUP
-create_file destination_root("test/test.rake"), SHOULDA_RAKE
-end
-
-# Generates a controller test given the controllers name
-def generate_controller_test(name)
-# ...truncated...
-end
-
-def generate_model_test(name)
-# ...truncated...
-end
-</code></pre>
-
-Let's also add a test to ensure the new testing component generates as expected in
-["padrino-gen/test/test_project_generator.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L234]:
-
-<pre lang="ruby"><code>
-# padrino-gen/test/test_project_generator.rb
-should "properly generate for shoulda" do
-buffer = silence_logger {@project.start(['sample_project', '--root=/tmp', '--test=shoulda',
-'--script=none'])}
-assert_match /Applying.*?shoulda.*?test/, buffer
-assert_match_in_file(/gem 'shoulda'/, '/tmp/sample_project/Gemfile')
-assert_match_in_file(/Test::Unit::TestCase/, '/tmp/sample_project/test/test_config.rb')
-assert_file_exists('/tmp/sample_project/test/test.rake')
-end
-</code></pre>
-
-and finally let's update the README for @padrino-gen@ to reflect the new component in
-["padrino-gen/README.rdoc":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc]:
-
-<pre lang="ruby"><code># padrino-gen/README.rdoc
-test:: rspec (default), bacon, shoulda, cucumber, testspec, riot
-</code></pre>
-
-h2. Rendering Engine
-
-Contributing a rendering engine to Padrino is actually quite straightforward. For this guide, let's assume we
-want to add @haml@ as a rendering engine integrated into Padrino. First, let's add @haml@ to the project
-generator's available components in
-["padrino-gen/generators/project.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L32]:
-
-pre[ruby]. # padrino-gen/lib/padrino-gen/generators/project.rb
-ccomponent_option :renderer, "template engine", :choices => [:haml, :erb]
-
-Next, let's define the actual integration of the rendering engine into the generator in
-["padrino-gen/generators/components/renderers/haml.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/renderers/haml.rb]:
-
-pre[ruby]. # padrino-gen/lib/padrino-gen/generators/components/renderers/haml.rb
-def setup_renderer
-require_dependencies 'haml'
-end
-
-Let's also add a test to ensure the new rendering component generates as expected in
-["padrino-gen/test/test_project_generator.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L161]:
-
-<pre lang="ruby"><code>
-# padrino-gen/test/test_project_generator.rb
-should "properly generate for haml" do
-buffer = silence_logger {@project.start(['sample_project', '--root=/tmp',
-'--renderer=haml','--script=none'])}
-assert_match /Applying.*?haml.*?renderer/, buffer
-assert_match_in_file(/gem 'haml'/, '/tmp/sample_project/Gemfile')
-end
-</code></pre>
-
-and finally let's update the README for @padrino-gen@ to reflect the new component in
-["padrino-gen/README.rdoc":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc]:
-
-<pre lang="ruby"><code># padrino-gen/README.rdoc
-renderer:: erb (default), haml
-</code></pre>
-
-When adding support for a new rendering engine, you are highly encouraged to also include support for this
-engine within the @padrino-admin@ gem. This admin gem constructs views and forms based on templates provided
-for each supported renderer.
-
-When adding a new renderer, be sure to add templates for each of the necessary admin views. The necessary
-templates and structure can be found in the
-["padrino-admin/generators/templates/haml":http://github.com/padrino/padrino-framework/tree/master/padrino-admin/lib/padrino-admin/generators/templates/haml/]
-views folder. Be sure to implement all of these if you want the integrated rendering engine to work with the
-admin dashboard.
-
-Finally, let's update the @padrino-admin@ README file at
-["padrino-admin/README.rdoc":http://github.com/padrino/padrino-framework/blob/master/padrino-admin/README.rdoc]
-to reflect our newly support component:
-
-pre. # padrino-admin/README.rdoc
-Template Agnostic:: Erb and Haml Renderer
-
-This completes the full integration of a rendering engine into Padrino. Once all of this has been finished in
-your github fork, send us a pull request and assuming you followed these instructions properly and the engine
-actually works when generated, we will include the component into the next Padrino version crediting you for
-the contribution!
-
-h2. Mocking Library
-
-Contributing an additional mocking library to Padrino is actually quite straightforward. For this guide, let's
-assume we want to add @mocha@ as a mocking component integrated into Padrino. First, let's add @mocha@ to the
-project generator's available components in
-["padrino-gen/generators/project.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L30]:
-
-pre[ruby]. # padrino-gen/lib/padrino-gen/generators/project.rb
-component_option :mock, "mocking library", :choices => [:mocha, :rr]
-
-Next, let's define the actual integration of the mocking library into the generator in
-["padrino-gen/generators/components/mocks/mocha.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/mocks/mocha.rb]:
-
-pre[ruby]. # padrino-gen/lib/padrino-gen/generators/components/mocks/mocha.rb
-def setup_mock
-require_dependencies 'mocha', :group => 'test'
-insert_mocking_include "Mocha::API"
-end
-
-Let's also add a test to ensure the new mocking component generates as expected in
-["padrino-gen/test/test_project_generator.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L93]:
-
-<pre lang="ruby"><code>
-# padrino-gen/test/test_project_generator.rb
-should "properly generate for mocha and rspec" do
-buffer = silence_logger {@project.start(['sample_project', '--root=/tmp', '--mock=mocha'])}
-assert_match /Applying.*?mocha.*?mock/, buffer
-assert_match_in_file(/gem 'mocha'/, '/tmp/sample_project/Gemfile')
-assert_match_in_file(/conf.mock_with :mocha/m, '/tmp/sample_project/spec/spec_helper.rb')
-end
-</code></pre>
-
-and finally let's update the README for @padrino-gen@ to reflect the new component in
-["padrino-gen/README.rdoc":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc]:
-
-<pre lang="ruby"><code># padrino-gen/README.rdoc
-mock:: none (default), mocha, rr
-</code></pre>
-
-This completes the full integration of a mocking library into Padrino. Once all of this has been finished in
-your github fork, send us a pull request and assuming you followed these instructions properly and the library
-actually works when generated, we will include the component into the next Padrino version crediting you for
-the contribution!
-
-h2. Stylesheet Engine
-
-Contributing an additional stylesheet engine to Padrino is actually quite straightforward. For this guide,
-let's assume we want to add @less@ as a stylesheet engine component integrated into Padrino. First, let's add
-@less@ to the project generator's available components in
-["padrino-gen/generators/project.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/project.rb#L33]:
-
-pre[ruby]. # padrino-gen/lib/padrino-gen/generators/project.rb
-component_option :stylesheet, "stylesheet engine", :choices => [:sass, :less]
-
-Next, let's define the actual integration of the stylesheet engine into the generator in
-["padrino-gen/generators/components/stylesheets/less.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/lib/padrino-gen/generators/components/stylesheets/less.rb]:
-
-<pre lang="ruby"><code># padrino-gen/lib/padrino-gen/generators/components/stylesheets/less.rb
-LESS_INIT = (<<-LESS).gsub(/^ {6}/, '')
-require 'rack/less'
-Rack::Less.configure do |config|
-config.compress = true
-end
-app.use Rack::Less, :root => app.root, :source => 'stylesheets/',
-:public => 'public/', :hosted_at => '/stylesheets'
-LESS
-
-def setup_stylesheet
-require_dependencies 'less', 'rack-less'
-initializer :less, LESS_INIT
-empty_directory destination_root('/app/stylesheets')
-end
-</code></pre>
-
-Let's also add a test to ensure the new stylesheet engine component generates as expected in
-["padrino-gen/test/test_project_generator.rb":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/test/test_project_generator.rb#L278]:
-
-<pre lang="ruby"><code>
-# padrino-gen/test/test_project_generator.rb
-should "properly generate for less" do
-buffer = silence_logger { @project.start(['sample_project', '--root=/tmp', '--stylesheet=less']) }
-assert_match_in_file(/gem 'less'/, '/tmp/sample_project/Gemfile')
-assert_match_in_file(/gem 'rack-less'/, '/tmp/sample_project/Gemfile')
-assert_match_in_file(/module LessInitializer.*Rack::Less/m, '/tmp/sample_project/lib/less_init.rb')
-assert_match_in_file(/register LessInitializer/m, '/tmp/sample_project/app/app.rb')
-assert_dir_exists('/tmp/sample_project/app/stylesheets')
-end
-</code></pre>
-
-and finally let's update the README for @padrino-gen@ to reflect the new component in
-["padrino-gen/README.rdoc":http://github.com/padrino/padrino-framework/blob/master/padrino-gen/README.rdoc]:
-
-<pre lang="ruby"><code># padrino-gen/README.rdoc
-stylesheet:: sass (default), less
-</code></pre>
-
-This completes the full integration of a stylesheet engine into Padrino. Once all of this has been finished in
-your github fork, send us a pull request and assuming you followed these instructions properly and the engine
-actually works when generated, we will include the component into the next Padrino version crediting you for
-the contribution!
-
-h2. Locale Translations
-
-In addition to components, we also encourage developers to send us their locale translations allowing Padrino
-to support a wide variety of different languages.
-
-In order to add locale translations, simply port the following yml files to your favorite language. For this
-example, let's port over Padrino to Russian. The following yml files must be translated:
-
-*
-"padrino-core/locale/ru.yml":http://github.com/padrino/padrino-framework/blob/master/padrino-core/lib/padrino-core/locale/ru.yml
-*
-"padrino-helpers/locale/ru.yml":http://github.com/padrino/padrino-framework/blob/master/padrino-helpers/lib/padrino-helpers/locale/ru.yml
-*
-"padrino-admin/locale/admin/ru.yml":http://github.com/padrino/padrino-framework/blob/master/padrino-admin/lib/padrino-admin/locale/admin/ru.yml
-*
-"padrino-admin/locale/orm/ru.yml":http://github.com/padrino/padrino-framework/blob/master/padrino-admin/lib/padrino-admin/locale/orm/ru.yml
-
-This completes the full integration of a new locale into Padrino. Once all of this has been finished in your
-github fork, send us a pull request and assuming you followed these instructions properly and the language has
-proper translations, we will include the locale into the next Padrino version crediting you for the
-contribution!
-
-An example of the ["actual
-commit":http://github.com/padrino/padrino-framework/commit/64465d1835cf32996bc36bb14ed9fd1c21e3cd76] of the
-Russian locale translations are a great example of how to contribute to Padrino.
View
729 guides/application-helpers.md
@@ -0,0 +1,729 @@
+---
+date: 2010-03-01
+author: Nathan
+email: nesquena@gmail.com
+title: Application Helpers
+---
+
+This component provides a great deal of view helpers related to html markup generation. There are helpers for generating tags, forms, links, images, and more. Most of the basic methods should be very familiar to anyone who has used rails view helpers.
+
+
+## Output Helpers
+
+Output helpers are a collection of important methods for managing, capturing and displaying output in various ways and is used frequently to support higher-level helper functions. There are three output helpers worth mentioning: `content_for`, `capture_html`, and `concat_content`
+
+The content\_for functionality supports capturing content and then rendering this into a different place such as within a layout. One such popular example is including assets onto the layout from a template:
+
+ # app/views/site/index.erb
+ ...
+ <% content_for :assets do %>
+ <%= stylesheet_link_tag 'index', 'custom' %>
+ <% end %>
+ ...
+
+Added to a template, this will capture the includes from the block and allow them to be yielded into the layout:
+
+ # app/views/layout.erb
+ ...
+ <head>
+ <title>Example</title>
+ <%= stylesheet_link_tag 'style' %>
+ <%= yield_content :assets %>
+ </head>
+
+This will automatically insert the contents of the block (in this case a stylesheet include) into the location the content is yielded within the layout.
+
+You can also check if a `content_for` block exists for a given key using `content_for?`:
+
+ # app/views/layout.erb
+ <% if content_for?(:assets) %>
+ <div><%= yield_content :assets %></div<
+ <% end %>
+
+The `capture_html` and the `concat_content` methods allow content to be manipulated and stored for use in building additional helpers accepting blocks or displaying information in a template. One example is the use of these in constructing a simplified ‘form\_tag’ helper which accepts a block.
+
+ # form_tag '/register' do ... end
+ def form_tag(url, options={}, &block)
+ # ... truncated ...
+ inner_form_html = capture_html(&block)
+ concat_content '<form>' + inner_form_html + '</form>'
+ end
+
+This will capture the template body passed into the form\_tag block and then append the content to the template through the use of `concat_content`. Note have been built to work for both haml and erb templates using the same syntax.
+
+The list of defined helpers in the ‘output helpers’ category:
+
+- `content_for(key, &block)`
+ - Capture a block of content to be rendered at a later time.
+ - Existence can be checked using the `content_for?(key)` method.
+ - `content_for(:head) { …content… }`
+ - Also supports arguments passed to the content block
+ - `content_for(:head) { |param1, param2| …content… }`
+
+- `yield_content(key, *args)`
+ - Render the captured content blocks for a given key.
+ - `yield_content :head`
+ - Also supports arguments yielded to the content block
+ - `yield_content :head, param1, param2`
+
+- `capture_html(*args, &block)`
+ - Captures the html from a block of template code for erb or haml
+ - `capture_html(&block)` =\> “…html…”
+
+- `concat_content(text="")`
+ - Outputs the given text to the templates buffer directly in erb or haml
+ - `concat_content(“This will be output to the template buffer in erb or haml”)`
+
+
+## Tag Helpers
+
+Tag helpers are the basic building blocks used to construct html ‘tags’ within a view template. There are three major functions for this category: `tag`, `content_tag` and `input_tag`.
+
+The tag and content\_tag are for building arbitrary html tags with a name and specified options. If the tag contains ‘content’ within then `content_tag` is used. For example:
+
+The input\_tag is used to build tags that are related to accepting input from the user:
+
+ input_tag :text, :class => "demo" # => <input type='text' class='demo' />
+ input_tag :password, :value => "secret", :class => "demo"
+
+Note that all of these accept html options and result in returning a string containing html tags.
+
+The list of defined helpers in the ‘tag helpers’ category:
+
+- `tag(name, options=nil, open=false)`
+ - Creates an html tag with the given name and options
+ - `tag(:br, :style => ‘clear:both’, :open => true)` =\> `<br style="clear:both">`
+
+- `content_tag(name, content, options=nil, &block)`
+ - Creates an html tag with given name, content and options
+ - `content_tag(:p, “demo”, :class => ‘light’)` =\> `<p class="light">demo</p>`
+ - `content_tag(:p, :class => ‘dark’) { …content… }` =\> `<p class="dark">...content...</p>`
+
+- `input_tag(type, options = {})`
+ - Creates an html input field with given type and options
+ - `input_tag :text, :class => “demo”`
+ - `input_tag :password, :value => “secret”, :class => “demo”`
+
+
+## Asset Helpers
+
+Asset helpers are intended to help insert useful html onto a view template such as ‘flash’ notices, hyperlinks, mail\_to links, images, stylesheets and javascript. An example of their uses would be on a simple view template:
+
+ # app/views/example.haml
+ ...
+ %head
+ = stylesheet_link_tag 'layout'
+ = javascript_include_tag 'application'
+ = favicon_tag 'images/favicon.png'
+ %body
+ ...
+ = flash_tag :notice
+ %p= link_to 'Blog', '/blog', :class => 'example'
+ %p Mail me at #{mail_to 'fake@faker.com', "Fake Email Link", :cc => "test@demo.com"}
+ %p= image_tag 'padrino.png', :width => '35', :class => 'logo'
+
+The list of defined helpers in the ‘asset helpers’ category:
+
+- `flash_tag(kind, options={})`
+ - Creates a div to display the flash of given type if it exists
+ - `flash_tag(:notice, :class => ‘flash’, :id => ‘flash-notice’)`
+
+- `link_to(*args, &block)`
+ - Creates a link element with given name, url and options
+ - `link_to ‘click me’, ‘/dashboard’, :class => ‘linky’`
+ - `link_to ‘click me’, ‘/dashboard’, :class => ‘linky’, :if => @foo.present?`
+ - `link_to ‘click me’, ‘/dashboard’, :class => ‘linky’, :unless => @foo.blank?`
+ - `link_to ‘click me’, ‘/dashboard’, :class => ‘linky’, :unless => :current`
+ - `link_to(‘/dashboard’, :class => ‘blocky’) { …content… }`
+
+- `mail_to(email, caption=nil, mail_options={})`
+ - Creates a mailto link tag to the specified email\_address
+ - `mail_to “me@demo.com”`
+ - `mail_to “me@demo.com”, “My Email”, :subject => “Feedback”, :cc => ‘test@demo.com’`
+
+- `image_tag(url, options={})`
+ - Creates an image element with given url and options
+ - `image_tag(‘icons/avatar.png’)`
+
+- `stylesheet_link_tag(*sources)`
+ - Returns a stylesheet link tag for the sources specified as arguments
+ - `stylesheet_link_tag ‘style’, ‘application’, ‘layout’`
+
+- `javascript_include_tag(*sources)`
+ - Returns an html script tag for each of the sources provided.
+ - `javascript_include_tag ‘application’, ‘special’`
+
+- `favicon_tag(source, options={})`
+ - Returns a favicon tag for the header for the source specified.
+ - `favicon_tag ‘images/favicon.ico’, :type => ‘image/ico’`
+
+- `feed_tag(mime,source, options={})`
+ - Returns a feed tag for the mime and source specified
+ - `feed_tag :atom, url(:blog, :posts, :format => :atom), :title => “ATOM”`
+
+By default, all ‘assets’ including images, scripts, and stylesheets have a timestamp appended at the end to clear the stale cache for the item when modified. To disable this, simply put the setting `disable :asset_stamp` in your application configuration within `app/app.rb`.
+
+
+## Form Helpers
+
+Form helpers are the ‘standard’ form tag helpers you would come to expect when building forms. A simple example of constructing a non-object form would be:
+
+ # app/views/example.haml
+ - form_tag '/destroy', :class => 'destroy-form', :method => 'delete' do
+ = flash_tag(:notice)
+ - field_set_tag do
+ %p
+ = label_tag :username, :class => 'first'
+ = text_field_tag :username, :value => params[:username]
+ %p
+ = label_tag :password, :class => 'first'
+ = password_field_tag :password, :value => params[:password]
+ %p
+ = label_tag :strategy
+ = select_tag :strategy, :options => ['delete', 'destroy'], :selected => 'delete'
+ %p
+ = check_box_tag :confirm_delete
+ - field_set_tag(:class => 'buttons') do
+ = submit_tag "Remove"
+
+The list of defined helpers in the ‘form helpers’ category:
+
+- `form_tag(url, options={}, &block)`
+ - Constructs a form without object based on options
+ - Supports form methods ‘put’ and ‘delete’ through hidden field
+ - `form_tag(‘/register’, :class => ‘example’) { … }`
+
+- `field_set_tag(*args, &block)`
+ - Constructs a field\_set to group fields with given options
+ - `field_set_tag(:class => ‘office-set’) { }`
+ - `field_set_tag(“Office”, :class => ‘office-set’) { }`
+
+- `error_messages_for(:record, options={})`
+ - Constructs list html for the errors for a given object
+ - `error_messages_for :user`
+
+- `label_tag(name, options={}, &block)`
+ - Constructs a label tag from the given options
+ - `label_tag :username, :class => ‘long-label’`
+ - `label_tag(:username, :class => ‘blocked-label’) { … }`
+
+- `hidden_field_tag(name, options={})`
+ - Constructs a hidden field input from the given options
+ - `hidden_field_tag :session_key, :value => ‘secret’`
+
+- `text_field_tag(name, options={})`
+ - Constructs a text field input from the given options
+ - `text_field_tag :username, :class => ‘long’`
+
+- `text_area_tag(name, options={})`
+ - Constructs a text area input from the given options
+ - `text_area_tag :username, :class => ‘long’`
+
+- `password_field_tag(name, options={})`
+ - Constructs a password field input from the given options
+ - `password_field_tag :password, :class => ‘long’`
+
+- `number_field_tag(name, options={})`
+ - Constructs a number field input from the given options
+ - `number_field_tag :age, :class => ‘long’`
+
+- `telephone_field_tag(name, options={})`
+ - Constructs a phone field input from the given options
+ - `telephone_field_tag :mobile, :class => ‘long’`
+
+- `email_field_tag(name, options={})`
+ - Constructs a email field input from the given options
+ - `email_field_tag :email, :class => ‘long’`
+
+- `search_field_tag(name, options={})`
+ - Constructs a search field input from the given options
+ - `search_field_tag :query, :class => ‘long’`
+
+- `url_field_tag(name, options={})`
+ - Constructs a url field input from the given options
+ - `url_field_tag :image_source_url, :class => ‘long’`
+
+- `check_box_tag(name, options={})`
+ - Constructs a checkbox input from the given options
+ - `check_box_tag :remember_me, :checked => true`
+
+- `radio_button_tag(name, options={})`
+ - Constructs a radio button input from the given options
+ - `radio_button_tag :gender, :value => ‘male’`
+
+- `select_tag(name, settings={})`
+ - Constructs a select tag with options from the given settings
+ - `select_tag(:favorite_color, :options => [‘1’, ‘2’, ‘3’], :selected => ‘1’)`
+ - `select_tag(:more_color, :options => [[‘label’, ‘1’], [‘label2’, ‘2’]])`
+ - `select_tag(:multiple_color, :options => […], :multiple => true)`
+
+- `file_field_tag(name, options={})`
+ - Constructs a file field input from the given options
+ - `file_field_tag :photo, :class => ‘long’`
+
+- `submit_tag(caption, options={})`
+ - Constructs a submit button from the given options
+ - `submit_tag “Create”, :class => ‘success’`
+
+- `button_tag(caption, options={})`
+ - Constructs an input (type =\> ‘button’) from the given options
+ - `button_tag “Cancel”, :class => ‘clear’`
+
+- `image_submit_tag(source, options={})`
+ - Constructs an image submit button from the given options
+ - `image_submit_tag “submit.png”, :class => ‘success’`
+
+
+## FormBuilders
+
+Form builders are full-featured objects allowing the construction of complex object-based forms using a simple, intuitive syntax.
+
+A form\_for using these basic fields might look like:
+
+ # app/views/example.haml
+ - form_for @user, '/register', :id => 'register' do |f|
+ = f.error_messages
+ %p
+ = f.label :username, :caption => "Nickname"
+ = f.text_field :username
+ %p
+ = f.label :email
+ = f.text_field :email
+ %p
+ = f.label :password
+ = f.password_field :password
+ %p
+ = f.label :is_admin, :caption => "Admin User?"
+ = f.check_box :is_admin
+ %p
+ = f.label :color, :caption => "Favorite Color?"
+ = f.select :color, :options => ['red', 'black']
+ %p
+ - fields_for @user.location do |location|
+ = location.text_field :street
+ = location.text_field :city
+ %p
+ = f.submit "Create", :class => 'button'
+
+The list of defined helpers in the ‘form builders’ category:
+
+- `form_for(object, url, settings={}, &block)`
+ - Constructs a form using given or default form\_builder
+ - Supports form methods ‘put’ and ‘delete’ through hidden field
+ - Defaults to StandardFormBuilder but you can easily create your own!
+ - `form_for(@user, ‘/register’, :id => ‘register’) { |f| …field-elements… }`
+ - `form_for(:user, ‘/register’, :id => ‘register’) { |f| …field-elements… }`
+
+- `fields_for(object, settings={}, &block)`
+ - Constructs fields for a given object for use in an existing form
+ - Defaults to StandardFormBuilder but you can easily create your own!
+ - `fields_for @user.assignment do |assignment| … end`
+ - `fields_for :assignment do |assigment| … end`
+
+The following are fields provided by AbstractFormBuilder that can be used within a form\_for or fields\_for:
+
+- `error_messages(options={})`
+ - Displays list html for the errors on form object
+ - `f.errors_messages`
+
+- `label(field, options={})`
+ - `f.label :name, :class => ‘long’`
+
+- `text_field(field, options={})`
+ - `f.text_field :username, :class => ‘long’`
+
+- `check_box(field, options={})`
+ - Uses hidden field to provide a ‘unchecked’ value for field
+ - `f.check_box :remember_me, :uncheck_value => ‘false’`
+
+- `radio_button(field, options={})`
+ - `f.radio_button :gender, :value => ‘male’`
+
+- `hidden_field(field, options={})`
+ - `f.hidden_field :session_id, :class => ‘hidden’`
+
+- `text_area(field, options={})`
+ - `f.text_area :summary, :class => ‘long’`
+
+- `password_field(field, options={})`
+ - `f.password_field :secret, :class => ‘long’`
+
+- `number_field(field, options={})`
+ - `f.number_field :age, :class => ‘long’`
+
+- `telephone_field(field, options={})`
+ - `f.telephone_field :mobile, :class => ‘long’`
+
+- `email_field(field, options={})`
+ - `f.email_field :email, :class => ‘long’`
+
+- `search_field(field, options={})`
+ - `f.search_field :query, :class => ‘long’`
+
+- `url_field(field, options={})`
+ - `f.url_field :image_source, :class => ‘long’`
+
+- `file_field(field, options={})`
+ - `f.file_field :photo, :class => ‘long’`
+
+- `select(field, options={})`
+ - `f.select(:state, :options => [‘California’, ‘Texas’, ‘Wyoming’])`
+ - `f.select(:state, :collection => @states, :fields => [:name, :id])`
+ - `f.select(:state, :options => […], :include_blank => true)`
+
+- `submit(caption, options={})`
+ - `f.submit “Update”, :class => ‘long’`
+
+- `image_submit(source, options={})`
+ - `f.image_submit “submit.png”, :class => ‘long’`
+
+### Standard Form Builder
+
+There is also an additional StandardFormBuilder which builds on the abstract fields that can be used within a form\_for.
+
+A form\_for using these standard fields might be:
+
+ # app/views/example.haml
+ - form_for @user, '/register', :id => 'register' do |f|
+ = f.error_messages
+ = f.text_field_block :name, :caption => "Full name"
+ = f.text_field_block :email
+ = f.check_box_block :remember_me
+ = f.select_block :fav_color, :options => ['red', 'blue']
+ = f.password_field_block :password
+ = f.submit_block "Create", :class => 'button'
+
+and would generate this html (with each input contained in a paragraph and containing a label):
+
+ <form id="register" action="/register" method="post">
+ <label for="user_name">Full name:</label>
+ <input type="text" id="user_name" name="user[name]" />
+ ...omitted...
+ <input type="submit" value="Create" class="button" />
+ </form>
+
+The following are fields provided by StandardFormBuilder that can be used within a form\_for or fields\_for:
+
+- `text_field_block(field, options={}, label_options={})`
+ - `text_field_block(:nickname, :class => ‘big’, :caption => “Username”)`
+
+- `text_area_block(field, options={}, label_options={})`
+ - `text_area_block(:about, :class => ‘big’)`
+
+- `password_field_block(field, options={}, label_options={})`
+ - `password_field_block(:code, :class => ‘big’)`
+
+- `file_field_block(field, options={}, label_options={})`
+ - `file_field_block(:photo, :class => ‘big’)`
+
+- `check_box_block(field, options={}, label_options={})`
+ - `check_box_block(:remember_me, :class => ‘big’)`
+
+- `select_block(field, options={}, label_options={})`
+ - `select_block(:country, :option => [‘USA’, ‘Canada’])`
+
+- `submit_block(caption, options={})`
+ - `submit_block(:username, :class => ‘big’)`
+
+- `image_submit_block(source, options={})`
+ - `image_submit_block(‘submit.png’, :class => ‘big’)`
+
+### Custom Form Builders
+
+You can also easily build your own FormBuilder which allows for customized fields and behavior:
+
+ class MyCustomFormBuilder < AbstractFormBuilder
+ # Here we have access to a number of useful variables
+ #
+ # ** template (use this to invoke any helpers)(ex. template.hidden_field_tag(...))
+ # ** object (the record for this form) (ex. object.valid?)
+ # ** object_name (object's underscored type) (ex. object_name => 'admin_user')
+ #
+ # We also have access to self.field_types => [:text_field, :text_area, ...]
+ # In addition, we have access to all the existing field tag
+ # helpers (text_field, hidden_field, file_field, ...)
+ end
+
+Once a custom builder is defined, any call to form\_for can use the new builder:
+
+ - form_for @user, '/register', :builder => 'MyCustomFormBuilder', :id => 'register' do |f|
+ ...fields here...
+
+The form builder can even be made into the default builder when form\_for is invoked:
+
+ # anywhere in the Padrino or Sinatra application
+ set :default_builder, 'MyCustomFormBuilder'
+
+And there you have it, a fairly complete form builder solution for Padrino (and Sinatra).
+ I hope to create or merge in an even better ‘default’ form\_builder in the near future.
+
+### Nested Object Form Support
+
+Available in the 0.9.21 Padrino release is support for nested object form helpers. This allows forms to have arbitrarily complex nested forms that can build multiple related objects together. Let’s take a simple example of a person with an address. Here are the related psuedo models:
+
+ class Person < ORM::Base
+ has_many :addresses, :class_name => 'Address'
+ accepts_nested_attributes_for :addresses, :allow_destroy => true
+ end
+
+ class Address < ORM::Base
+ belongs_to :person
+ end
+
+The model declarations are dependent on your chosen ORM. Check the documentation to understand how to declare nested attributes in your given ORM component. Given those models and enabling nested attributes for the association, the following view will allow nested form creation:
+
+ # app/views/person/_form.html.haml
+ - form_for @person, '/person/create' do |f|
+ = f.text_field :name
+ = f.text_field :favorite_color
+ - f.fields_for :addresses do |address_form|
+ = address_form.label :street
+ = address_form.text_field :street
+ = address_form.label :city
+ = address_form.text_field :city
+ - unless address_form.object.new_record?
+ = address_form.check_box '_destroy'
+ = address_form.label '_destroy', :caption => 'Remove'
+ = submit_tag "Save"
+
+This will present a form that allows the person’s name and color to be set along with their first address. Using this functionality, the controller does not need to change whatsoever as the nested data will be passed in and instantiated as part of the parent model.
+
+ 
+
+## Format Helpers
+
+Format helpers are several useful utilities for manipulating the format of text to achieve a goal.
+ The four format helpers are `escape_html`, `distance_of_time_in_words`, `time_ago_in_words`, and `js_escape_html`.
+
+The escape\_html and js\_escape\_html function are for taking an html string and escaping certain characters.
+ `escape_html` will escape ampersands, brackets and quotes to their HTML/XML entities. This is useful to sanitize user content before displaying this on a template. `js_escape_html` is used for passing javascript information from a js template to a javascript function.
+
+ escape_html('<hello>&<goodbye>') # => <hello>&<goodbye>
+
+There is also an alias for escape\_html called `h` for even easier usage within templates.
+
+Format helpers also includes a number of useful text manipulation functions such as `simple_format`, `pluralize`, `word_wrap`, and `truncate`.
+
+ simple_format("hello\nworld") # => "<p>hello<br/>world</p>"
+ pluralize(2, 'person') => '2 people'
+ word_wrap('Once upon a time', :line_width => 8) => "Once upon\na time"
+ truncate("Once upon a time in a world far far away", :length => 8) => "Once upon..."
+ truncate_words("Once upon a time in a world far far away", :length => 4) => "Once upon a time..."
+ highlight('Lorem dolor sit', 'dolor') => "Lorem <strong class="highlight">dolor</strong> sit"
+
+These helpers can be invoked from any route or view within your application.
+
+The list of defined helpers in the ‘format helpers’ category:
+
+- `simple_format(text, html_options)`
+ - Returns text transformed into HTML using simple formatting rules.
+ - `simple_format(“hello\nworld”)` =\> `"<p>hello<br/>world</p>"`
+
+- `pluralize(count, singular, plural = nil)`
+ - Attempts to pluralize the singular word unless count is 1.
+ - `pluralize(2, ‘person’)` =\> ‘2 people’
+
+- `word_wrap(text, *args)`
+ - Wraps the text into lines no longer than line\_width width.
+ - `word_wrap(‘Once upon a time’, :line_width => 8)` =\> “Once upon\\na time”
+
+- `truncate(text, *args)`
+ - Truncates a given text after a given :length if text is longer than :length (defaults to 30).
+ - `truncate(“Once upon a time in a world far far away”, :length => 8)` =\> “Once upon…”
+
+- `truncate_words(text, *args)`
+ - Truncates a given text after a given :length of total words (defaults to 30).
+ - truncate\_words(“Once upon a time in a world far far away”, :length =\> 4) =\> “Once upon a time…”
+
+- `highlight(text, words, *args)`
+ - Highlights one or more words everywhere in text by inserting it into a :highlighter string.
+ - `highlight(‘Lorem ipsum dolor sit amet’, ‘dolor’)`
+
+- `escape_html` (alias `h` and `h!`)
+ - (from RackUtils) Escape ampersands, brackets and quotes to their HTML/XML entities.
+
+- `strip_tags(html)`
+ - Remove all html tags and return only a clean text.
+
+- `distance_of_time_in_words(from_time, to_time = 0)`
+ - Returns relative time in words referencing the given date
+ - `distance_of_time_in_words(2.days.ago)` =\> “2 days”
+ - `distance_of_time_in_words(5.minutes.ago)` =\> “5 minutes”
+ - `distance_of_time_in_words(2800.days.ago)` =\> “over 7 years”
+
+- `time_ago_in_words(from_time)`
+ - Returns relative time in words from the current date
+ - `time_ago_in_words(2.days.ago)` =\> “2 days”
+ - `time_ago_in_words(1.day.from_now)` =\> “tomorrow”
+
+- `js_escape_html(html_content)`
+ - Escapes html to allow passing information to javascript. Used for passing data inside an ajax .js.erb template
+ - `js_escape_html("<h1>Hey</h1>")`
+
+ 
+
+## Render Helpers
+
+This component provides a number of rendering helpers making the process of displaying templates a bit easier.
+ This plugin also has support for useful additions such as partials (with support for :collection) for the templating system.
+
+Using render plugin helpers is extremely simple. If you want to render an erb template in your view path:
+
+ render :erb, 'path/to/erb/template'
+
+or using haml templates works just as well:
+
+ render :haml, 'path/to/haml/template'
+
+There is also a method which renders the first view matching the path and removes the need to define an engine:
+
+ render 'path/to/any/template'
+
+It is worth noting these are mostly for convenience. With nested view file paths in Sinatra, this becomes tiresome:
+
+ haml :"the/path/to/file"
+ erb "/path/to/file".to_sym
+
+Finally, we have the all-important partials support for rendering mini-templates onto a page:
+
+ partial 'photo/item', :object => @photo, :locals => { :foo => 'bar' }
+ partial 'photo/item', :collection => @photos
+
+This works as you would expect and also supports the collection counter inside the partial `item_counter`
+
+ # /views/photo/_item.haml
+ # Access to collection counter with <partial_name>_counter i.e item_counter
+ # Access the object with the partial_name i.e item
+
+The list of defined helpers in the ‘render helpers’ category:
+
+- `render(engine, data, options, locals)`
+ - Renders the specified template with the given options
+ - `render ‘user/new’`
+ - `render :erb, ‘users/new’, :layout => false`
+
+- `partial(template, *args)`
+ - Renders the html related to the partial template for object or collection
+ - `partial ‘photo/item’, :object => @photo, :locals => { :foo => ‘bar’ }`
+ - `partial ‘photo/item’, :collection => @photos`
+
+ 
+
+## Custom Defined Helpers
+
+In addition to the helpers provided by Padrino out of the box, you can also add your own helper methods and classes that will be accessible within any controller or view automatically.
+
+To define a helper method, simply use an existing helper file (created when generating a controller) or define your own file in `app/helpers` within your application. Methods can be made available within you controller by simply wrapping the methods in the `helpers` block:
+
+ # app/helpers/some_helper.rb
+ MyAppName.helpers do
+ def some_method
+ # ...do something here...
+ end
+ end
+
+You can also define entire classes for use as helpers just as easily:
+
+ # app/helpers/some_helper.rb
+ class SomeHelper
+ def self.do_something
+ # ...do something here...
+ end
+ end
+
+These helpers can then easily be invoked in any controllers or templates within your application:
+
+ # app/controllers/posts.rb
+ MyAppName.controllers :posts do
+ get :index do
+ some_method # helper method
+ SomeHelper.do_something # helper class
+ end
+ end
+
+Use these in situations where you wish to cleanup your controller or your view code. Helpers are particularly useful for DRY’ing up repeated use of the same markup or behavior. **Note** that helper methods and objects should be reloaded automatically for you in development.
+
+ 
+
+## Unobtrusive Javascript Helpers
+
+In addition to the helpers above, certain helpers also have certain unobtrusive javascript options that are available to be used with any of the javascript adapters packaged with padrino. Once your app has been [generated](http://www.padrinorb.com/guides/generators) with a particular javascript adapter, you can utilize the baked in support with the `link_to` and `form_for` tags.
+
+### Remote Forms
+
+To generate a ‘remote’ form in a view:
+
+ # /app/views/users/new.html.haml
+ - form_for :user, url(:create, :format => :js), :remote => true do |f|
+ .content=partial "/users/form"
+
+which will generate the following unobtrusive markup:
+
+ <form data-remote="true" action="/items/create.js" method="post">
+ <div class="content">
+ <input type="text" id="post_title" name="post[title]">
+ <input type="submit" value="Create">
+ </div>
+ </form>
+
+ # /app/controllers/users.rb
+ post :create, :provides => :js do
+ @user = User.new(params[:user])
+ if @user.save
+ "$('form.content').html('#{partial("/users/form")}');"
+ else
+ "alert('User is not valid');"
+ end
+ end
+
+A remote form, when submitted by the user, invokes an xhr request to the specified url (with the appropriate form parameters) and then evaluates the response as javascript.
+
+### Remote Links
+
+To generate a ‘remote’ link in a view:
+
+ link_to "add item", url(:items, :new, :format => :js), :remote => true
+
+which will generate the following unobtrusive markup:
+
+ <a href="/items/new.js" data-remote="true">add item</a>
+
+A remote link, when clicked by the user, invokes an xhr request to the specified url and then evaluates the response as javascript.
+
+### Link Confirmations
+
+To generate a ‘confirmation’ link in a view:
+
+ link_to "delete item", url(:items, :destroy, :format => :js), :confirm => "Are You Sure?"
+
+which will generate the following unobtrusive markup:
+
+ <a data-confirm="Are You Sure?" href="/posts/destroy/7">[destroy]</a>
+
+A link with confirmation, when clicked by the user, displays an alert box confirming the action before invoking the link.
+
+### Custom Method Links
+
+To generate a ‘method’ link in a view:
+
+ link_to "logout", url(:session, :destroy, :format => :js), :method => :delete
+
+which will generate the following unobtrusive markup:
+
+ <a data-method="delete" href="/posts/destroy/7" rel="nofollow">[destroy]</a>
+
+A link with a custom method, when clicked by the user, visits the link using the http method specified rather than via the ‘GET’ method.
+
+### Enabling UJS Adapter
+
+**Note**: In order for the unobstrusive javascript to work, you must be sure to include the chosen javascript framework and ujs adapter in your views (or layout). For instance, if I selected jquery for my project:
+
+ # /apps/views/layouts/application.haml
+ = javascript_include_tag 'jquery', 'jquery-ujs', 'application'
+
+This will ensure jquery and the jquery ujs adapter are properly loaded to work with the helpers listed above.
View
675 guides/application-helpers.textile
@@ -1,675 +0,0 @@
----
-:author: Foo Bar
-:title: Application Helpers
----
-This component provides a great deal of view helpers related to html markup generation. There are helpers for
-generating tags, forms, links, images, and more. Most of the basic methods should be very familiar to anyone
-who has used rails view helpers.
-
-h2. Output Helpers
-
-Output helpers are a collection of important methods for managing, capturing and displaying output in various
-ways and is used frequently to support higher-level helper functions. There are three output helpers worth
-mentioning: <tt>content_for</tt>, <tt>capture_html</tt>, and <tt>concat_content</tt>
-
-The content_for functionality supports capturing content and then rendering this into a different place such
-as within a layout. One such popular example is including assets onto the layout from a template:
-
-pre[erb]. # app/views/site/index.erb
-...
-<% content_for :assets do %>
-<%= stylesheet_link_tag 'index', 'custom' %>
-<% end %>
-...
-
-Added to a template, this will capture the includes from the block and allow them to be yielded into the
-layout:
-
-pre[erb]. # app/views/layout.erb
-...
-<head>
-<title>Example</title>
-<%= stylesheet_link_tag 'style' %>
-<%= yield_content :assets %>
-</head>
-
-This will automatically insert the contents of the block (in this case a stylesheet include) into the location
-the content is yielded within the layout.
-
-The capture_html and the concat_content methods allow content to be manipulated and stored for use in building
-additional helpers accepting blocks or displaying information in a template. One example is the use of these
-in constructing a simplified 'form_tag' helper which accepts a block.
-
-pre[ruby]. # form_tag '/register' do ... end
-def form_tag(url, options={}, &block)
-# ... truncated ...
-inner_form_html = capture_html(&block)
-concat_content '<form>' + inner_form_html + '</form>'
-end
-
-This will capture the template body passed into the form_tag block and then append the content to the template
-through the use of <tt>concat_content</tt>. Note have been built to work for both haml and erb templates using
-the same syntax.
-
-The list of defined helpers in the 'output helpers' category:
-
-* <tt>content_for(key, &block)</tt>
-** Capture a block of content to be rendered at a later time.
-** <tt>content_for(:head) { ...content... }</tt>
-** Also supports arguments passed to the content block
-** <tt>content_for(:head) { |param1, param2| ...content... }</tt>
-* <tt>yield_content(key, *args)</tt>
-** Render the captured content blocks for a given key.
-** <tt>yield_content :head</tt>
-** Also supports arguments yielded to the content block
-** <tt>yield_content :head, param1, param2</tt>
-* <tt>capture_html(*args, &block)</tt>
-** Captures the html from a block of template code for erb or haml
-** <tt>capture_html(&block)</tt> => "...html..."
-* <tt>concat_content(text="")</tt>
-** Outputs the given text to the templates buffer directly in erb or haml
-** <tt>concat_content("This will be output to the template buffer in erb or haml")</tt>
-
-h2. Tag Helpers
-
-Tag helpers are the basic building blocks used to construct html 'tags' within a view template. There are
-three major functions for this category: <tt>tag</tt>, <tt>content_tag</tt> and <tt>input_tag</tt>.
-
-The tag and content_tag are for building arbitrary html tags with a name and specified options. If the tag
-contains 'content' within then <tt>content_tag</tt> is used. For example:
-
-pre[ruby]. tag(:br, :style => ‘clear:both’) # => <br style="clear:both" />
-content_tag(:p, "demo", :class => ‘light’) # => <p class="light">demo</p>
-
-The input_tag is used to build tags that are related to accepting input from the user:
-
-pre[ruby]. input_tag :text, :class => "demo" # => <input type='text' class='demo' />
-input_tag :password, :value => "secret", :class => "demo"
-
-Note that all of these accept html options and result in returning a string containing html tags.
-
-The list of defined helpers in the 'tag helpers' category:
-
-* <tt>tag(name, options={})</tt>
-** Creates an html tag with the given name and options
-** <tt>tag(:br, :style => 'clear:both')</tt> => @<br style="clear:both" />@
-** <tt>tag(:p, :content => "demo", :class => 'large')</tt> => @<p class="large">demo</p>@
-* <tt>content_tag(name, content, options={})</tt>
-** Creates an html tag with given name, content and options
-** <tt>content_tag(:p, "demo", :class => 'light')</tt> => @<p class="light">demo</p>@
-** <tt>content_tag(:p, :class => 'dark') { ...content... }</tt> => @<p class="dark">...content...</p>@
-* <tt>input_tag(type, options = {})</tt>
-** Creates an html input field with given type and options
-** <tt>input_tag :text, :class => "demo"</tt>
-** <tt>input_tag :password, :value => "secret", :class => "demo"</tt>
-
-h2. Asset Helpers
-
-Asset helpers are intended to help insert useful html onto a view template such as 'flash' notices,
-hyperlinks, mail_to links, images, stylesheets and javascript. An example of their uses would be on a simple
-view template:
-
-pre[haml]. # app/views/example.haml
-...
-%head
-= stylesheet_link_tag 'layout'
-= javascript_include_tag 'application'
-= favicon_tag 'images/favicon.png'
-%body
-...
-= flash_tag :notice
-%p= link_to 'Blog', '/blog', :class => 'example'
-%p Mail me at #{mail_to 'fake@faker.com', "Fake Email Link", :cc => "test@demo.com"}
-%p= image_tag 'padrino.png', :width => '35', :class => 'logo'
-
-The list of defined helpers in the 'asset helpers' category:
-
-* <tt>flash_tag(kind, options={})</tt>
-** Creates a div to display the flash of given type if it exists
-** <tt>flash_tag(:notice, :class => 'flash', :id => 'flash-notice')</tt>
-* <tt>link_to(*args, &block)</tt>
-** Creates a link element with given name, url and options
-** <tt>link_to 'click me', '/dashboard', :class => 'linky'</tt>
-** <tt>link_to 'click me', '/dashboard', :class => 'linky', :if => @foo.present?</tt>
-** <tt>link_to 'click me', '/dashboard', :class => 'linky', :unless => @foo.blank?</tt>
-** <tt>link_to 'click me', '/dashboard', :class => 'linky', :unless => :current</tt>
-** <tt>link_to('/dashboard', :class => 'blocky') { ...content... }</tt>
-* <tt>mail_to(email, caption=nil, mail_options={})</tt>
-** Creates a mailto link tag to the specified email_address
-** <tt>mail_to "me@demo.com"</tt>
-** <tt>mail_to "me@demo.com", "My Email", :subject => "Feedback", :cc => 'test@demo.com'</tt>
-* <tt>image_tag(url, options={})</tt>
-** Creates an image element with given url and options
-** <tt>image_tag('icons/avatar.png')</tt>
-* <tt>stylesheet_link_tag(*sources)</tt>
-** Returns a stylesheet link tag for the sources specified as arguments
-** <tt>stylesheet_link_tag 'style', 'application', 'layout'</tt>
-* <tt>javascript_include_tag(*sources)</tt>
-** Returns an html script tag for each of the sources provided.
-** <tt>javascript_include_tag 'application', 'special'</tt>
-* <tt>favicon_tag(source, options={})</tt>
-** Returns a favicon tag for the header for the source specified.
-** <tt>favicon_tag 'images/favicon.ico', :type => 'image/ico'</tt>
-* <tt>feed_tag(mime,source, options={})</tt>
-** Returns a feed tag for the mime and source specified
-** <tt>feed_tag :atom, url(:blog, :posts, :format => :atom), :title => "ATOM"</tt>
-
-By default, all 'assets' including images, scripts, and stylesheets have a timestamp appended at the end to
-clear the stale cache for the item when modified. To disable this, simply put the setting @disable
-:asset_stamp@ in your application configuration within @app/app.rb@.
-
-h2. Form Helpers
-
-Form helpers are the 'standard' form tag helpers you would come to expect when building forms. A simple
-example of constructing a non-object form would be:
-
-pre[haml]. # app/views/example.haml
-- form_tag '/destroy', :class => 'destroy-form', :method => 'delete' do
-= flash_tag(:notice)
-- field_set_tag do
-%p
-= label_tag :username, :class => 'first'
-= text_field_tag :username, :value => params[:username]
-%p
-= label_tag :password, :class => 'first'