diff options
Diffstat (limited to 'railties')
10 files changed, 80 insertions, 33 deletions
diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 8937a0c172..082f9eda7d 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -256,7 +256,7 @@ The above will yield the supplied block with +1000+ invoices every time. h3. Conditions -The +find+ method allows you to specify conditions to limit the records returned, representing the +WHERE+-part of the SQL statement. Conditions can either be specified as a string, array, or hash. +The +where+ method allows you to specify conditions to limit the records returned, representing the +WHERE+-part of the SQL statement. Conditions can either be specified as a string, array, or hash. h4. Pure String Conditions diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index d2441727ee..563c1c79ae 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -32,7 +32,7 @@ h4. Main Features The first is to concatenate of assets. This is important in a production environment to reduce the number of requests that a client browser has to make to render a web page. While Rails already has a feature to concatenate these types of asset--by placing +:cache => true+ at the end of tags such as +javascript_include_tag+ and +stylesheet_link_tag+--, many people do not use it. -The default behavior in 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. +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. The second feature of the pipeline is to minify or compress. For CSS this usually involves removing whitespace and comments. For Javascript more complex processes can be applied. @@ -42,7 +42,7 @@ The third feature is the ability to code these assets using another language, or h4. What is fingerprinting and why should I care? -Fingerprinting is a technique where the filenames of content that is static or infrequently updated is altered to be unique to the content contained in the file. +Fingerprinting is a technique where the filenames of content that is static or infrequently updated is altered to be unique to the content contained in the file. 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 there 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 _cachebusting_. @@ -57,8 +57,8 @@ 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: <plain> -/stylesheets/global.css?1309495796 -</plain> +/stylesheets/global.css?1309495796 +</plain> This has several disadvantages: @@ -88,8 +88,7 @@ This is not to say that assets can (or should) no longer be placed in +public+. When a scaffold or controller is generated for the application, Rails will also generate a JavaScript file (or CoffeeScript if the +coffee-script+ gem is in the +Gemfile+) and a Cascading Style Sheet file (or SCSS if +sass-rails+ is in the +Gemfile+) file 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 can put any JavaScript or CSS unique to a controller inside their respective asset files. - +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] %>+. h4. Asset Organization @@ -184,6 +183,31 @@ In the development environment assets are compiled and cached on the first reque If any of the files in the manifest have changed between requests, the server will respond with a new compiled file. +h4. Debugging Assets + +You can put +?debug_assets=true+ or +?debug_assets=1+ at the end of a URL and Sprockets will expand the lines which load the assets. For example, if we had an +app/assets/javascripts/application.js+ file containing these lines: + +<plain> +//= require "projects" +//= require "tickets" +</plain> + +By default, this would only render this line when used with +<%= javascript_include_tag "application" %>+ in a view or layout: + +<html> + <script src='/assets/application.js'></script> +</html> + +When the +debug_assets+ parameter is set, this line will be expanded out into three separate lines, separating out the combined file into their parts. + +<html> + <script src='/assets/application.js'></script> + <script src='/assets/projects.js'></script> + <script src='/assets/tickets.js'></script> +</html> + +This allows the individual parts of an asset to be rendered and debugged separately. + h3. In Production In the production environment, assets are served slightly differently. @@ -308,3 +332,4 @@ h3. Making Your Library or Gem a Pre-Processor "You should be able to register [your gems] on Tilt and Sprockets will find them." - Josh Tilt: https://github.com/rtomayko/tilt + diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile index 6f028805d6..f5bee52b5a 100644 --- a/railties/guides/source/debugging_rails_applications.textile +++ b/railties/guides/source/debugging_rails_applications.textile @@ -127,7 +127,7 @@ When something is logged it's printed into the corresponding log if the log leve The available log levels are: +:debug+, +:info+, +:warn+, +:error+, and +:fatal+, corresponding to the log level numbers from 0 up to 4 respectively. To change the default log level, use <ruby> -config.log_level = Logger::WARN # In any environment initializer, or +config.log_level = :warn # In any environment initializer, or Rails.logger.level = 0 # at any time </ruby> @@ -480,11 +480,7 @@ class Author < ActiveRecord::Base def find_recent_comments(limit = 10) debugger - @recent_comments ||= comments.find( - :all, - :conditions => ["created_at > ?", 1.week.ago], - :limit => limit - ) + @recent_comments ||= comments.where("created_at > ?", 1.week.ago).limit(limit) end end </ruby> @@ -493,7 +489,7 @@ TIP: You can use ruby-debug while using +rails console+. Just remember to +requi <shell> $ rails console -Loading development environment (Rails 2.1.0) +Loading development environment (Rails 3.1.0) >> require "ruby-debug" => [] >> author = Author.first @@ -507,15 +503,15 @@ With the code stopped, take a look around: <shell> (rdb:1) list -[6, 15] in /PathTo/project/app/models/author.rb +[2, 9] in /PathTo/project/app/models/author.rb + 2 has_one :editorial + 3 has_many :comments + 4 + 5 def find_recent_comments(limit = 10) 6 debugger - 7 @recent_comments ||= comments.find( - 8 :all, - 9 :conditions => ["created_at > ?", 1.week.ago], - 10 :limit => limit -=> 11 ) - 12 end - 13 end +=> 7 @recent_comments ||= comments.where("created_at > ?", 1.week.ago).limit(limit) + 8 end + 9 end </shell> You are at the end of the line, but... was this line executed? You can inspect the instance variables. diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile index 4314d00f2e..9051ede9dd 100644 --- a/railties/guides/source/form_helpers.textile +++ b/railties/guides/source/form_helpers.textile @@ -589,7 +589,7 @@ def upload end </ruby> -Once a file has been uploaded, there are a multitude of potential tasks, ranging from where to store the files (on disk, Amazon S3, etc) and associating them with models to resizing image files and generating thumbnails. The intricacies of this are beyond the scope of this guide, but there are several plugins designed to assist with these. Two of the better known ones are "Attachment-Fu":https://github.com/technoweenie/attachment_fu and "Paperclip":http://www.thoughtbot.com/projects/paperclip. +Once a file has been uploaded, there are a multitude of potential tasks, ranging from where to store the files (on disk, Amazon S3, etc) and associating them with models to resizing image files and generating thumbnails. The intricacies of this are beyond the scope of this guide, but there are several libraries designed to assist with these. Two of the better known ones are "CarrierWave":https://github.com/jnicklas/carrierwave and "Paperclip":http://www.thoughtbot.com/projects/paperclip. NOTE: If the user has not selected a file the corresponding parameter will be an empty string. diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile index 412ded1d0b..908f3f125a 100644 --- a/railties/guides/source/security.textile +++ b/railties/guides/source/security.textile @@ -649,7 +649,7 @@ h5(#sql-injection-introduction). Introduction SQL injection attacks aim at influencing database queries by manipulating web application parameters. A popular goal of SQL injection attacks is to bypass authorization. Another goal is to carry out data manipulation or reading arbitrary data. Here is an example of how not to use user input data in a query: <ruby> -Project.all(:conditions => "name = '#{params[:name]}'") +Project.where("name = '#{params[:name]}'") </ruby> This could be in a search action and the user may enter a project's name that he wants to find. If a malicious user enters ' OR 1 --, the resulting SQL query will be: @@ -681,7 +681,7 @@ h5. Unauthorized Reading The UNION statement connects two SQL queries and returns the data in one set. An attacker can use it to read arbitrary data from the database. Let's take the example from above: <ruby> -Project.all(:conditions => "name = '#{params[:name]}'") +Project.where("name = '#{params[:name]}'") </ruby> And now let's inject another query using the UNION statement: @@ -703,18 +703,18 @@ Also, the second query renames some columns with the AS statement so that the we h5(#sql-injection-countermeasures). Countermeasures -Ruby on Rails has a built-in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. <em class="highlight">Using +Model.find(id)+ or +Model.find_by_some thing(something)+ automatically applies this countermeasure</em>. But in SQL fragments, especially <em class="highlight">in conditions fragments (+:conditions => "..."+), the +connection.execute()+ or +Model.find_by_sql()+ methods, it has to be applied manually</em>. +Ruby on Rails has a built-in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. <em class="highlight">Using +Model.find(id)+ or +Model.find_by_some thing(something)+ automatically applies this countermeasure</em>. But in SQL fragments, especially <em class="highlight">in conditions fragments (+where("...")+), the +connection.execute()+ or +Model.find_by_sql()+ methods, it has to be applied manually</em>. Instead of passing a string to the conditions option, you can pass an array to sanitize tainted strings like this: <ruby> -Model.first(:conditions => ["login = ? AND password = ?", entered_user_name, entered_password]) +Model.where("login = ? AND password = ?", entered_user_name, entered_password).first </ruby> As you can see, the first part of the array is an SQL fragment with question marks. The sanitized versions of the variables in the second part of the array replace the question marks. Or you can pass a hash for the same result: <ruby> -Model.first(:conditions => {:login => entered_user_name, :password => entered_password}) +Model.where(:login => entered_user_name, :password => entered_password).first </ruby> The array or hash form is only available in model instances. You can try +sanitize_sql()+ elsewhere. _(highlight)Make it a habit to think about the security consequences when using an external string in SQL_. diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index df92934457..603ede3d1e 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -4,6 +4,7 @@ require 'pathname' require 'active_support' require 'active_support/core_ext/kernel/reporting' +require 'active_support/core_ext/array/extract_options' require 'active_support/core_ext/logger' require 'rails/application' @@ -91,7 +92,7 @@ module Rails # # * The Rails environment; # * The environment variable RAILS_GROUPS; - # * The optional hash given as argument with group dependencies; + # * The optional envs given as argument and the hash with group dependencies; # # == Examples # @@ -101,12 +102,14 @@ module Rails # # => [:default, :development, :assets] for Rails.env == "development" # # => [:default, :production] for Rails.env == "production" # - def groups(hash={}) + def groups(*groups) + hash = groups.extract_options! env = Rails.env - groups = [:default, env] + groups.unshift(:default, env) groups.concat ENV["RAILS_GROUPS"].to_s.split(",") groups.concat hash.map { |k,v| k if v.map(&:to_s).include?(env) } groups.compact! + groups.uniq! groups end diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index fe29668c72..559739b2ec 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -106,6 +106,15 @@ module Rails self end + # Rails.application.env_config stores some of the Rails initial environment parameters. + # Currently stores: + # + # * action_dispatch.parameter_filter" => config.filter_parameters, + # * action_dispatch.secret_token" => config.secret_token, + # * action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions + # + # These parameters will be used by middlewares and engines to configure themselves. + # def env_config @env_config ||= super.merge({ "action_dispatch.parameter_filter" => config.filter_parameters, diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index eaa31e7386..0460009954 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -15,7 +15,7 @@ require "active_resource/railtie" # If you have a Gemfile, require the default gems, the ones in the # current environment and also include :assets gems if in development # or test environments. -Bundler.require *Rails.groups(:assets => %w(development test)) if defined?(Bundler) +Bundler.require *Rails.groups(:assets) if defined?(Bundler) module <%= app_const_base %> class Application < Rails::Application diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb index 9e8b0131f8..5d8d9be237 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb @@ -8,3 +8,8 @@ # inflect.irregular 'person', 'people' # inflect.uncountable %w( fish sheep ) # end +# +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 2547863d12..448982f9de 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -45,7 +45,7 @@ module ApplicationTests Rails.env = "development" assert_equal [:default, "development"], Rails.groups assert_equal [:default, "development", :assets], Rails.groups(:assets => [:development]) - assert_equal [:default, "development", :assets], Rails.groups(:assets => %w(development)) + assert_equal [:default, "development", :another, :assets], Rails.groups(:another, :assets => %w(development)) Rails.env = "test" assert_equal [:default, "test"], Rails.groups(:assets => [:development]) @@ -516,5 +516,14 @@ module ApplicationTests get "/", { :format => :xml }, "HTTP_ACCEPT" => "application/xml" assert_equal 'XML', last_response.body end + + test "Rails.application#env_config exists and include some existing parameters" do + make_basic_app + + assert_respond_to app, :env_config + assert_equal app.env_config['action_dispatch.parameter_filter'], app.config.filter_parameters + assert_equal app.env_config['action_dispatch.secret_token'], app.config.secret_token + assert_equal app.env_config['action_dispatch.show_exceptions'], app.config.action_dispatch.show_exceptions + end end end |