diff options
43 files changed, 443 insertions, 407 deletions
@@ -94,7 +94,7 @@ RDoc::Task.new do |rdoc| rdoc.options << '-f' << 'sdoc' rdoc.options << '-T' << 'rails' - rdoc.options << '-c' << 'utf-8' + rdoc.options << '-e' << 'UTF-8' rdoc.options << '-g' # SDoc flag, link methods to GitHub rdoc.options << '-m' << RDOC_MAIN diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index c992f1388a..f408c50390 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 3.2.0 (unreleased) ## +* Add font_path helper method *Santiago Pastorino* + * Depends on rack ~> 1.4.0 *Santiago Pastorino* * Add :gzip option to `caches_page`. The default option can be configured globally using `page_cache_compression` *Andrey Sitnik* @@ -155,7 +157,7 @@ ## Rails 3.1.3 (unreleased) ## -* Fix using `tranlate` helper with a html translation which uses the `:count` option for +* Fix using `translate` helper with a html translation which uses the `:count` option for pluralization. *Jon Leighton* @@ -204,23 +206,30 @@ ## Rails 3.1.1 (unreleased) ## * javascript_path and stylesheet_path now refer to /assets if asset pipelining - is on. [Santiago Pastorino] + is on. *Santiago Pastorino* + * button_to support form option. Now you're able to pass for example - 'data-type' => 'json'. [ihower] + 'data-type' => 'json'. *ihower* + * image_path and image_tag should use /assets if asset pipelining is turned - on. Closes #3126 [Santiago Pastorino and christos] + on. Closes #3126 *Santiago Pastorino and christos* + * Avoid use of existing precompiled assets during rake assets:precompile run. - Closes #3119 [Guillermo Iguaran] + Closes #3119 *Guillermo Iguaran* + * Copy assets to nondigested filenames too *Santiago Pastorino* * Give precedence to `config.digest = false` over the existence of - manifest.yml asset digests [christos] + manifest.yml asset digests *christos* + * escape options for the stylesheet_link_tag method *Alexey Vakhov* * Re-launch assets:precompile task using (Rake.)ruby instead of Kernel.exec so - it works on Windows [cablegram] -* env var passed to process shouldn't be modified in process method. [Santiago - Pastorino] + it works on Windows *cablegram* + +* env var passed to process shouldn't be modified in process method. *Santiago + Pastorino* + * `rake assets:precompile` loads the application but does not initialize it. To the app developer, this means configuration add in @@ -235,7 +244,8 @@ * Fix Hash#to_query edge case with html_safe strings. *brainopia* * Allow asset tag helper methods to accept :digest => false option in order to completely avoid the digest generation. - Useful for linking assets from static html files or from emails when the user could probably look at an older html email with an older asset. [Santiago Pastorino] + Useful for linking assets from static html files or from emails when the user could probably look at an older html email with an older asset. *Santiago Pastorino* + * Don't mount Sprockets server at config.assets.prefix if config.assets.compile is false. *Mark J. Titorenko* * Set relative url root in assets when controller isn't available for Sprockets (eg. Sass files using asset_path). Fixes #2435 *Guillermo Iguaran* @@ -392,6 +402,7 @@ * ActionDispatch::MiddlewareStack now uses composition over inheritance. It is no longer an array which means there may be methods missing that were not tested. + * Add an :authenticity_token option to form_tag for custom handling or to omit the token (pass :authenticity_token => false). *Jakub Kuźma, Igor Wiedler* * HTML5 button_tag helper. *Rizwan Reza* @@ -433,7 +444,7 @@ * No changes. -* Rails 3.0.6 (April 5, 2011) +## Rails 3.0.6 (April 5, 2011) ## * Fixed XSS vulnerability in `auto_link`. `auto_link` no longer marks input as html safe. Please make sure that calls to auto_link() are wrapped in a @@ -622,7 +633,7 @@ * Added ActionDispatch::Request#authorization to access the http authentication header regardless of its proxy hiding *DHH* -* Added :alert, :notice, and :flash as options to ActionController::Base#redirect_to that'll automatically set the proper flash before the redirection [DHH]. Examples: +* Added :alert, :notice, and :flash as options to ActionController::Base#redirect_to that'll automatically set the proper flash before the redirection *DHH*. Examples: flash[:notice] = 'Post was created' redirect_to(@post) @@ -633,7 +644,6 @@ * Added ActionController::Base#notice/= and ActionController::Base#alert/= as a convenience accessors in both the controller and the view for flash[:notice]/= and flash[:alert]/= *DHH* - * Introduce grouped_collection_select helper. #1249 *Dan Codeape, Erik Ostrom* * Make sure javascript_include_tag/stylesheet_link_tag does not append ".js" or ".css" onto external urls. #1664 *Matthew Rudy Jacobs* @@ -673,19 +683,19 @@ * Make the form_for and fields_for helpers support the new Active Record nested update options. #1202 *Eloy Duran* - <% form_for @person do |person_form| %> + <% form_for @person do |person_form| %> ... <% person_form.fields_for :projects do |project_fields| %> <% if project_fields.object.active? %> Name: <%= project_fields.text_field :name %> <% end %> <% end %> - <% end %> + <% end %> * Added grouped_options_for_select helper method for wrapping option tags in optgroups. #977 *Jon Crawford* -* Implement HTTP Digest authentication. #1230 [Gregg Kellogg, Pratik Naik] Example : +* Implement HTTP Digest authentication. #1230 *Gregg Kellogg, Pratik Naik* Example : class DummyDigestController < ActionController::Base USERS = { "lifo" => 'world' } @@ -723,7 +733,7 @@ * Fixed the AssetTagHelper cache to use the computed asset host as part of the cache key instead of just assuming the its a string #1299 *DHH* -* Make ActionController#render(string) work as a shortcut for render :file/:template/:action => string. [#1435] [Pratik Naik] Examples: +* Make ActionController#render(string) work as a shortcut for render :file/:template/:action => string. #1435 *Pratik Naik* Examples: \# Instead of render(:action => 'other_action') render('other_action') # argument has no '/' @@ -755,7 +765,7 @@ * Remove deprecated ActionController::Base#assign_default_content_type_and_charset -* Changed the default of ActionView#render to assume partials instead of files when not given an options hash [David Heinemeier Hansson]. Examples: +* Changed the default of ActionView#render to assume partials instead of files when not given an options hash *DHH*. Examples: # Instead of <%= render :partial => "account" %> <%= render "account" %> @@ -813,7 +823,7 @@ * Fix incorrect closing CDATA delimiter and that HTML::Node.parse would blow up on unclosed CDATA sections *packagethief* -* Added stale? and fresh_when methods to provide a layer of abstraction above request.fresh? and friends [David Heinemeier Hansson]. Example: +* Added stale? and fresh_when methods to provide a layer of abstraction above request.fresh? and friends *DHH*. Example: class ArticlesController < ApplicationController def show_with_respond_to_block @@ -847,7 +857,7 @@ end -* Added inline builder yield to atom_feed_helper tags where appropriate [Sam Ruby]. Example: +* Added inline builder yield to atom_feed_helper tags where appropriate *Sam Ruby*. Example: entry.summary :type => 'xhtml' do |xhtml| xhtml.p pluralize(order.line_items.count, "line item") @@ -869,7 +879,7 @@ * Changed BenchmarkHelper#benchmark to report in milliseconds *David Heinemeier Hansson* -* Changed logging format to be millisecond based and skip misleading stats [David Heinemeier Hansson]. Went from: +* Changed logging format to be millisecond based and skip misleading stats *DHH*. Went from: Completed in 0.10000 (4 reqs/sec) | Rendering: 0.04000 (40%) | DB: 0.00400 (4%) | 200 OK [http://example.com] @@ -953,7 +963,7 @@ * Deprecated TemplateHandler line offset *Josh Peek* -* Allow caches_action to accept cache store options. #416. [José Valim]. Example: +* Allow caches_action to accept cache store options. #416. *José Valim*. Example: caches_action :index, :redirected, :if => Proc.new { |c| !c.request.format.json? }, :expires_in => 1.hour @@ -983,7 +993,7 @@ * Replaced TemplateFinder abstraction with ViewLoadPaths *Josh Peek* -* Added block-call style to link_to [Sam Stephenson/David Heinemeier Hansson]. Example: +* Added block-call style to link_to *Sam Stephenson/David Heinemeier Hansson*. Example: <% link_to(@profile) do %> <strong><%= @profile.name %></strong> -- <span>Check it out!!</span> @@ -1206,7 +1216,7 @@ * Added OPTIONS to list of default accepted HTTP methods #10449 *holoway* -* Added option to pass proc to ActionController::Base.asset_host for maximum configurability #10521 [Cheah Chu Yeow]. Example: +* Added option to pass proc to ActionController::Base.asset_host for maximum configurability #10521 *Cheah Chu Yeow*. Example: ActionController::Base.asset_host = Proc.new { |source| if source.starts_with?('/images') @@ -1251,7 +1261,7 @@ * Update to Prototype -r8232. *sam* -* Make sure the optimisation code for routes doesn't get used if :host, :anchor or :port are provided in the hash arguments. [pager, Michael Koziarski] #10292 +* Make sure the optimisation code for routes doesn't get used if :host, :anchor or :port are provided in the hash arguments. *pager, Michael Koziarski* #10292 * Added protection from trailing slashes on page caching #10229 *devrieda* @@ -1423,9 +1433,9 @@ * Don't warn when a path segment precedes a required segment. Closes #9615. *Nicholas Seckar* -* Fixed CaptureHelper#content_for to work with the optional content parameter instead of just the block #9434 [sandofsky/wildchild]. +* Fixed CaptureHelper#content_for to work with the optional content parameter instead of just the block #9434 *sandofsky/wildchild*. -* Added Mime::Type.register_alias for dealing with different formats using the same mime type [David Heinemeier Hansson]. Example: +* Added Mime::Type.register_alias for dealing with different formats using the same mime type *DHH*. Example: class PostsController < ApplicationController before_filter :adjust_format_for_iphone @@ -1448,7 +1458,7 @@ end end -* Added that render :json will automatically call .to_json unless it's being passed a string [David Heinemeier Hansson]. +* Added that render :json will automatically call .to_json unless it's being passed a string *DHH*. * Autolink behaves well with emails embedded in URLs. #7313 *Jeremy McAnally, Tarmo Tänav* @@ -1472,7 +1482,7 @@ * Removed deprecated form of calling xml_http_request/xhr without the first argument being the http verb *David Heinemeier Hansson* -* Removed deprecated methods [David Heinemeier Hansson]: +* Removed deprecated methods *DHH*: - ActionController::Base#keep_flash (use flash.keep instead) - ActionController::Base#expire_matched_fragments (just call expire_fragment with a regular expression) @@ -1588,7 +1598,7 @@ * Reduce file stat calls when checking for template changes. #7736 *alex* -* Added custom path cache_page/expire_page parameters in addition to the options hashes [David Heinemeier Hansson]. Example: +* Added custom path cache_page/expire_page parameters in addition to the options hashes *DHH*. Example: def index caches_page(response.body, "/index.html") @@ -1626,7 +1636,7 @@ * Update to Prototype 1.5.1. *Sam Stephenson* -* Allow routes to be decalred under namespaces [Tobias Lütke]: +* Allow routes to be decalred under namespaces *Tobias Lütke*: map.namespace :admin do |admin| admin.root :controller => "products" @@ -1641,7 +1651,7 @@ * select :include_blank option can be set to a string instead of true, which just uses an empty string. #7664 *Wizard* -* Added url_for usage on render :location, which allows for record identification [David Heinemeier Hansson]. Example: +* Added url_for usage on render :location, which allows for record identification *DHH*. Example: render :xml => person, :status => :created, :location => person @@ -1667,7 +1677,7 @@ end end -* Added record identifications to FormHelper#form_for and PrototypeHelper#remote_form_for [David Heinemeier Hansson]. Examples: +* Added record identifications to FormHelper#form_for and PrototypeHelper#remote_form_for *DHH*. Examples: <% form_for(@post) do |f| %> ... @@ -1693,7 +1703,7 @@ * Rationalize route path escaping according to RFC 2396 section 3.3. #7544, #8307. *Jeremy Kemper, Chris Roos, begemot, jugend* -* Added record identification with polymorphic routes for ActionController::Base#url_for and ActionView::Base#url_for [David Heinemeier Hansson]. Examples: +* Added record identification with polymorphic routes for ActionController::Base#url_for and ActionView::Base#url_for *DHH*. Examples: redirect_to(post) # => redirect_to(posts_url(post)) => Location: http://example.com/posts/1 link_to(post.title, post) # => link_to(post.title, posts_url(post)) => <a href="/posts/1">Hello world</a> @@ -1724,13 +1734,13 @@ * Update UrlWriter to accept :anchor parameter. Closes #6771. *Chris McGrath* -* Added RecordTagHelper for using RecordIdentifier conventions on divs and other container elements [David Heinemeier Hansson]. Example: +* Added RecordTagHelper for using RecordIdentifier conventions on divs and other container elements *DHH*. Example: <% div_for(post) do %> <div id="post_45" class="post"> <%= post.body %> What a wonderful world! <% end %> </div> -* Added page[record] accessor to JavaScriptGenerator that relies on RecordIdentifier to find the right dom id [David Heinemeier Hansson]. Example: +* Added page[record] accessor to JavaScriptGenerator that relies on RecordIdentifier to find the right dom id *DHH*. Example: format.js do # Calls: new Effect.fade('post_45'); @@ -1757,7 +1767,7 @@ :has_many => [ :tags, :images, :variants ] end -* Added :name_prefix as standard for nested resources [David Heinemeier Hansson]. WARNING: May be backwards incompatible with your app +* Added :name_prefix as standard for nested resources *DHH*. WARNING: May be backwards incompatible with your app Before: @@ -1789,7 +1799,7 @@ map.resources :notes, :has_many => [ :comments, :attachments ], :has_one => :author -* Added that render :xml will try to call to_xml if it can [David Heinemeier Hansson]. Makes these work: +* Added that render :xml will try to call to_xml if it can *DHH*. Makes these work: render :xml => post render :xml => comments @@ -1866,7 +1876,7 @@ * Allow array and hash query parameters. Array route parameters are converted/to/a/path as before. #6765, #7047, #7462 *bgipsy, Jeremy McAnally, Dan Kubb, brendan* - \# Add a #dbman attr_reader for CGI::Session and make CGI::Session::CookieStore#generate_digest public so it's easy to generate digests using the cookie store's secret. [Rick Olson] + \# Add a #dbman attr_reader for CGI::Session and make CGI::Session::CookieStore#generate_digest public so it's easy to generate digests using the cookie store's secret. *Rick Olson* * Added Request#url that returns the complete URL used for the request *David Heinemeier Hansson* * Extract dynamic scaffolding into a plugin. #7700 *Josh Peek* @@ -1883,7 +1893,7 @@ * Allow send_file/send_data to use a registered mime type as the :type parameter #7620 *jonathan* -* Allow routing requirements on map.resource(s) #7633 [quixoten]. Example: +* Allow routing requirements on map.resource(s) #7633 *quixoten*. Example: map.resources :network_interfaces, :requirements => { :id => /^\d+\.\d+\.\d+\.\d+$/ } @@ -1907,9 +1917,9 @@ :secret => Proc.new { User.current.secret_key } } -* Added .erb and .builder as preferred aliases to the now deprecated .rhtml and .rxml extensions [Chad Fowler]. This is done to separate the renderer from the mime type. .erb templates are often used to render emails, atom, csv, whatever. So labeling them .rhtml doesn't make too much sense. The same goes for .rxml, which can be used to build everything from HTML to Atom to whatever. .rhtml and .rxml will continue to work until Rails 3.0, though. So this is a slow phasing out. All generators and examples will start using the new aliases, though. +* Added .erb and .builder as preferred aliases to the now deprecated .rhtml and .rxml extensions *Chad Fowler*. This is done to separate the renderer from the mime type. .erb templates are often used to render emails, atom, csv, whatever. So labeling them .rhtml doesn't make too much sense. The same goes for .rxml, which can be used to build everything from HTML to Atom to whatever. .rhtml and .rxml will continue to work until Rails 3.0, though. So this is a slow phasing out. All generators and examples will start using the new aliases, though. -* Added caching option to AssetTagHelper#stylesheet_link_tag and AssetTagHelper#javascript_include_tag [David Heinemeier Hansson]. Examples: +* Added caching option to AssetTagHelper#stylesheet_link_tag and AssetTagHelper#javascript_include_tag *DHH*. Examples: stylesheet_link_tag :all, :cache => true # when ActionController::Base.perform_caching is false => <link href="/stylesheets/style1.css" media="screen" rel="Stylesheet" type="text/css" /> @@ -1948,7 +1958,7 @@ * Fix #render_file so that TemplateError is called with the correct params and you don't get the WSOD. *Rick Olson* * Fix issue with deprecation messing up #template_root= usage. Add #prepend_view_path and #append_view_path to allow modification of a copy of the - superclass' view_paths. [Rick Olson] + superclass' view_paths. *Rick Olson* * Allow Controllers to have multiple view_paths instead of a single template_root. Closes #2754 *John Long* * Add much-needed html-scanner tests. Fixed CDATA parsing bug. *Rick Olson* @@ -2100,13 +2110,13 @@ * Added map.root as an alias for map.connect '' *David Heinemeier Hansson* -* Added Request#format to return the format used for the request as a mime type. If no format is specified, the first Request#accepts type is used. This means you can stop using respond_to for anything else than responses [David Heinemeier Hansson]. Examples: +* Added Request#format to return the format used for the request as a mime type. If no format is specified, the first Request#accepts type is used. This means you can stop using respond_to for anything else than responses *DHH*. Examples: GET /posts/5.xml | request.format => Mime::XML GET /posts/5.xhtml | request.format => Mime::HTML GET /posts/5 | request.format => request.accepts.first (usually Mime::HTML for browsers) -* Added the option for extension aliases to mime type registration [David Heinemeier Hansson]. Example (already in the default routes): +* Added the option for extension aliases to mime type registration *DHH*. Example (already in the default routes): Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml ) @@ -2173,7 +2183,7 @@ * Add a 0 margin/padding div around the hidden _method input tag that form_tag outputs. *Rick Olson* -* Added block-usage to TagHelper#content_tag [David Heinemeier Hansson]. Example: +* Added block-usage to TagHelper#content_tag *DHH*. Example: <% content_tag :div, :class => "strong" %> Hello world! @@ -2204,7 +2214,7 @@ * Fix deprecation warnings when rendering the template error template. *Nicholas Seckar* -* Fix routing to correctly determine when generation fails. Closes #6300. [psross]. +* Fix routing to correctly determine when generation fails. Closes #6300. *psross*. * Fix broken assert_generates when extra keys are being checked. *Jamis Buck* @@ -2230,7 +2240,7 @@ * Fixed that FormHelper#radio_button didn't respect an :id being passed in #6266 *evansj* -* Added an html_options hash parameter to javascript_tag() and update_page_tag() helpers #6311 [tzaharia]. Example: +* Added an html_options hash parameter to javascript_tag() and update_page_tag() helpers #6311 *tzaharia*. Example: update_page_tag :defer => 'true' { |page| ... } @@ -2254,13 +2264,13 @@ * Deprecation: @cookies, @headers, @request, @response will be removed after 1.2. Use the corresponding method instead. *Jeremy Kemper* -* Make the :status parameter expand to the default message for that status code if it is an integer. Also support symbol statuses. [Jamis Buck]. Examples: +* Make the :status parameter expand to the default message for that status code if it is an integer. Also support symbol statuses. *Jamis Buck*. Examples: head :status => 404 # expands to "404 Not Found" head :status => :not_found # expands to "404 Not Found" head :status => :created # expands to "201 Created" -* Add head(options = {}) for responses that have no body. [Jamis Buck]. Examples: +* Add head(options = {}) for responses that have no body. *Jamis Buck*. Examples: head :status => 404 # return an empty response with a 404 status head :location => person_path(@person), :status => 201 @@ -2281,7 +2291,7 @@ * Rescue Errno::ECONNRESET to handle an unexpectedly closed socket connection. Improves SCGI reliability. #3368, #6226 *sdsykes, fhanshaw@vesaria.com* -* Added that respond_to blocks will automatically set the content type to be the same as is requested [David Heinemeier Hansson]. Examples: +* Added that respond_to blocks will automatically set the content type to be the same as is requested *DHH*. Examples: respond_to do |format| format.html { render :text => "I'm being sent as text/html" } @@ -2291,7 +2301,7 @@ * Added utf-8 as the default charset for all renders. You can change this default using ActionController::Base.default_charset=(encoding) *David Heinemeier Hansson* -* Added proper getters and setters for content type and charset [David Heinemeier Hansson]. Example of what we used to do: +* Added proper getters and setters for content type and charset *DHH*. Example of what we used to do: response.headers["Content-Type"] = "application/atom+xml; charset=utf-8" @@ -2336,7 +2346,7 @@ * Update UrlWriter to support :only_path. *Nicholas Seckar, Dave Thomas* -* Fixed JavaScriptHelper#link_to_function and JavaScriptHelper#button_to_function to have the script argument be optional [David Heinemeier Hansson]. So what used to require a nil, like this: +* Fixed JavaScriptHelper#link_to_function and JavaScriptHelper#button_to_function to have the script argument be optional *DHH*. So what used to require a nil, like this: link_to("Hider", nil, :class => "hider_link") { |p| p[:something].hide } @@ -2348,7 +2358,7 @@ * Update to Prototype 1.5.0_rc1 *sam* -* Added access to nested attributes in RJS #4548 [richcollins@gmail.com]. Examples: +* Added access to nested attributes in RJS #4548 *richcollins@gmail.com*. Examples: page['foo']['style'] # => $('foo').style; page['foo']['style']['color'] # => $('blank_slate').style.color; @@ -2460,7 +2470,7 @@ * Fixed the new_#{resource}_url route and added named route tests for Simply Restful. *Rick Olson* -* Added map.resources from the Simply Restful plugin [David Heinemeier Hansson]. Examples (the API has changed to use plurals!): +* Added map.resources from the Simply Restful plugin *DHH*. Examples (the API has changed to use plurals!): map.resources :messages map.resources :messages, :comments @@ -2533,9 +2543,9 @@ * Added Mime::TEXT (text/plain) and Mime::ICS (text/calendar) as new default types *David Heinemeier Hansson* -* Added Mime::Type.register(string, symbol, synonyms = []) for adding new custom mime types [David Heinemeier Hansson]. Example: Mime::Type.register("image/gif", :gif) +* Added Mime::Type.register(string, symbol, synonyms = []) for adding new custom mime types *DHH*. Example: Mime::Type.register("image/gif", :gif) -* Added support for Mime objects in render :content_type option [David Heinemeier Hansson]. Example: render :text => some_atom, :content_type => Mime::ATOM +* Added support for Mime objects in render :content_type option *DHH*. Example: render :text => some_atom, :content_type => Mime::ATOM * Add :status option to send_data and send_file. Defaults to '200 OK'. #5243 *Manfred Stienstra <m.stienstra@fngtps.com>* @@ -2549,7 +2559,7 @@ * Accept multipart PUT parameters. #5235 *guy.naor@famundo.com* -* Added interrogation of params[:format] to determine Accept type. If :format is specified and matches a declared extension, like "rss" or "xml", that mime type will be put in front of the accept handler. This means you can link to the same action from different extensions and use that fact to determine output [David Heinemeier Hansson]. Example: +* Added interrogation of params[:format] to determine Accept type. If :format is specified and matches a declared extension, like "rss" or "xml", that mime type will be put in front of the accept handler. This means you can link to the same action from different extensions and use that fact to determine output *DHH*. Example: class WeblogController < ActionController::Base def index @@ -2817,7 +2827,7 @@ * Add a 0 margin/padding div around the hidden _method input tag that form_tag outputs. *Rick Olson* -* Added block-usage to TagHelper#content_tag [David Heinemeier Hansson]. Example: +* Added block-usage to TagHelper#content_tag *DHH*. Example: <% content_tag :div, :class => "strong" %> Hello world! @@ -2846,7 +2856,7 @@ * Fix double-escaped entities, such as &amp;, &#123;, etc. *Rick Olson* -* Fix routing to correctly determine when generation fails. Closes #6300. [psross]. +* Fix routing to correctly determine when generation fails. Closes #6300. *psross*. * Fix broken assert_generates when extra keys are being checked. *Jamis Buck* @@ -2868,7 +2878,7 @@ * Fixed that FormHelper#radio_button didn't respect an :id being passed in #6266 *evansj* -* Added an html_options hash parameter to javascript_tag() and update_page_tag() helpers #6311 [tzaharia]. Example: +* Added an html_options hash parameter to javascript_tag() and update_page_tag() helpers #6311 *tzaharia*. Example: update_page_tag :defer => 'true' { |page| ... } @@ -2892,13 +2902,13 @@ * Deprecation: @cookies, @headers, @request, @response will be removed after 1.2. Use the corresponding method instead. *Jeremy Kemper* -* Make the :status parameter expand to the default message for that status code if it is an integer. Also support symbol statuses. [Jamis Buck]. Examples: +* Make the :status parameter expand to the default message for that status code if it is an integer. Also support symbol statuses. *Jamis Buck*. Examples: head :status => 404 # expands to "404 Not Found" head :status => :not_found # expands to "404 Not Found" head :status => :created # expands to "201 Created" -* Add head(options = {}) for responses that have no body. [Jamis Buck]. Examples: +* Add head(options = {}) for responses that have no body. *Jamis Buck*. Examples: head :status => 404 # return an empty response with a 404 status head :location => person_path(@person), :status => 201 @@ -2917,7 +2927,7 @@ * Rescue Errno::ECONNRESET to handle an unexpectedly closed socket connection. Improves SCGI reliability. #3368, #6226 *sdsykes, fhanshaw@vesaria.com* -* Added that respond_to blocks will automatically set the content type to be the same as is requested [David Heinemeier Hansson]. Examples: +* Added that respond_to blocks will automatically set the content type to be the same as is requested *DHH*. Examples: respond_to do |format| format.html { render :text => "I'm being sent as text/html" } @@ -2927,7 +2937,7 @@ * Added utf-8 as the default charset for all renders. You can change this default using ActionController::Base.default_charset=(encoding) *David Heinemeier Hansson* -* Added proper getters and setters for content type and charset [David Heinemeier Hansson]. Example of what we used to do: +* Added proper getters and setters for content type and charset *DHH*. Example of what we used to do: response.headers["Content-Type"] = "application/atom+xml; charset=utf-8" @@ -2964,7 +2974,7 @@ * Update UrlWriter to support :only_path. *Nicholas Seckar, Dave Thomas* -* Fixed JavaScriptHelper#link_to_function and JavaScriptHelper#button_to_function to have the script argument be optional [David Heinemeier Hansson]. So what used to require a nil, like this: +* Fixed JavaScriptHelper#link_to_function and JavaScriptHelper#button_to_function to have the script argument be optional *DHH*. So what used to require a nil, like this: link_to("Hider", nil, :class => "hider_link") { |p| p[:something].hide } @@ -2972,7 +2982,7 @@ link_to("Hider", :class => "hider_link") { |p| p[:something].hide } -* Added access to nested attributes in RJS #4548 [richcollins@gmail.com]. Examples: +* Added access to nested attributes in RJS #4548 *richcollins@gmail.com*. Examples: page['foo']['style'] # => $('foo').style; page['foo']['style']['color'] # => $('blank_slate').style.color; @@ -3059,7 +3069,7 @@ * Fixed the new_#{resource}_url route and added named route tests for Simply Restful. *Rick Olson* -* Added map.resources from the Simply Restful plugin [David Heinemeier Hansson]. Examples (the API has changed to use plurals!): +* Added map.resources from the Simply Restful plugin *DHH*. Examples (the API has changed to use plurals!): map.resources :messages map.resources :messages, :comments @@ -3126,9 +3136,9 @@ * Added Mime::TEXT (text/plain) and Mime::ICS (text/calendar) as new default types *David Heinemeier Hansson* -* Added Mime::Type.register(string, symbol, synonyms = []) for adding new custom mime types [David Heinemeier Hansson]. Example: Mime::Type.register("image/gif", :gif) +* Added Mime::Type.register(string, symbol, synonyms = []) for adding new custom mime types *DHH*. Example: Mime::Type.register("image/gif", :gif) -* Added support for Mime objects in render :content_type option [David Heinemeier Hansson]. Example: render :text => some_atom, :content_type => Mime::ATOM +* Added support for Mime objects in render :content_type option *DHH*. Example: render :text => some_atom, :content_type => Mime::ATOM * Add :status option to send_data and send_file. Defaults to '200 OK'. #5243 *Manfred Stienstra <m.stienstra@fngtps.com>* @@ -3142,7 +3152,7 @@ * Accept multipart PUT parameters. #5235 *guy.naor@famundo.com* -* Added interrogation of params[:format] to determine Accept type. If :format is specified and matches a declared extension, like "rss" or "xml", that mime type will be put in front of the accept handler. This means you can link to the same action from different extensions and use that fact to determine output [David Heinemeier Hansson]. Example: +* Added interrogation of params[:format] to determine Accept type. If :format is specified and matches a declared extension, like "rss" or "xml", that mime type will be put in front of the accept handler. This means you can link to the same action from different extensions and use that fact to determine output *DHH*. Example: class WeblogController < ActionController::Base def index @@ -3281,7 +3291,7 @@ * Applied Prototype $() performance patches (#4465, #4477) and updated script.aculo.us *Sam Stephenson, Thomas Fuchs* -* Added automated timestamping to AssetTagHelper methods for stylesheets, javascripts, and images when Action Controller is run under Rails [David Heinemeier Hansson]. Example: +* Added automated timestamping to AssetTagHelper methods for stylesheets, javascripts, and images when Action Controller is run under Rails *DHH*. Example: image_tag("rails.png") # => '<img alt="Rails" src="/images/rails.png?1143664135" />' @@ -3335,7 +3345,7 @@ * Change url_for to escape the resulting URLs when called from a view. *Nicholas Seckar, coffee2code* -* Added easy support for testing file uploads with fixture_file_upload #4105 [turnip@turnipspatch.com]. Example: +* Added easy support for testing file uploads with fixture_file_upload #4105 *turnip@turnipspatch.com*. Example: # Looks in Test::Unit::TestCase.fixture_path + '/files/spongebob.png' post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png') @@ -3370,11 +3380,11 @@ * Added simple alert() notifications for RJS exceptions when config.action_view.debug_rjs = true. *Sam Stephenson* -* Added :content_type option to render, so you can change the content type on the fly [David Heinemeier Hansson]. Example: render :action => "atom.rxml", :content_type => "application/atom+xml" +* Added :content_type option to render, so you can change the content type on the fly *DHH*. Example: render :action => "atom.rxml", :content_type => "application/atom+xml" * CHANGED DEFAULT: The default content type for .rxml is now application/xml instead of type/xml, see http://www.xml.com/pub/a/2004/07/21/dive.html for reason *David Heinemeier Hansson* -* Added option to render action/template/file of a specific extension (and here by template type). This means you can have multiple templates with the same name but a different extension [David Heinemeier Hansson]. Example: +* Added option to render action/template/file of a specific extension (and here by template type). This means you can have multiple templates with the same name but a different extension *DHH*. Example: class WeblogController < ActionController::Base def index @@ -3388,7 +3398,7 @@ end end -* Added better support for using the same actions to output for different sources depending on the Accept header [David Heinemeier Hansson]. Example: +* Added better support for using the same actions to output for different sources depending on the Accept header *DHH*. Example: class WeblogController < ActionController::Base def create @@ -3409,7 +3419,7 @@ * Integration test's url_for now runs in the context of the last request (if any) so after post /products/show/1 url_for :action => 'new' will yield /product/new *Tobias Lütke* -* Re-added mixed-in helper methods for the JavascriptGenerator. Moved JavascriptGenerators methods to a module that is mixed in after the helpers are added. Also fixed that variables set in the enumeration methods like #collect are set correctly. Documentation added for the enumeration methods [Rick Olson]. Examples: +* Re-added mixed-in helper methods for the JavascriptGenerator. Moved JavascriptGenerators methods to a module that is mixed in after the helpers are added. Also fixed that variables set in the enumeration methods like #collect are set correctly. Documentation added for the enumeration methods *Rick Olson*. Examples: page.select('#items li').collect('items') do |element| element.hide @@ -3427,7 +3437,7 @@ # Assign the default XmlSimple to a new content type ActionController::Base.param_parsers['application/backpack+xml'] = :xml_simple - Default YAML web services were retired, ActionController::Base.param_parsers carries an example which shows how to get this functionality back. As part of this new plugin support, request.[formatted_post?, xml_post?, yaml_post? and post_format] were all deprecated in favor of request.content_type [Tobias Lütke] + Default YAML web services were retired, ActionController::Base.param_parsers carries an example which shows how to get this functionality back. As part of this new plugin support, request.[formatted_post?, xml_post?, yaml_post? and post_format] were all deprecated in favor of request.content_type *Tobias Lütke* * Fixed Effect.Appear in effects.js to work with floats in Safari #3524, #3813, #3044 *Thomas Fuchs* * Fixed that default image extension was not appended when using a full URL with AssetTagHelper#image_tag #4032, #3728 *rubyonrails@beautifulpixel.com* @@ -3442,7 +3452,7 @@ * Added .rxml (and any non-rhtml template, really) supportfor CaptureHelper#content_for and CaptureHelper#capture #3287 *Brian Takita* -* Added script.aculo.us drag and drop helpers to RJS [Thomas Fuchs]. Examples: +* Added script.aculo.us drag and drop helpers to RJS *Thomas Fuchs*. Examples: page.draggable 'product-1' page.drop_receiving 'wastebasket', :url => { :action => 'delete' } @@ -3460,7 +3470,7 @@ * Update script.aculo.us to V1.5.2 *Thomas Fuchs* -* Added element and collection proxies to RJS [David Heinemeier Hansson]. Examples: +* Added element and collection proxies to RJS *DHH*. Examples: page['blank_slate'] # => $('blank_slate'); page['blank_slate'].show # => $('blank_slate').show(); @@ -3510,7 +3520,7 @@ * Ensure that the instance variables are copied to the template when performing render :update. *Nicholas Seckar* -* Add the ability to call JavaScriptGenerator methods from helpers called in update blocks. [Sam Stephenson] Example: +* Add the ability to call JavaScriptGenerator methods from helpers called in update blocks. *Sam Stephenson* Example: module ApplicationHelper def update_time page.replace_html 'time', Time.now.to_s(:db) @@ -3544,7 +3554,7 @@ * Pass along blocks from render_to_string to render. *Sam Stephenson* -* Add render :update for inline RJS. [Sam Stephenson] Example: +* Add render :update for inline RJS. *Sam Stephenson* Example: class UserController < ApplicationController def refresh render :update do |page| @@ -3594,7 +3604,7 @@ * Added :select option for JavaScriptMacroHelper#auto_complete_field that makes it easier to only use part of the auto-complete suggestion as the value for insertion *Thomas Fuchs* -* Added delayed execution of Javascript from within RJS #3264 [devslashnull@gmail.com]. Example: +* Added delayed execution of Javascript from within RJS #3264 *devslashnull@gmail.com*. Example: page.delay(20) do page.visual_effect :fade, 'notice' @@ -3678,7 +3688,7 @@ * Handle cookie parsing irregularity for certain Nokia phones. #2530 *zaitzow@gmail.com* -* Added PrototypeHelper::JavaScriptGenerator and PrototypeHelper#update_page for easily modifying multiple elements in an Ajax response. [Sam Stephenson] Example: +* Added PrototypeHelper::JavaScriptGenerator and PrototypeHelper#update_page for easily modifying multiple elements in an Ajax response. *Sam Stephenson* Example: update_page do |page| page.insert_html :bottom, 'list', '<li>Last item</li>' @@ -3702,7 +3712,7 @@ * Only include builtin filters whose filenames match /^[a-z][a-z_]*_helper.rb$/ to avoid including operating system metadata such as ._foo_helper.rb. #2855 *court3nay* -* Added FormHelper#form_for and FormHelper#fields_for that makes it easier to work with forms for single objects also if they don't reside in instance variables [David Heinemeier Hansson]. Examples: +* Added FormHelper#form_for and FormHelper#fields_for that makes it easier to work with forms for single objects also if they don't reside in instance variables *DHH*. Examples: <% form_for :person, @person, :url => { :action => "update" } do |f| %> First name: <%= f.text_field :first_name %> @@ -3745,7 +3755,7 @@ * Added short-hand to assert_tag so assert_tag :tag => "span" can be written as assert_tag "span" *David Heinemeier Hansson* -* Added skip_before_filter/skip_after_filter for easier control of the filter chain in inheritance hierachies [David Heinemeier Hansson]. Example: +* Added skip_before_filter/skip_after_filter for easier control of the filter chain in inheritance hierachies *DHH*. Example: class ApplicationController < ActionController::Base before_filter :authenticate @@ -3928,7 +3938,7 @@ * Fixed that number_to_currency(1000, {:precision => 0})) should return "$1,000", instead of "$1,000." #2122 *sd@notso.net* -* Allow link_to_remote to use any DOM-element as the parent of the form elements to be submitted #2137 [erik@ruby-lang.nl]. Example: +* Allow link_to_remote to use any DOM-element as the parent of the form elements to be submitted #2137 *erik@ruby-lang.nl*. Example: <tr id="row023"> <td><input name="foo"/></td> @@ -3955,7 +3965,7 @@ * Updated vendor copy of html-scanner to support better xml parsing -* Added :popup option to UrlHelper#link_to #1996 [gabriel.gironda@gmail.com]. Examples: +* Added :popup option to UrlHelper#link_to #1996 *gabriel.gironda@gmail.com*. Examples: link_to "Help", { :action => "help" }, :popup => true link_to "Busy loop", { :action => "busy" }, :popup => ['new_window', 'height=300,width=600'] @@ -4012,7 +4022,7 @@ * Added support for per-action session management #1763 -* Improved rendering speed on complicated templates by up to 100% (the more complex the templates, the higher the speedup) #1234 [Stefan Kaes]. This did necessasitate a change to the internals of ActionView#render_template that now has four parameters. Developers of custom view handlers (like Amrita) need to update for that. +* Improved rendering speed on complicated templates by up to 100% (the more complex the templates, the higher the speedup) #1234 *Stefan Kaes*. This did necessasitate a change to the internals of ActionView#render_template that now has four parameters. Developers of custom view handlers (like Amrita) need to update for that. * Added options hash as third argument to FormHelper#input, so you can do input('person', 'zip', :size=>10) #1719 *jeremye@bsa.ca.gov* @@ -4087,7 +4097,7 @@ * Added :prompt option to FormOptions#select (and the users of it, like FormOptions#select_country etc) to create "Please select" style descriptors #1181 *Michael Schuerig* -* Added JavascriptHelper#update_element_function, which returns a Javascript function (or expression) that'll update a DOM element according to the options passed #933 [mortonda@dgrmm.net]. Examples: +* Added JavascriptHelper#update_element_function, which returns a Javascript function (or expression) that'll update a DOM element according to the options passed #933 *mortonda@dgrmm.net*. Examples: <%= update_element_function("products", :action => :insert, :position => :bottom, :content => "<p>New product!</p>") %> @@ -4104,7 +4114,7 @@ * Removed the default option of wrap=virtual on FormHelper#text_area to ensure XHTML compatibility #1300 *thomas@columbus.rr.com* -* Adds the ability to include XML CDATA tags using Builder #1563 [Josh Knowles]. Example: +* Adds the ability to include XML CDATA tags using Builder #1563 *Josh Knowles*. Example: xml.cdata! "some text" # => <![CDATA[some text]]> @@ -4116,7 +4126,7 @@ * Routes fail with leading slash #1540 *Nicholas Seckar* -* Added support for graceful error handling of Ajax calls #1217 [Jamis Buck/Thomas Fuchs]. Example: +* Added support for graceful error handling of Ajax calls #1217 *Jamis Buck/Thomas Fuchs*. Example: link_to_remote( "test", @@ -4146,7 +4156,7 @@ * Added TextHelper#word_wrap(text, line_length = 80) #1449 *tuxie@dekadance.se* -* Added a fall-through action for form_remote_tag that'll be used in case Javascript is unavailable #1459 [Scott Barron]. Example: +* Added a fall-through action for form_remote_tag that'll be used in case Javascript is unavailable #1459 *Scott Barron*. Example: form_remote_tag :html => { :action => url_for(:controller => "some", :action => "place") } @@ -4154,7 +4164,7 @@ * Added tag_options as a third parameter to AssetHelper#auto_discovery_link_tag to control options like the title of the link #1430 *Kevin Clark* -* Added option to pass in parameters to CaptureHelper#capture, so you can create more advanced view helper methods #1466 [duane.johnson@gmail.com]. Example: +* Added option to pass in parameters to CaptureHelper#capture, so you can create more advanced view helper methods #1466 *duane.johnson@gmail.com*. Example: <% show_calendar(:year => 2005, :month => 6) do |day, options| %> <% options[:bgcolor] = '#dfd' if 10..15.include? day %> @@ -4167,7 +4177,7 @@ * Correct distance_of_time_in_words for integer arguments and make the second arg optional, treating the first arg as a duration in seconds. #1458 *madrobby <thomas@fesch.at>* -* Fixed query parser to deal gracefully with equal signs inside keys and values #1345 [gorou]. +* Fixed query parser to deal gracefully with equal signs inside keys and values #1345 *gorou*. Example: /?sig=abcdef=:foobar=&x=y will pass now. * Added Cuba to country list #1351 *todd* @@ -4180,7 +4190,7 @@ * Fixed image_tag so an exception is not thrown just because the image is missing and alt value can't be generated #1395 *Marcel Molina Jr.* -* Added a third parameter to TextHelper#auto_link called href_options for specifying additional tag options on the links generated #1401 [tyler.kovacs@gmail.com]. Example: auto_link(text, :all, { :target => "_blank" }) to have all the generated links open in a new window. +* Added a third parameter to TextHelper#auto_link called href_options for specifying additional tag options on the links generated #1401 *tyler.kovacs@gmail.com*. Example: auto_link(text, :all, { :target => "_blank" }) to have all the generated links open in a new window. * Fixed TextHelper#highlight to return the text, not nil, if the phrase is blank #1409 *Patrick Lenz* @@ -4366,7 +4376,7 @@ ## 1.8.1 (20th April, 2005) ## -* Added xml_http_request/xhr method for simulating XMLHttpRequest in functional tests #1151 [Sam Stephenson]. Example: +* Added xml_http_request/xhr method for simulating XMLHttpRequest in functional tests #1151 *Sam Stephenson*. Example: xhr :post, :index @@ -4388,18 +4398,18 @@ * Deprecated the majority of all the testing assertions and replaced them with a much smaller core and access to all the collections the old assertions relied on. That way the regular test/unit assertions can be used against these. Added documentation about how to use it all. * Added a wide range of new Javascript effects: - * Effect.Puff zooms the element out and makes it smoothly transparent at the same time, giving a "puff" illusion #996 [thomas@fesch.at] + * Effect.Puff zooms the element out and makes it smoothly transparent at the same time, giving a "puff" illusion #996 *thomas@fesch.at* After the animation is completed, the display property will be set to none. This effect will work on relative and absolute positioned elements. - * Effect.Appear as the opposite of Effect.Fade #990 [thomas@fesch.at] + * Effect.Appear as the opposite of Effect.Fade #990 *thomas@fesch.at* You should return elements with style="display:none;" or a like class for this to work best and have no chance of flicker. - * Effect.Squish for scaling down an element and making it disappear at the end #972 [thomas@fesch.at] + * Effect.Squish for scaling down an element and making it disappear at the end #972 *thomas@fesch.at* - * Effect.Scale for smoothly scaling images or text up and down #972 [thomas@fesch.at] + * Effect.Scale for smoothly scaling images or text up and down #972 *thomas@fesch.at* - * Effect.Fade which smoothly turns opacity from 100 to 0 and then hides the element #960 [thomas@fesch.at] + * Effect.Fade which smoothly turns opacity from 100 to 0 and then hides the element #960 *thomas@fesch.at* * Added Request#xml_http_request? (and an alias xhr?) to that'll return true when the request came from one of the Javascript helper methods (Ajax). This can be used to give one behavior for modern browsers supporting Ajax, another to old browsers #1127 *Sam Stephenson* @@ -4537,7 +4547,7 @@ * Fixed routing and helpers to make Rails work on non-vhost setups #826 *Nicholas Seckar/Tobias Lütke* -* Added a much improved Flash module that allows for finer-grained control on expiration and allows you to flash the current action #839 [Caio Chassot]. Example of flash.now: +* Added a much improved Flash module that allows for finer-grained control on expiration and allows you to flash the current action #839 *Caio Chassot*. Example of flash.now: class SomethingController < ApplicationController def save @@ -4554,7 +4564,7 @@ end end -* Added to_param call for parameters when composing an url using url_for from something else than strings #812 [Sam Stephenson]. Example: +* Added to_param call for parameters when composing an url using url_for from something else than strings #812 *Sam Stephenson*. Example: class Page def initialize(number) @@ -4583,7 +4593,7 @@ * Added that the html options disabled, readonly, and multiple can all be treated as booleans. So specifying <tt>disabled => :true</tt> will give <tt>disabled="disabled"</tt>. #809 *mindel* -* Added path collection syntax for Routes that will gobble up the rest of the url and pass it on to the controller #830 [rayners]. Example: +* Added path collection syntax for Routes that will gobble up the rest of the url and pass it on to the controller #830 *rayners*. Example: map.connect 'categories/*path_info', :controller => 'categories', :action => 'show' @@ -4600,7 +4610,7 @@ * Removed the reliance on PATH_INFO as it was causing problems for caching and inhibited the new non-vhost support #822 *Nicholas Seckar* -* Added assigns shortcut for @response.template.assigns to controller test cases [Jeremy Kemper]. Example: +* Added assigns shortcut for @response.template.assigns to controller test cases *Jeremy Kemper*. Example: Before: @@ -5012,7 +5022,7 @@ * Added that ActiveRecordHelper#form now calls url_for on the :action option. -* Added all the HTTP methods as alternatives to the generic "process" for functional testing #276 [Tobias Lütke]. Examples: +* Added all the HTTP methods as alternatives to the generic "process" for functional testing #276 *Tobias Lütke*. Examples: # Calls Controller#miletone with a GET request process :milestone @@ -5185,7 +5195,7 @@ * Added assert_flash_equal(expected, key, message), assert_session_equal(expected, key, message), assert_assigned_equal(expected, key, message) to test the contents of flash, session, and template assigns. -* Improved the failure report on assert_success when the action triggered a redirection [alexey]. +* Improved the failure report on assert_success when the action triggered a redirection *alexey*. * Added "markdown" to accompany "textilize" as a TextHelper method for converting text to HTML using the Markdown syntax. BlueCloth must be installed in order for this method to become available. @@ -5260,7 +5270,7 @@ *Builder is created by Jim Weirich* -* Added much improved support for functional testing [what-a-day]. +* Added much improved support for functional testing *what-a-day*. # Old style def test_failing_authenticate @@ -5289,7 +5299,7 @@ following the suggestion from Matz on: http://groups.google.com/groups?th=e3a4e68ba042f842&seekm=c3sioe%241qvm%241%40news.cybercity.dk#link14 -* Added caching for compiled ERb templates. On Basecamp, it gave between 8.5% and 71% increase in performance [Andreas Schwarz]. +* Added caching for compiled ERb templates. On Basecamp, it gave between 8.5% and 71% increase in performance *Andreas Schwarz*. * Added implicit counter variable to render_collection_of_partials [Marcel Molina Jr.]. From the docs: @@ -5316,7 +5326,7 @@ :confirm => 'Are you sure?', the link will be guarded with a JS popup asking that question. If the user accepts, the link is processed, otherwise not. -* Added link_to_unless_current as a UrlHelper method [Sam Stephenson]. Documentation: +* Added link_to_unless_current as a UrlHelper method *Sam Stephenson*. Documentation: Creates a link tag of the given +name+ using an URL created by the set of +options+, unless the current controller, action, and id are the same as the link's, in which case only the name is returned (or the @@ -5447,7 +5457,7 @@ So this will render "advertiser/_ad.rhtml" and pass the local variable +ad+ for the template to display. -* Improved send_file by allowing a wide range of options to be applied [Jeremy Kemper]: +* Improved send_file by allowing a wide range of options to be applied *Jeremy Kemper*: Sends the file by streaming it 4096 bytes at a time. This way the whole file doesn't need to be read into memory at once. This makes @@ -5698,7 +5708,7 @@ * Fixed that exceptions raised during filters are now also caught by the default rescues -* Added new around_filter for doing before and after filtering with a single object [Florian Weber]: +* Added new around_filter for doing before and after filtering with a single object *Florian Weber*: class WeblogController < ActionController::Base around_filter BenchmarkingFilter.new @@ -5724,7 +5734,7 @@ end end -* Added the options for specifying a different name and id for the form helper methods than what is guessed [Florian Weber]: +* Added the options for specifying a different name and id for the form helper methods than what is guessed *Florian Weber*: text_field "post", "title" ...just gives: <input id="post_title" name="post[title]" size="30" type="text" value="" /> diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index fa300b4a16..2f6b9d266d 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -284,10 +284,5 @@ module ActionDispatch SEPARATORS = %w( / . ? ) #:nodoc: HTTP_METHODS = [:get, :head, :post, :put, :delete, :options] #:nodoc: - - # A helper module to hold URL related helpers. - module Helpers #:nodoc: - include PolymorphicRoutes - end end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 10b3e212e6..9d0a3e9993 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -123,11 +123,6 @@ module ActionDispatch routes.length end - def install(destinations = [ActionController::Base, ActionView::Base]) - helper = @module - destinations.each { |d| d.module_eval { include helper } } - end - private def url_helper_name(name, kind = :url) :"#{name}_#{kind}" @@ -276,14 +271,15 @@ module ActionDispatch @prepend.each { |blk| eval_block(blk) } end - def install_helpers(destinations) - destinations.each { |d| d.module_eval { include Helpers } } - named_routes.install(destinations) - end - - module MountedHelpers + module MountedHelpers #:nodoc: + extend ActiveSupport::Concern + include UrlFor end + # Contains all the mounted helpers accross different + # engines and the `main_app` helper for the application. + # You can include this in your classes if you want to + # access routes for other engines. def mounted_helpers MountedHelpers end @@ -294,7 +290,7 @@ module ActionDispatch routes = self MountedHelpers.class_eval do define_method "_#{name}" do - RoutesProxy.new(routes, self._routes_context) + RoutesProxy.new(routes, _routes_context) end end @@ -306,29 +302,40 @@ module ActionDispatch end def url_helpers - routes = self + @url_helpers ||= begin + routes = self + + Module.new do + extend ActiveSupport::Concern + include UrlFor + + # Define url_for in the singleton level so one can do: + # Rails.application.routes.url_helpers.url_for(args) + @_routes = routes + class << self + delegate :url_for, :to => '@_routes' + end - @url_helpers ||= Module.new { - extend ActiveSupport::Concern - include UrlFor + # Make named_routes available in the module singleton + # as well, so one can do: + # Rails.application.routes.url_helpers.posts_path + extend routes.named_routes.module - @_routes = routes - def self.url_for(options) - @_routes.url_for options - end + # Any class that includes this module will get all + # named routes... + include routes.named_routes.module - extend routes.named_routes.module + # plus a singleton class method called _routes ... + included do + singleton_class.send(:redefine_method, :_routes) { routes } + end - # ROUTES TODO: install_helpers isn't great... can we make a module with the stuff that - # we can include? - # Yes plz - JP - included do - routes.install_helpers([self]) - singleton_class.send(:redefine_method, :_routes) { routes } + # And an instance method _routes. Note that + # UrlFor (included in this module) add extra + # conveniences for working with @_routes. + define_method(:_routes) { @_routes || routes } end - - define_method(:_routes) { @_routes || routes } - } + end end def empty? diff --git a/actionpack/lib/action_dispatch/routing/routes_proxy.rb b/actionpack/lib/action_dispatch/routing/routes_proxy.rb index f7d5f6397d..73af5920ed 100644 --- a/actionpack/lib/action_dispatch/routing/routes_proxy.rb +++ b/actionpack/lib/action_dispatch/routing/routes_proxy.rb @@ -16,6 +16,10 @@ module ActionDispatch end end + def respond_to?(method, include_private = false) + super || routes.url_helpers.respond_to?(method) + end + def method_missing(method, *args) if routes.url_helpers.respond_to?(method) self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1 diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 6c2a98ab15..ee6616c5d3 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -8,7 +8,8 @@ module ActionDispatch # # <b>Tip:</b> If you need to generate URLs from your models or some other place, # then ActionController::UrlFor is what you're looking for. Read on for - # an introduction. + # an introduction. In general, this module should not be included on its own, + # as it is usually included by url_helpers (as in Rails.application.routes.url_helpers). # # == URL generation from parameters # @@ -84,7 +85,6 @@ module ActionDispatch include PolymorphicRoutes included do - # TODO: with_routing extends @controller with url_helpers, trickling down to including this module which overrides its default_url_options unless method_defined?(:default_url_options) # Including in a class uses an inheritable hash. Modules get a plain hash. if respond_to?(:class_attribute) @@ -151,16 +151,17 @@ module ActionDispatch end protected - def _with_routes(routes) - old_routes, @_routes = @_routes, routes - yield - ensure - @_routes = old_routes - end - def _routes_context - self - end + def _with_routes(routes) + old_routes, @_routes = @_routes, routes + yield + ensure + @_routes = old_routes + end + + def _routes_context + self + end end end end diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 653e12c7d8..5dbba3c4a7 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -306,6 +306,20 @@ module ActionView end alias_method :path_to_audio, :audio_path # aliased to avoid conflicts with an audio_path named route + # Computes the path to a font asset in the public fonts directory. + # Full paths from the document root will be passed through. + # + # ==== Examples + # font_path("font") # => /fonts/font + # font_path("font.ttf") # => /fonts/font.ttf + # font_path("dir/font.ttf") # => /fonts/dir/font.ttf + # font_path("/dir/font.ttf") # => /dir/font.ttf + # font_path("http://www.example.com/dir/font.ttf") # => http://www.example.com/dir/font.ttf + def font_path(source) + asset_paths.compute_public_path(source, 'fonts') + end + alias_method :path_to_font, :font_path # aliased to avoid conflicts with an font_path named route + # Returns an html image tag for the +source+. The +source+ can be a full # path or a file that exists in your public images directory. # diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index d46ee4faef..1e4bebeee7 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -1093,7 +1093,7 @@ module ActionView end hidden = tag("input", "name" => options["name"], "type" => "hidden", "value" => options['disabled'] && checked ? checked_value : unchecked_value) checkbox = tag("input", options) - (hidden + checkbox).html_safe + hidden + checkbox end def to_boolean_select_tag(options = {}) diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 1c0fdb8ff9..43122ef2ba 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -32,22 +32,29 @@ module ActionView # in the +options+ hash. # # ==== Options - # * <tt>:area_code</tt> - Adds parentheses around the area code. - # * <tt>:delimiter</tt> - Specifies the delimiter to use (defaults to "-"). - # * <tt>:extension</tt> - Specifies an extension to add to the end of the - # generated number. + # + # * <tt>:area_code</tt> - Adds parentheses around the area code. + # * <tt>:delimiter</tt> - Specifies the delimiter to use (defaults to "-"). + # * <tt>:extension</tt> - Specifies an extension to add to the end of the + # generated number. # * <tt>:country_code</tt> - Sets the country code for the phone number. + # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid. # # ==== Examples + # # number_to_phone(5551234) # => 555-1234 + # number_to_phone("5551234") # => 555-1234 # number_to_phone(1235551234) # => 123-555-1234 # number_to_phone(1235551234, :area_code => true) # => (123) 555-1234 # number_to_phone(1235551234, :delimiter => " ") # => 123 555 1234 # number_to_phone(1235551234, :area_code => true, :extension => 555) # => (123) 555-1234 x 555 # number_to_phone(1235551234, :country_code => 1) # => +1-123-555-1234 + # number_to_phone("123a456") # => 123a456 + # + # number_to_phone("1234a567", :raise => true) # => InvalidNumberError # # number_to_phone(1235551234, :country_code => 1, :extension => 1343, :delimiter => ".") - # => +1.123.555.1234 x 1343 + # # => +1.123.555.1234 x 1343 def number_to_phone(number, options = {}) return unless number @@ -82,6 +89,7 @@ module ActionView # in the +options+ hash. # # ==== Options + # # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale). # * <tt>:precision</tt> - Sets the level of precision (defaults to 2). # * <tt>:unit</tt> - Sets the denomination of the currency (defaults to "$"). @@ -94,12 +102,17 @@ module ActionView # an hyphen to the formatted number given by <tt>:format</tt>). # Accepts the same fields than <tt>:format</tt>, except # <tt>%n</tt> is here the absolute value of the number. + # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid. # # ==== Examples + # # number_to_currency(1234567890.50) # => $1,234,567,890.50 # number_to_currency(1234567890.506) # => $1,234,567,890.51 # number_to_currency(1234567890.506, :precision => 3) # => $1,234,567,890.506 # number_to_currency(1234567890.506, :locale => :fr) # => 1 234 567 890,51 € + # number_to_currency("123a456") # => $123a456 + # + # number_to_currency("123a456", :raise => true) # => InvalidNumberError # # number_to_currency(-1234567890.50, :negative_format => "(%u%n)") # # => ($1,234,567,890.50) @@ -114,6 +127,7 @@ module ActionView defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {}) currency = I18n.translate(:'number.currency.format', :locale => options[:locale], :default => {}) + currency[:negative_format] ||= "-" + currency[:format] if currency[:format] defaults = DEFAULT_CURRENCY_VALUES.merge(defaults).merge!(currency) defaults[:negative_format] = "-" + options[:format] if options[:format] @@ -141,23 +155,33 @@ module ActionView end - # Formats a +number+ as a percentage string (e.g., 65%). You can customize the - # format in the +options+ hash. + # Formats a +number+ as a percentage string (e.g., 65%). You can customize the format in the +options+ hash. # # ==== Options - # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale). - # * <tt>:precision</tt> - Sets the precision of the number (defaults to 3). - # * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +false+) - # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to "."). - # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ""). - # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +false+) + # + # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current + # locale). + # * <tt>:precision</tt> - Sets the precision of the number (defaults to 3). + # * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, + # the # of fractional digits (defaults to +false+). + # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults + # to "."). + # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ""). + # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator + # (defaults to +false+). + # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid. # # ==== Examples + # # number_to_percentage(100) # => 100.000% + # number_to_percentage("98") # => 98.000% # number_to_percentage(100, :precision => 0) # => 100% # number_to_percentage(1000, :delimiter => '.', :separator => ',') # => 1.000,000% # number_to_percentage(302.24398923423, :precision => 5) # => 302.24399% # number_to_percentage(1000, :locale => :fr) # => 1 000,000% + # number_to_percentage("98a") # => 98a% + # + # number_to_percentage("98a", :raise => true) # => InvalidNumberError def number_to_percentage(number, options = {}) return unless number @@ -184,19 +208,26 @@ module ActionView # customize the format in the +options+ hash. # # ==== Options + # # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale). # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ","). # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to "."). + # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid. # # ==== Examples + # # number_with_delimiter(12345678) # => 12,345,678 + # number_with_delimiter("123456") # => 123,456 # number_with_delimiter(12345678.05) # => 12,345,678.05 # number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678 # number_with_delimiter(12345678, :delimiter => ",") # => 12,345,678 # number_with_delimiter(12345678.05, :separator => " ") # => 12,345,678 05 # number_with_delimiter(12345678.05, :locale => :fr) # => 12 345 678,05 + # number_with_delimiter("112a") # => 112a # number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",") # # => 98 765 432,98 + # + # number_with_delimiter("112a", :raise => true) # => raise InvalidNumberError def number_with_delimiter(number, options = {}) options.symbolize_keys! @@ -224,12 +255,15 @@ module ActionView # You can customize the format in the +options+ hash. # # ==== Options - # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale). - # * <tt>:precision</tt> - Sets the precision of the number (defaults to 3). - # * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +false+) - # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to "."). - # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ""). - # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +false+) + # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale). + # * <tt>:precision</tt> - Sets the precision of the number (defaults to 3). + # * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, + # the # of fractional digits (defaults to +false+). + # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults + # to "."). + # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ""). + # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator + # (defaults to +false+). # # ==== Examples # number_with_precision(111.2345) # => 111.235 @@ -240,8 +274,10 @@ module ActionView # number_with_precision(111.2345, :precision => 1, :significant => true) # => 100 # number_with_precision(13, :precision => 5, :significant => true) # => 13.000 # number_with_precision(111.234, :locale => :fr) # => 111,234 + # # number_with_precision(13, :precision => 5, :significant => true, :strip_insignificant_zeros => true) # # => 13 + # # number_with_precision(389.32314, :precision => 4, :significant => true) # => 389.3 # number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.') # # => 1.111,23 diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index c34b3f6f26..976ae5a76d 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -63,13 +63,18 @@ module Sprockets end alias_method :path_to_image, :image_path # aliased to avoid conflicts with an image_path named route - def javascript_path(source) + def font_path(source) path_to_asset(source) end + alias_method :path_to_font, :font_path # aliased to avoid conflicts with an font_path named route + + def javascript_path(source) + path_to_asset(source, :ext => 'js') + end alias_method :path_to_javascript, :javascript_path # aliased to avoid conflicts with an javascript_path named route def stylesheet_path(source) - path_to_asset(source) + path_to_asset(source, :ext => 'css') end alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with an stylesheet_path named route diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index fab70c71d6..bdbf158b36 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -159,20 +159,6 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase assert_equal @response.body, 'request method: GET' end - def test_redirect_to_named_route - with_routing do |set| - set.draw do - match 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one - match ':controller/:action' - end - set.install_helpers([ActionController::Base, ActionView::Base]) - - process :redirect_to_named_route - assert_redirected_to 'http://test.host/route_one' - assert_redirected_to route_one_url - end - end - def test_string_constraint with_routing do |set| set.draw do diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index 93eccaecbd..bd5b5edab0 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -30,6 +30,7 @@ module TestGenerationPrefix match "/url_to_application", :to => "inside_engine_generating#url_to_application" match "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine" match "/conflicting_url", :to => "inside_engine_generating#conflicting" + match "/foo", :to => "never#invoked", :as => :named_helper_that_should_be_invoked_only_in_respond_to_test end routes @@ -152,6 +153,8 @@ module TestGenerationPrefix RailsApplication.routes.default_url_options = {} end + include BlogEngine.routes.mounted_helpers + # Inside Engine test "[ENGINE] generating engine's url use SCRIPT_NAME from request" do get "/pure-awesomeness/blog/posts/1" @@ -219,6 +222,10 @@ module TestGenerationPrefix end # Inside any Object + test "[OBJECT] proxy route should override respond_to?() as expected" do + assert_respond_to blog_engine, :named_helper_that_should_be_invoked_only_in_respond_to_test_path + end + test "[OBJECT] generating engine's route includes prefix" do assert_equal "/awesome/blog/posts/1", engine_object.post_path(:id => 1) end diff --git a/actionpack/test/fixtures/sprockets/app/fonts/dir/font.ttf b/actionpack/test/fixtures/sprockets/app/fonts/dir/font.ttf new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/actionpack/test/fixtures/sprockets/app/fonts/dir/font.ttf diff --git a/actionpack/test/fixtures/sprockets/app/fonts/font.ttf b/actionpack/test/fixtures/sprockets/app/fonts/font.ttf new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/actionpack/test/fixtures/sprockets/app/fonts/font.ttf diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 73b936b16e..6fe4ce65cf 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -330,6 +330,7 @@ class FormHelperTest < ActionView::TestCase end def test_check_box + assert check_box("post", "secret").html_safe? assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb index 5df09b4d3b..d6e9de9555 100644 --- a/actionpack/test/template/number_helper_i18n_test.rb +++ b/actionpack/test/template/number_helper_i18n_test.rb @@ -53,6 +53,13 @@ class NumberHelperTest < ActionView::TestCase assert_equal("-$10.00", number_to_currency(-10)) end end + + def test_number_to_currency_without_currency_negative_format + clean_i18n do + I18n.backend.store_translations 'ts', :number => { :currency => { :format => { :unit => '@', :format => '%n %u' } } } + assert_equal("-10.00 @", number_to_currency(-10, :locale => 'ts')) + end + end def test_number_with_i18n_precision #Delimiter was set to "" diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb index 64fdd53e73..1c591bdcc2 100644 --- a/actionpack/test/template/sprockets_helper_test.rb +++ b/actionpack/test/template/sprockets_helper_test.rb @@ -24,6 +24,7 @@ class SprocketsHelperTest < ActionView::TestCase @assets.append_path(FIXTURES.join("sprockets/app/javascripts")) @assets.append_path(FIXTURES.join("sprockets/app/stylesheets")) @assets.append_path(FIXTURES.join("sprockets/app/images")) + @assets.append_path(FIXTURES.join("sprockets/app/fonts")) application = Struct.new(:config, :assets).new(config, @assets) Rails.stubs(:application).returns(application) @@ -147,8 +148,19 @@ class SprocketsHelperTest < ActionView::TestCase path_to_image("logo.png") end + test "font_path" do + assert_match %r{/assets/font-[0-9a-f]+.ttf}, + font_path("font.ttf") + + assert_match %r{/assets/font-[0-9a-f]+.ttf}, + path_to_font("font.ttf") + end + test "javascript_path" do assert_match %r{/assets/application-[0-9a-f]+.js}, + javascript_path("application") + + assert_match %r{/assets/application-[0-9a-f]+.js}, javascript_path("application.js") assert_match %r{/assets/application-[0-9a-f]+.js}, @@ -157,6 +169,9 @@ class SprocketsHelperTest < ActionView::TestCase test "stylesheet_path" do assert_match %r{/assets/application-[0-9a-f]+.css}, + stylesheet_path("application") + + assert_match %r{/assets/application-[0-9a-f]+.css}, stylesheet_path("application.css") assert_match %r{/assets/application-[0-9a-f]+.css}, @@ -186,6 +201,17 @@ class SprocketsHelperTest < ActionView::TestCase asset_path("/images/logo.gif") end + test "font path through asset_path" do + assert_match %r{/assets/font-[0-9a-f]+.ttf}, + asset_path('font.ttf') + + assert_match %r{/assets/dir/font-[0-9a-f]+.ttf}, + asset_path("dir/font.ttf") + + assert_equal "http://www.example.com/fonts/font.ttf", + asset_path("http://www.example.com/fonts/font.ttf") + end + test "javascript path through asset_path" do assert_match %r{/assets/application-[0-9a-f]+.js}, asset_path(:application, :ext => "js") diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb index 1759a41d93..4183c222de 100644 --- a/activerecord/lib/active_record/associations/builder/belongs_to.rb +++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb @@ -33,8 +33,10 @@ module ActiveRecord::Associations::Builder method_name = "belongs_to_counter_cache_before_destroy_for_#{name}" mixin.redefine_method(method_name) do - record = send(name) - record.class.decrement_counter(cache_column, record.id) unless record.nil? + unless marked_for_destruction? + record = send(name) + record.class.decrement_counter(cache_column, record.id) unless record.nil? + end end model.before_destroy(method_name) diff --git a/activerecord/lib/active_record/associations/builder/has_many.rb b/activerecord/lib/active_record/associations/builder/has_many.rb index 9c24f40690..fc6799fb15 100644 --- a/activerecord/lib/active_record/associations/builder/has_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_many.rb @@ -31,12 +31,7 @@ module ActiveRecord::Associations::Builder mixin.redefine_method(dependency_method_name) do send(name).each do |o| # No point in executing the counter update since we're going to destroy the parent anyway - counter_method = ('belongs_to_counter_cache_before_destroy_for_' + self.class.name.downcase).to_sym - if o.respond_to?(counter_method) - class << o - self - end.send(:define_method, counter_method, Proc.new {}) - end + o.mark_for_destruction end send(name).delete_all diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index d29cf82dad..5c8dbd1b47 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1,8 +1,3 @@ -begin - require 'psych' -rescue LoadError -end - require 'yaml' require 'set' require 'active_support/benchmarkable' diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 980f8fe50f..0755379a74 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -317,26 +317,6 @@ module ActiveRecord "#<#{self.class} #{inspection}>" end - # Hackery to accomodate Syck. Remove for 4.0. - def to_yaml(opts = {}) #:nodoc: - if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? - super - else - coder = {} - encode_with(coder) - YAML.quick_emit(self, opts) do |out| - out.map(taguri, to_yaml_style) do |map| - coder.each { |k, v| map.add(k, v) } - end - end - end - end - - # Hackery to accomodate Syck. Remove for 4.0. - def yaml_initialize(tag, coder) #:nodoc: - init_with(coder) - end - private # Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index c59c00f424..339ba1e19e 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -1,10 +1,4 @@ require 'erb' - -begin - require 'psych' -rescue LoadError -end - require 'yaml' require 'zlib' require 'active_support/dependencies' @@ -445,7 +439,8 @@ module ActiveRecord self.all_loaded_fixtures = {} def self.create_fixtures(fixtures_directory, table_names, class_names = {}) - table_names = [table_names].flatten.map { |n| n.to_s } + table_names = Array(table_names).map(&:to_s) + class_names = class_names.stringify_keys # FIXME: Apparently JK uses this. connection = block_given? ? yield : ActiveRecord::Base.connection @@ -464,7 +459,7 @@ module ActiveRecord fixtures_map[fixture_name] = new( # ActiveRecord::Fixtures.new connection, fixture_name, - class_names[fixture_name] || default_fixture_model_name(fixture_name), + class_names[fixture_name.to_s] || default_fixture_model_name(fixture_name), ::File.join(fixtures_directory, path)) end @@ -728,6 +723,7 @@ module ActiveRecord self.pre_loaded_fixtures = false self.fixture_class_names = Hash.new do |h, fixture_name| + fixture_name = fixture_name.to_s h[fixture_name] = ActiveRecord::Fixtures.default_fixture_model_name(fixture_name) end end @@ -754,8 +750,9 @@ module ActiveRecord def fixtures(*fixture_names) if fixture_names.first == :all - fixture_names = Dir["#{fixture_path}/**/*.{yml}"] - fixture_names.map! { |f| f[(fixture_path.size + 1)..-5] } + fixture_names = Dir["#{fixture_path}/**/*.yml"].map { |f| + File.basename f, '.yml' + } else fixture_names = fixture_names.flatten.map { |n| n.to_s } end @@ -789,6 +786,7 @@ module ActiveRecord fixture_names = Array.wrap(fixture_names || fixture_table_names) methods = Module.new do fixture_names.each do |fixture_name| + fixture_name = fixture_name.to_s accessor_name = fixture_name.tr('/', '_').to_sym define_method(accessor_name) do |*fixtures| diff --git a/activerecord/lib/active_record/fixtures/file.rb b/activerecord/lib/active_record/fixtures/file.rb index 6bad36abb9..6547791144 100644 --- a/activerecord/lib/active_record/fixtures/file.rb +++ b/activerecord/lib/active_record/fixtures/file.rb @@ -1,8 +1,3 @@ -begin - require 'psych' -rescue LoadError -end - require 'erb' require 'yaml' diff --git a/activerecord/lib/active_record/migration/command_recorder.rb b/activerecord/lib/active_record/migration/command_recorder.rb index ffee5a081a..4e27293cb4 100644 --- a/activerecord/lib/active_record/migration/command_recorder.rb +++ b/activerecord/lib/active_record/migration/command_recorder.rb @@ -59,7 +59,7 @@ module ActiveRecord private def invert_create_table(args) - [:drop_table, args] + [:drop_table, [args.first]] end def invert_rename_table(args) diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb index 26842d3998..2c69bfde5b 100644 --- a/activerecord/test/cases/connection_pool_test.rb +++ b/activerecord/test/cases/connection_pool_test.rb @@ -22,7 +22,7 @@ module ActiveRecord def teardown super - @pool.connections.each(&:close) + @pool.disconnect! end def test_full_pool_exception @@ -81,7 +81,7 @@ module ActiveRecord @pool.remove conn assert_not_equal(conn, @pool.connection) ensure - conn.close + conn.close if conn end def test_active_connection? diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 859bb7992b..5c67cbfcce 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -65,8 +65,9 @@ class FixturesTest < ActiveRecord::TestCase end def test_create_fixtures - ActiveRecord::Fixtures.create_fixtures(FIXTURES_ROOT, "parrots") - assert Parrot.find_by_name('Curious George'), 'George is in the database' + fixtures = ActiveRecord::Fixtures.create_fixtures(FIXTURES_ROOT, "parrots") + assert Parrot.find_by_name('Curious George'), 'George is not in the database' + assert fixtures.detect { |f| f.name == 'parrots' }, "no fixtures named 'parrots' in #{fixtures.map(&:name).inspect}" end def test_multiple_clean_fixtures @@ -76,6 +77,13 @@ class FixturesTest < ActiveRecord::TestCase fixtures_array.each { |fixtures| assert_kind_of(ActiveRecord::Fixtures, fixtures) } end + def test_create_symbol_fixtures + fixtures = ActiveRecord::Fixtures.create_fixtures(FIXTURES_ROOT, :collections, :collections => Course) { Course.connection } + + assert Course.find_by_name('Collection'), 'course is not in the database' + assert fixtures.detect { |f| f.name == 'collections' }, "no fixtures named 'collections' in #{fixtures.map(&:name).inspect}" + end + def test_attributes topics = create_fixtures("topics").first assert_equal("The First Topic", topics["first"]["title"]) @@ -589,7 +597,7 @@ class FasterFixturesTest < ActiveRecord::TestCase load_extra_fixture('posts') assert ActiveRecord::Fixtures.fixture_is_cached?(ActiveRecord::Base.connection, 'posts') - self.class.setup_fixture_accessors('posts') + self.class.setup_fixture_accessors :posts assert_equal 'Welcome to the weblog', posts(:welcome).title end end diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index f7ee83998d..65cd9f9755 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -6,6 +6,9 @@ require 'models/reader' require 'models/legacy_thing' require 'models/reference' require 'models/string_key_object' +require 'models/car' +require 'models/engine' +require 'models/wheel' class LockWithoutDefault < ActiveRecord::Base; end @@ -224,6 +227,15 @@ class OptimisticLockingTest < ActiveRecord::TestCase assert_equal lock_version, p1.lock_version end end + + def test_polymorphic_destroy_with_dependencies_and_lock_version + car = Car.create! + car.wheels << Wheel.create! + assert_equal 1, car.wheels.count + assert car.destroy + assert_equal 0, car.wheels.count + assert car.destroyed? + end end class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb index d108b456f0..8f136bce2b 100644 --- a/activerecord/test/cases/migration/command_recorder_test.rb +++ b/activerecord/test/cases/migration/command_recorder_test.rb @@ -67,6 +67,12 @@ module ActiveRecord assert_equal [:drop_table, [:system_settings]], drop_table end + def test_invert_create_table_with_options + @recorder.record :create_table, [:people_reminders, {:id => false}] + drop_table = @recorder.inverse.first + assert_equal [:drop_table, [:people_reminders]], drop_table + end + def test_invert_rename_table @recorder.record :rename_table, [:old, :new] rename = @recorder.inverse.first diff --git a/activerecord/test/cases/yaml_serialization_test.rb b/activerecord/test/cases/yaml_serialization_test.rb index 2b4ec81199..302913e095 100644 --- a/activerecord/test/cases/yaml_serialization_test.rb +++ b/activerecord/test/cases/yaml_serialization_test.rb @@ -1,4 +1,4 @@ -require "cases/helper" +require 'cases/helper' require 'models/topic' class YamlSerializationTest < ActiveRecord::TestCase @@ -36,22 +36,17 @@ class YamlSerializationTest < ActiveRecord::TestCase assert_equal({'attributes' => topic.attributes}, coder) end - begin - require 'psych' - - def test_psych_roundtrip - topic = Topic.first - assert topic - t = Psych.load Psych.dump topic - assert_equal topic, t - end - - def test_psych_roundtrip_new_object - topic = Topic.new - assert topic - t = Psych.load Psych.dump topic - assert_equal topic.attributes, t.attributes - end - rescue LoadError + def test_psych_roundtrip + topic = Topic.first + assert topic + t = Psych.load Psych.dump topic + assert_equal topic, t + end + + def test_psych_roundtrip_new_object + topic = Topic.new + assert topic + t = Psych.load Psych.dump topic + assert_equal topic.attributes, t.attributes end end diff --git a/activerecord/test/models/car.rb b/activerecord/test/models/car.rb index b9c2e8ec9a..6ff1329d8e 100644 --- a/activerecord/test/models/car.rb +++ b/activerecord/test/models/car.rb @@ -9,7 +9,7 @@ class Car < ActiveRecord::Base has_many :tyres has_many :engines, :dependent => :destroy - has_many :wheels, :as => :wheelable + has_many :wheels, :as => :wheelable, :dependent => :destroy scope :incl_tyres, includes(:tyres) scope :incl_engines, includes(:engines) diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index b8f34bb739..11378c12e5 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -107,6 +107,7 @@ ActiveRecord::Schema.define do t.string :name t.integer :engines_count t.integer :wheels_count + t.column :lock_version, :integer, :null => false, :default => 0 end create_table :categories, :force => true do |t| diff --git a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb index 391bdc925d..3ec7e576c8 100644 --- a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb +++ b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb @@ -1,29 +1,9 @@ require 'bigdecimal' - -begin - require 'psych' -rescue LoadError -end - require 'yaml' class BigDecimal - YAML_TAG = 'tag:yaml.org,2002:float' YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' } - # This emits the number without any scientific notation. - # This is better than self.to_f.to_s since it doesn't lose precision. - # - # Note that reconstituting YAML floats to native floats may lose precision. - def to_yaml(opts = {}) - return super if defined?(YAML::ENGINE) && !YAML::ENGINE.syck? - - YAML.quick_emit(nil, opts) do |out| - string = to_s - out.scalar(YAML_TAG, YAML_MAPPING[string] || string, :plain) - end - end - def encode_with(coder) string = to_s coder.represent_scalar(nil, YAML_MAPPING[string] || string) diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb index 45bec264ff..305ed4964b 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute.rb @@ -110,6 +110,6 @@ class Class private def singleton_class? - !name || '' == name + ancestors.first != self end end diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 6cb2ea68b3..73aa7dd89a 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -136,11 +136,6 @@ module ActiveSupport #:nodoc: coder.represent_scalar nil, to_str end - def to_yaml(*args) - return super() if defined?(YAML::ENGINE) && !YAML::ENGINE.syck? - to_str.to_yaml(*args) - end - UNSAFE_STRING_METHODS.each do |unsafe_method| if 'String'.respond_to?(unsafe_method) class_eval <<-EOT, __FILE__, __LINE__ + 1 diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb index f9505a247c..80dcaf5613 100644 --- a/activesupport/lib/active_support/deprecation/behaviors.rb +++ b/activesupport/lib/active_support/deprecation/behaviors.rb @@ -34,8 +34,8 @@ module ActiveSupport if defined?(Rails) && Rails.logger Rails.logger else - require 'logger' - Logger.new($stderr) + require 'active_support/logger' + ActiveSupport::Logger.new($stderr) end logger.warn message logger.debug callstack.join("\n ") if debug diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index d4f309fbd7..8edd3960c7 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -1,8 +1,3 @@ -begin - require 'psych' -rescue LoadError -end - require 'yaml' YAML.add_builtin_type("omap") do |type, val| @@ -29,20 +24,6 @@ module ActiveSupport coder.represent_seq '!omap', map { |k,v| { k => v } } end - def to_yaml(opts = {}) - if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? - return super - end - - YAML.quick_emit(self, opts) do |out| - out.seq(taguri) do |seq| - each do |k, v| - seq.add(k => v) - end - end - end - end - def nested_under_indifferent_access self end diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index d3adf671a0..1cb71012ef 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -1,4 +1,4 @@ -require "active_support/values/time_zone" +require 'active_support/values/time_zone' require 'active_support/core_ext/object/acts_like' require 'active_support/core_ext/object/inclusion' @@ -146,12 +146,6 @@ module ActiveSupport end end - def to_yaml(options = {}) - return super if defined?(YAML::ENGINE) && !YAML::ENGINE.syck? - - utc.to_yaml(options) - end - def httpdate utc.httpdate end diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index 8119b36491..78de7fb6ab 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -291,21 +291,16 @@ class OrderedHashTest < Test::Unit::TestCase assert_equal @ordered_hash.values, @deserialized_ordered_hash.values end - begin - require 'psych' + def test_psych_serialize + @deserialized_ordered_hash = Psych.load(Psych.dump(@ordered_hash)) - def test_psych_serialize - @deserialized_ordered_hash = Psych.load(Psych.dump(@ordered_hash)) - - values = @deserialized_ordered_hash.map { |_, value| value } - assert_equal @values, values - end + values = @deserialized_ordered_hash.map { |_, value| value } + assert_equal @values, values + end - def test_psych_serialize_tag - yaml = Psych.dump(@ordered_hash) - assert_match '!omap', yaml - end - rescue LoadError + def test_psych_serialize_tag + yaml = Psych.dump(@ordered_hash) + assert_match '!omap', yaml end def test_has_yaml_tag diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index 8f77999d25..2fde07995b 100644 --- a/activesupport/test/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -1,9 +1,4 @@ require 'abstract_unit' -begin - require 'psych' -rescue LoadError -end - require 'active_support/core_ext/string/inflections' require 'yaml' @@ -96,13 +91,20 @@ class SafeBufferTest < ActiveSupport::TestCase assert !@buffer.dup.html_safe? end + test "Should return safe buffer when added with another safe buffer" do + clean = "<script>".html_safe + result_buffer = @buffer + clean + assert result_buffer.html_safe? + assert_equal "<script>", result_buffer + end + test "Should raise an error when safe_concat is called on dirty buffers" do @buffer.gsub!('', '<>') assert_raise ActiveSupport::SafeBuffer::SafeConcatError do @buffer.safe_concat "BUSTED" end end - + test "should not fail if the returned object is not a string" do assert_kind_of NilClass, @buffer.slice("chipchop") end diff --git a/railties/guides/source/3_2_release_notes.textile b/railties/guides/source/3_2_release_notes.textile index 2965dc6fae..927abc7944 100644 --- a/railties/guides/source/3_2_release_notes.textile +++ b/railties/guides/source/3_2_release_notes.textile @@ -67,7 +67,6 @@ When running a multi-user, multi-account application, it's a great help to be ab h3. Railties -* Rails::Plugin is deprecated and will be removed in Rails 4.0. Instead of adding plugins to vendor/plugins use gems or bundler with path or git dependencies. * Speed up development by only reloading classes if dependencies files changed. This can be turned off by setting <tt>config.reload_classes_only_on_change</tt> to false. @@ -107,6 +106,10 @@ will create indexes for +title+ and +author+ with the latter being an unique ind * Remove old <tt>config.paths.app.controller</tt> API in favor of <tt>config.paths["app/controller"]</tt>. +h4. Deprecations + +* +Rails::Plugin+ is deprecated and will be removed in Rails 4.0. Instead of adding plugins to +vendor/plugins+ use gems or bundler with path or git dependencies. + h3. Action Pack h4. Action Controller @@ -227,6 +230,8 @@ content_tag_for(:li, @items) do |item| end </ruby> +* Added +font_path+ helper method that computes the path to a font asset in <tt>public/fonts</tt>. + h5. Deprecations * Passing formats or handlers to render :template and friends like <tt>render :template => "foo.html.erb"</tt> is deprecated. Instead, you can provide :handlers and :formats directly as an options: <tt> render :template => "foo", :formats => [:html, :js], :handlers => :erb</tt>. @@ -416,6 +421,8 @@ Event.where(:created_at => Time.now.all_day) h4. Deprecations +* +ActiveSupport::Base64+ is deprecated in favor of <tt>::Base64</tt>. + * Deprecated <tt>ActiveSupport::Memoizable</tt> in favor of Ruby memoization pattern. * <tt>Module#synchronize</tt> is deprecated with no replacement. Please use monitor from ruby's standard library. diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 05cb8888a0..da7d46ef71 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -6,7 +6,7 @@ By referring to this guide you will be able to: * Understand what the asset pipeline is and what it does * Properly organize your application assets * Understand the benefits of the asset pipeline -* Adding a pre-processor to the pipeline +* Add a pre-processor to the pipeline * Package assets with a gem endprologue. @@ -17,7 +17,7 @@ The asset pipeline provides a framework to concatenate and minify or compress Ja Prior to Rails 3.1 these features were added through third-party Ruby libraries such as Jammit and Sprockets. Rails 3.1 is integrated with Sprockets through Action Pack which depends on the +sprockets+ gem, by default. -By having this as a core feature of Rails, all developers can benefit from the power of having their assets pre-processed, compressed and minified by one central library, Sprockets. This is part of Rails' "fast by default" strategy as outlined by DHH in his keynote at RailsConf 2011. +Making the asset pipeline a core feature of Rails means that all developers can benefit from the power of having their assets pre-processed, compressed and minified by one central library, Sprockets. This is part of Rails' "fast by default" strategy as outlined by DHH in his keynote at RailsConf 2011. In Rails 3.1, the asset pipeline is enabled by default. It can be disabled in +config/application.rb+ by putting this line inside the application class definition: @@ -25,34 +25,34 @@ In Rails 3.1, the asset pipeline is enabled by default. It can be disabled in +c config.assets.enabled = false </ruby> -You can also disable it while creating a new application by passing the <tt>--skip-sprockets</tt> option. +You can also disable the asset pipeline while creating a new application by passing the <tt>--skip-sprockets</tt> option. <plain> rails new appname --skip-sprockets </plain> -It is recommended that you use the defaults for all new apps. +You should use the defaults for all new applications unless you have a specific reason to avoid the asset pipeline. h4. Main Features -The first feature of the pipeline is to concatenate assets. This is important in a production environment, as it reduces the number of requests that a browser must make to render a web page. +The first feature of the pipeline is to concatenate assets. This is important in a production environment, because it can reduce the number of requests that a browser must make to render a web page. Web browsers are limited in the number of requests that they can make in parallel, so fewer requests can mean faster loading for your application. -While Rails already has a feature to concatenate these types of assets by placing +:cache => true+ at the end of tags such as +javascript_include_tag+ and +stylesheet_link_tag+, it has a series of limitations. For example, it cannot generate the caches in advance, and it is not able to transparently include assets provided by third-party libraries. +Rails 2.x introduced the ability to concatenate JavaScript and CSS assets by placing +:cache => true+ at the end of the +javascript_include_tag+ and +stylesheet_link_tag+ methods. But this technique has some limitations. For example, it cannot generate the caches in advance, and it is not able to transparently include assets provided by third-party libraries. -The default behavior in Rails 3.1 and onward is to concatenate all files into one master file each for JS and CSS. However, you can separate files or groups of files if required (see below). In production, an MD5 fingerprint is inserted into each filename so that the file is cached by the web browser but can be invalidated if the fingerprint is altered. +Starting with version 3.1, Rails defaults to concatenating all JavaScript files into one master +.js+ file and all CSS files into one master +.css+ file. As you'll learn later in this guide, you can customize this strategy to group files any way you like. In production, Rails inserts an MD5 fingerprint into each filename so that the file is cached by the web browser. You can invalidate the cache by altering this fingerprint, which happens automatically whenever you change the file contents.. -The second feature is to minify or compress assets. For CSS, this usually involves removing whitespace and comments. For JavaScript, more complex processes can be applied. You can choose from a set of built in options or specify your own. +The second feature of the asset pipeline is asset minification or compression. For CSS files, this is done by removing whitespace and comments. For JavaScript, more complex processes can be applied. You can choose from a set of built in options or specify your own. -The third feature is the ability to code these assets using another language, or language extension. These include Sass for CSS, CoffeeScript for JavaScript, and ERB for both. +The third feature of the asset pipeline is that it allows coding assets via a higher-level language, with precompilation down to the actual assets. Supported languages include Sass for CSS, CoffeeScript for JavaScript, and ERB for both by default. h4. What is Fingerprinting and Why Should I Care? -Fingerprinting is a technique whereby the filenames of content that is static or infrequently updated are altered to be unique to the content contained in the file. +Fingerprinting is a technique that makes the name of a file dependent on the contents of the file. When the file contents change, the filename is also changed. For content that is static or infrequently changed, this provides an easy way to tell whether two versions of a file are identical, even across different servers or deployment dates. -When a filename is unique and based on its content, HTTP headers can be set to encourage caches everywhere (at ISPs, in browsers) to keep their own copy of the content. When the content is updated, the fingerprint will change and the remote clients will request the new file. This is generally known as _cache busting_. +When a filename is unique and based on its content, HTTP headers can be set to encourage caches everywhere (whether at CDNs, at ISPs, in networking equipment, or in web browsers) to keep their own copy of the content. When the content is updated, the fingerprint will change. This will cause the remote clients to request a new copy of the content. This is generally known as _cache busting_. -The most effective technique is to insert a hash of the content into the name, usually at the end. For example a CSS file +global.css+ is hashed and the filename is updated to incorporate the digest, for example becoming: +The technique that Rails uses for fingerprinting is to insert a hash of the content into the name, usually at the end. For example a CSS file +global.css+ could be renamed with an MD5 digest of its contents: <plain> global-908e25f4bf641868d8683022a5b62f54.css @@ -60,28 +60,30 @@ global-908e25f4bf641868d8683022a5b62f54.css This is the strategy adopted by the Rails asset pipeline. -Rails' old strategy was to append a query string to every asset linked with a built-in helper. In the source the generated code looked like this: +Rails' old strategy was to append a date-based query string to every asset linked with a built-in helper. In the source the generated code looked like this: <plain> /stylesheets/global.css?1309495796 </plain> -This has several disadvantages: +The query string strategy has several disadvantages: <ol> <li> - <strong>Not all caches will cache content with a query string</strong>.<br> + <strong>Not all caches will reliably cache content where the filename only differs by query parameters</strong>.<br> "Steve Souders recommends":http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/, "...avoiding a querystring for cacheable resources". He found that in this case 5-20% of requests will not be cached. Query strings in particular do not work at all with some CDNs for cache invalidation. </li> <li> <strong>The file name can change between nodes in multi-server environments.</strong><br> - The query string in Rails is based on the modification time of the files. When assets are deployed to a cluster, there is no guarantee that the timestamps will be the same, resulting in different values being used depending on which server handles the request. + The default query string in Rails 2.x is based on the modification time of the files. When assets are deployed to a cluster, there is no guarantee that the timestamps will be the same, resulting in different values being used depending on which server handles the request. + </li> + <li> + <strong>Too much cache invalidation</strong><br /> + When static assets are deployed with each new release of code, the mtime of _all_ these files changes, forcing all remote clients to fetch them again, even when the content of those assets has not changed. </li> </ol> -The other problem is that when static assets are deployed with each new release of code, the mtime of _all_ these files changes, forcing all remote clients to fetch them again, even when the content of those assets has not changed. - -Fingerprinting fixes these problems by avoiding query strings, and by ensuring filenames are consistent based on their content. +Fingerprinting fixes these problems by avoiding query strings, and by ensuring that filenames are consistent based on their content. Fingerprinting is enabled by default for production and disabled for all other environments. You can enable or disable it in your configuration through the +config.assets.digest+ option. @@ -95,19 +97,19 @@ h3. How to Use the Asset Pipeline In previous versions of Rails, all assets were located in subdirectories of +public+ such as +images+, +javascripts+ and +stylesheets+. With the asset pipeline, the preferred location for these assets is now the +app/assets+ directory. Files in this directory are served by the Sprockets middleware included in the sprockets gem. -This is not to say that assets can (or should) no longer be placed in +public+; they still can be and will be served as static files by the application or web server. You would only use +app/assets+ if you wish your files to undergo some pre-processing before they are served. +Assets can still be placed in the +public+ hierarchy. Any assets under +public+ will be served as static files by the application or web server. You should use +app/assets+ for files that must undergo some pre-processing before they are served. -In production, the default is to precompile these files to +public/assets+ so that they can be more efficiently delivered by the web server. +In production, Rails precompiles these files to +public/assets+ by default. The precompiled copies are then served as static assets by the web server. The files in +app/assets+ are never served directly in production. -When a scaffold or controller is generated for the application, Rails also generates a JavaScript file (or CoffeeScript file if the +coffee-rails+ gem is in the +Gemfile+) and a Cascading Style Sheet file (or SCSS file if +sass-rails+ is in the +Gemfile+) for that controller. +When you generate a scaffold or a controller, Rails also generates a JavaScript file (or CoffeeScript file if the +coffee-rails+ gem is in the +Gemfile+) and a Cascading Style Sheet file (or SCSS file if +sass-rails+ is in the +Gemfile+) for that controller. -For example, if a +ProjectsController+ is generated, there will be a new file at +app/assets/javascripts/projects.js.coffee+ and another at +app/assets/stylesheets/projects.css.scss+. You should put any JavaScript or CSS unique to a controller inside their respective asset files, as these files can then be loaded just for these controllers with lines such as +<%= javascript_include_tag params[:controller] %>+ or +<%= stylesheet_link_tag params[:controller] %>+. +For example, if you generate a +ProjectsController+, Rails will also add a new file at +app/assets/javascripts/projects.js.coffee+ and another at +app/assets/stylesheets/projects.css.scss+. You should put any JavaScript or CSS unique to a controller inside their respective asset files, as these files can then be loaded just for these controllers with lines such as +<%= javascript_include_tag params[:controller] %>+ or +<%= stylesheet_link_tag params[:controller] %>+. -NOTE: You will need an "ExecJS":https://github.com/sstephenson/execjs#readme supported runtime in order to use CoffeeScript. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. +NOTE: You must have an "ExecJS":https://github.com/sstephenson/execjs#readme supported runtime in order to use CoffeeScript. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. h4. Asset Organization -Assets can be placed inside an application in one of three locations: +app/assets+, +lib/assets+ or +vendor/assets+. +Assets that must be precompiled can be placed inside an application in one of three locations: +app/assets+, +lib/assets+ or +vendor/assets+. +app/assets+ is for assets that are owned by the application, such as custom images, JavaScript files or stylesheets. @@ -115,7 +117,7 @@ Assets can be placed inside an application in one of three locations: +app/asset +vendor/assets+ is for assets that are owned by outside entities, such as code for JavaScript plugins. -All subdirectories that exist within these three locations are added to the search path for Sprockets (visible by calling +Rails.application.config.assets.paths+ in a console). When an asset is requested, these paths are traversed to see if they contain an asset matching the name specified. Once an asset has been found, it's processed by Sprockets and served. +All subdirectories that exist within these three locations are added to the search path for Sprockets. You can see this search path by inspecting +Rails.application.config.assets.paths+ in the Rails console. When a client requests an asset, these paths are traversed (in the order that they occur in the search path) to see if they contain an asset matching the name specified. If an asset is found, it's processed by Sprockets and served. You can add additional (fully qualified) paths to the pipeline in +config/application.rb+. For example: @@ -138,7 +140,7 @@ In regular views you can access images in the +assets/images+ directory like thi <%= image_tag "rails.png" %> </erb> -Provided that the pipeline is enabled within your application (and not disabled in the current environment context), this file is served by Sprockets. If a file exists at +public/assets/rails.png+ it is served by the webserver. +Provided that the pipeline is enabled within your application (and not disabled in the current environment context), this file is served by Sprockets. If a file exists at +public/assets/rails.png+ it is served by the web server. Alternatively, a request for a file with an MD5 hash such as +public/assets/rails-af27b6a414e6da00003503148be9b409.png+ is treated the same way. How these hashes are generated is covered in the "In Production":#in-production section later on in this guide. @@ -152,7 +154,7 @@ Images can also be organized into subdirectories if required, and they can be ac h5. CSS and ERB -If you add an +erb+ extension to a CSS asset, making it something such as +application.css.erb+, then helpers like +asset_path+ are available in your CSS rules: +The asset pipeline automatically evaluates ERB. This means that if you add an +erb+ extension to a CSS asset (for example, +application.css.erb+), then helpers like +asset_path+ are available in your CSS rules: <plain> .class { background-image: url(<%= asset_path 'image.png' %>) } @@ -202,9 +204,9 @@ $('#logo').attr src: "<%= asset_path('logo.png') %>" h4. Manifest Files and Directives -Sprockets uses manifest files to determine which assets to include and serve. These manifest files contain _directives_ -- instructions that tell Sprockets which files to require in order to build a single CSS or JavaScript file. With these directives, Sprockets loads the files specified, processes them if necessary, concatenates them into one single file and then compresses them (if +Rails.application.config.assets.compress+ is true). By serving one file rather than many, the load time of pages are greatly reduced as there are fewer requests to make. +Sprockets uses manifest files to determine which assets to include and serve. These manifest files contain _directives_ -- instructions that tell Sprockets which files to require in order to build a single CSS or JavaScript file. With these directives, Sprockets loads the files specified, processes them if necessary, concatenates them into one single file and then compresses them (if +Rails.application.config.assets.compress+ is true). By serving one file rather than many, the load time of pages can be greatly reduced because the browser makes fewer requests. -For example, in the default Rails application there's a +app/assets/javascripts/application.js+ file which contains the following lines: +For example, a new Rails application includes a default +app/assets/javascripts/application.js+ file which contains the following lines: <plain> // ... @@ -217,11 +219,11 @@ In JavaScript files, the directives begin with +//=+. In this case, the file is NOTE. In Rails 3.1 the +jquery-rails+ gem provides the +jquery.js+ and +jquery_ujs.js+ files via the asset pipeline. You won't see them in the application tree. -The +require_tree+ directive tells Sprockets to recursively include _all_ JavaScript files in this directory into the output. Only a path relative to the manifest file can be specified. There is also a +require_directory+ directive which includes all JavaScript files only in the directory specified (no nesting). +The +require_tree+ directive tells Sprockets to recursively include _all_ JavaScript files in the specified directory into the output. These paths must be specified relative to the manifest file. You can also use the +require_directory+ directive which includes all JavaScript files only in the directory specified, without recursion. -Directives are processed top to bottom, but the order in which files are included by +require_tree+ is unspecified. You should not rely on any particular order among those. If you need to ensure some particular JavaScript ends up above some other, require it before in the manifest. Note that the family of +require+ directives prevents files from being included twice in the output. +Directives are processed top to bottom, but the order in which files are included by +require_tree+ is unspecified. You should not rely on any particular order among those. If you need to ensure some particular JavaScript ends up above some other in the concatenated file, require the prerequisite file first in the manifest. Note that the family of +require+ directives prevents files from being included twice in the output. -There's also a default +app/assets/stylesheets/application.css+ file which contains these lines: +Rails also creates a default +app/assets/stylesheets/application.css+ file which contains these lines: <plain> /* ... @@ -230,15 +232,15 @@ There's also a default +app/assets/stylesheets/application.css+ file which conta */ </plain> -The directives that work in the JavaScript files also work in stylesheets, obviously including stylesheets rather than JavaScript files. The +require_tree+ directive here works the same way as the JavaScript one, requiring all stylesheets from the current directory. +The directives that work in the JavaScript files also work in stylesheets (though obviously including stylesheets rather than JavaScript files). The +require_tree+ directive in a CSS manifest works the same way as the JavaScript one, requiring all stylesheets from the current directory. In this example +require_self+ is used. This puts the CSS contained within the file (if any) at the precise location of the +require_self+ call. If +require_self+ is called more than once, only the last call is respected. -NOTE. If you want to use multiple Sass files, use the "Sass +@import+ rule":http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import instead of the Sprockets directives. Using Sprockets directives all Sass files exist within their own scope, making variables or mixins only available within the document they were defined in. +NOTE. If you want to use multiple Sass files, you should generally use the "Sass +@import+ rule":http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import instead of these Sprockets directives. Using Sprockets directives all Sass files exist within their own scope, making variables or mixins only available within the document they were defined in. You can have as many manifest files as you need. For example the +admin.css+ and +admin.js+ manifest could contain the JS and CSS files that are used for the admin section of an application. -The same remarks about ordering made above apply. In particular, you can specify individual files and they are compiled in the order specified: +The same remarks about ordering made above apply. In particular, you can specify individual files and they are compiled in the order specified. For example, you might concatenate three CSS files together this way: <plain> /* ... @@ -312,7 +314,7 @@ You could potentially also enable compression in development mode as a sanity ch h3. In Production -In the production environment Rails uses the fingerprinting scheme outlined above. By default it is assumed that assets have been precompiled and will be served as static assets by your web server. +In the production environment Rails uses the fingerprinting scheme outlined above. By default Rails assumes that assets have been precompiled and will be served as static assets by your web server. During the precompilation phase an MD5 is generated from the contents of the compiled files, and inserted into the filenames as they are written to disc. These fingerprinted names are used by the Rails helpers in place of the manifest name. @@ -330,7 +332,7 @@ generates something like this: <link href="/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css" media="screen" rel="stylesheet" type="text/css" /> </html> -The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which is +true+ for production, +false+ for everything else). +The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which defaults to +true+ for production and +false+ for everything else). NOTE: Under normal circumstances the default option should not be changed. If there are no digests in the filenames, and far-future headers are set, remote clients will never know to refetch the files when their content changes. @@ -338,9 +340,9 @@ h4. Precompiling Assets Rails comes bundled with a rake task to compile the asset manifests and other files in the pipeline to the disk. -Compiled assets are written to the location specified in +config.assets.prefix+. The default setting will use the +public/assets+ directory. +Compiled assets are written to the location specified in +config.assets.prefix+. By default, this is the +public/assets+ directory. -You must use this task either during deployment or locally if you do not have write access to your production filesystem. +You can call this task on the server during deployment to create compiled versions of your assets directly on the server. If you do not have write access to your production file system, you can call this task locally and then deploy the compiled assets. The rake task is: @@ -357,7 +359,7 @@ test +rake assets:precompile+ locally before deploying. It may expose bugs where your assets reference application objects or methods, since those are still in scope in development mode regardless of the value of this flag. -Capistrano (v2.8.0 and above) has a recipe to handle this in deployment. Add the following line to +Capfile+: +Capistrano (v2.8.0 and above) includes a recipe to handle this in deployment. Add the following line to +Capfile+: <erb> load 'deploy/assets' @@ -381,7 +383,7 @@ If you have other manifests or individual stylesheets and JavaScript files to in config.assets.precompile += ['admin.js', 'admin.css', 'swfObject.js'] </erb> -The rake task also generates a +manifest.yml+ that contains a list with all your assets and their respective fingerprints. This is used by the Rails helper methods and avoids handing the mapping requests back to Sprockets. A typical manifest file looks like: +The rake task also generates a +manifest.yml+ that contains a list with all your assets and their respective fingerprints. This is used by the Rails helper methods to avoid handing the mapping requests back to Sprockets. A typical manifest file looks like: <plain> --- @@ -404,7 +406,7 @@ NOTE: If there are missing precompiled files in production you will get an <tt>S h5. Server Configuration -Precompiled assets exist on the filesystem and are served directly by your webserver. They do not have far-future headers by default, so to get the benefit of fingerprinting you'll have to update your server configuration to add them. +Precompiled assets exist on the filesystem and are served directly by your web server. They do not have far-future headers by default, so to get the benefit of fingerprinting you'll have to update your server configuration to add them. For Apache: @@ -451,7 +453,7 @@ This directive is available if the core module that provides this feature was co If you're compiling nginx with Phusion Passenger you'll need to pass that option when prompted. -Unfortunately, a robust configuration for Apache is possible but tricky; please Google around. +A robust configuration for Apache is possible but tricky; please Google around. (Or help update this Guide if you have a good example configuration for Apache.) h4. Live Compilation @@ -467,9 +469,9 @@ On the first request the assets are compiled and cached as outlined in developme Sprockets also sets the +Cache-Control+ HTTP header to +max-age=31536000+. This signals all caches between your server and the client browser that this content (the file served) can be cached for 1 year. The effect of this is to reduce the number of requests for this asset from your server; the asset has a good chance of being in the local browser cache or some intermediate cache. -This mode uses more memory, performs poorer than the default and is not recommended. +This mode uses more memory, performs more poorly than the default and is not recommended. -When deploying a production application to a system without any pre-existing JavaScript runtimes, you may want to add one to your Gemfile: +If you are deploying a production application to a system without any pre-existing JavaScript runtimes, you may want to add one to your Gemfile: <plain> group :production do @@ -495,7 +497,7 @@ h4. JavaScript Compression Possible options for JavaScript compression are +:closure+, +:uglifier+ and +:yui+. These require the use of the +closure-compiler+, +uglifier+ or +yui-compressor+ gems, respectively. -The default Gemfile includes "uglifier":https://github.com/lautis/uglifier. This gem wraps "UglifierJS":https://github.com/mishoo/UglifyJS (written for NodeJS) in Ruby. It compresses your code by removing white space and other magical things like changing your +if+ and +else+ statements to ternary operators where possible. +The default Gemfile includes "uglifier":https://github.com/lautis/uglifier. This gem wraps "UglifierJS":https://github.com/mishoo/UglifyJS (written for NodeJS) in Ruby. It compresses your code by removing white space. It also includes other optimizations such as changing your +if+ and +else+ statements to ternary operators where possible. The following line invokes +uglifier+ for JavaScript compression. @@ -503,13 +505,13 @@ The following line invokes +uglifier+ for JavaScript compression. config.assets.js_compressor = :uglifier </erb> -The +config.assets.compress+ must be set to +true+ to enable JavaScript compression +Note that +config.assets.compress+ must be set to +true+ to enable JavaScript compression -NOTE: You will need an "ExecJS":https://github.com/sstephenson/execjs#readme supported runtime in order to use +uglifier+. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes. +NOTE: You will need an "ExecJS":https://github.com/sstephenson/execjs#readme supported runtime in order to use +uglifier+. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check the "ExecJS":https://github.com/sstephenson/execjs#readme documentation for information on all of the supported JavaScript runtimes. h4. Using Your Own Compressor -The compressor config settings for CSS and JavaScript also take any Object. This object must have a +compress+ method that takes a string as the sole argument and it must return a string. +The compressor config settings for CSS and JavaScript also take any object. This object must have a +compress+ method that takes a string as the sole argument and it must return a string. <erb> class Transformer @@ -519,7 +521,7 @@ class Transformer end </erb> -To enable this, pass a +new+ Object to the config option in +application.rb+: +To enable this, pass a +new+ object to the config option in +application.rb+: <erb> config.assets.css_compressor = Transformer.new @@ -536,13 +538,13 @@ This can be changed to something else: config.assets.prefix = "/some_other_path" </erb> -This is a handy option if you have any existing project (pre Rails 3.1) that already uses this path or you wish to use this path for a new resource. +This is a handy option if you are updating an existing project (pre Rails 3.1) that already uses this path or you wish to use this path for a new resource. h4. X-Sendfile Headers The X-Sendfile header is a directive to the web server to ignore the response from the application, and instead serve a specified file from disk. This option is off by default, but can be enabled if your server supports it. When enabled, this passes responsibility for serving the file to the web server, which is faster. -Apache and nginx support this option which is enabled in <tt>config/environments/production.rb</tt>. +Apache and nginx support this option, which can be enabled in <tt>config/environments/production.rb</tt>. <erb> # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache @@ -619,7 +621,7 @@ config.assets.digest = true # config.assets.precompile += %w( search.js ) </erb> -There are no changes to +test.rb+. The defaults in the test environment are: +config.assets.compile+ is true and +config.assets.compress+, +config.assets.debug+ and +config.assets.digest+ are false. +You should not need to change +test.rb+. The defaults in the test environment are: +config.assets.compile+ is true and +config.assets.compress+, +config.assets.debug+ and +config.assets.digest+ are false. The following should also be added to +Gemfile+: @@ -633,7 +635,7 @@ group :assets do end </plain> -If you use the +assets+ group with Bundler, please make sure that your +config/application.rb+ has the following Bundler require statement. +If you use the +assets+ group with Bundler, please make sure that your +config/application.rb+ has the following Bundler require statement: <ruby> if defined?(Bundler) @@ -644,7 +646,7 @@ if defined?(Bundler) end </ruby> -Instead of the old Rails 3.0 one +Instead of the old Rails 3.0 version: <ruby> # If you have a Gemfile, require the gems listed there, including any gems diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb index 78d2e6c913..f96a7d1772 100644 --- a/railties/lib/rails/application/bootstrap.rb +++ b/railties/lib/rails/application/bootstrap.rb @@ -28,7 +28,7 @@ module Rails FileUtils.mkdir_p File.dirname path end - f = File.open path, 'w' + f = File.open path, 'a' f.binmode f.sync = !Rails.env.production? # make sure every write flushes diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb index d425c9db6c..6fc127efae 100644 --- a/railties/lib/rails/commands/dbconsole.rb +++ b/railties/lib/rails/commands/dbconsole.rb @@ -1,10 +1,4 @@ require 'erb' - -begin - require 'psych' -rescue LoadError -end - require 'yaml' require 'optparse' require 'rbconfig' |