diff options
Diffstat (limited to 'actionpack/lib')
-rw-r--r-- | actionpack/lib/abstract_controller/base.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/abstract_controller/helpers.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/abstract_controller/rendering.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/upload.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/cookies.rb | 115 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/session/cookie_store.rb | 96 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing.rb | 92 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/route_set.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/form_helper.rb | 16 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/form_options_helper.rb | 4 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/javascript_helper.rb | 4 | ||||
-rw-r--r-- | actionpack/lib/action_view/template/resolver.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_view/vendor/html-scanner/html/selector.rb | 16 |
14 files changed, 161 insertions, 196 deletions
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 56dc9ab7a1..af5de815bb 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -35,7 +35,7 @@ module AbstractController end def inherited(klass) # :nodoc: - # define the abstract ivar on subclasses so that we don't get + # Define the abstract ivar on subclasses so that we don't get # uninitialized ivar warnings unless klass.instance_variable_defined?(:@abstract) klass.instance_variable_set(:@abstract, false) diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb index 812a35735f..bb701184e8 100644 --- a/actionpack/lib/abstract_controller/helpers.rb +++ b/actionpack/lib/abstract_controller/helpers.rb @@ -59,7 +59,7 @@ module AbstractController # The +helper+ class method can take a series of helper module names, a block, or both. # # ==== Options - # * <tt>*args</tt> - Module, Symbol, String, :all + # * <tt>*args</tt> - Module, Symbol, String # * <tt>block</tt> - A block defining helper methods # # When the argument is a module it will be included directly in the template class. diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 07f5c2586c..3f34add790 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -106,7 +106,7 @@ module AbstractController # If a component extends the semantics of response_body # (as Action Controller extends it to be anything that # responds to the method each), this method needs to be - # overriden in order to still return a string. + # overridden in order to still return a string. # :api: plugin def render_to_string(*args, &block) options = _normalize_render(*args, &block) diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 618e2f3033..2c88bc3b1f 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -84,8 +84,6 @@ module ActionDispatch module Session autoload :AbstractStore, 'action_dispatch/middleware/session/abstract_store' autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store' - autoload :EncryptedCookieStore, 'action_dispatch/middleware/session/cookie_store' - autoload :UpgradeSignatureToEncryptionCookieStore, 'action_dispatch/middleware/session/cookie_store' autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store' autoload :CacheStore, 'action_dispatch/middleware/session/cache_store' end diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb index 319d0197d1..b57c84dec8 100644 --- a/actionpack/lib/action_dispatch/http/upload.rb +++ b/actionpack/lib/action_dispatch/http/upload.rb @@ -6,7 +6,7 @@ module ActionDispatch # of its interface is available directly for convenience. # # Uploaded files are temporary files whose lifespan is one request. When - # the object is finalized Ruby unlinks the file, so there is not need to + # the object is finalized Ruby unlinks the file, so there is no need to # clean them with a separate maintenance task. class UploadedFile # The basename of the file in the client. diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index f21d1d4ee5..08c75632ba 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -117,6 +117,9 @@ module ActionDispatch # the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed # cookie was tampered with by the user (or a 3rd party), nil will be returned. # + # If +config.secret_key_base+ and +config.secret_token+ (deprecated) are both set, + # legacy cookies signed with the old key generator will be transparently upgraded. + # # This jar requires that you set a suitable secret for the verification on your app's +config.secret_key_base+. # # Example: @@ -126,23 +129,20 @@ module ActionDispatch # # cookies.signed[:discount] # => 45 def signed - @signed ||= begin - if @options[:upgrade_legacy_signed_cookie_jar] + @signed ||= + if @options[:upgrade_legacy_signed_cookies] UpgradeLegacySignedCookieJar.new(self, @key_generator, @options) else SignedCookieJar.new(self, @key_generator, @options) end - end - end - - # Only needed for supporting the +UpgradeSignatureToEncryptionCookieStore+, users and plugin authors should not use this - def signed_using_old_secret #:nodoc: - @signed_using_old_secret ||= SignedCookieJar.new(self, ActiveSupport::DummyKeyGenerator.new(@options[:secret_token]), @options) end # Returns a jar that'll automatically encrypt cookie values before sending them to the client and will decrypt them for read. # If the cookie was tampered with by the user (or a 3rd party), nil will be returned. # + # If +config.secret_key_base+ and +config.secret_token+ (deprecated) are both set, + # legacy cookies signed with the old key generator will be transparently upgraded. + # # This jar requires that you set a suitable secret for the verification on your app's +config.secret_key_base+. # # Example: @@ -152,7 +152,38 @@ module ActionDispatch # # cookies.encrypted[:discount] # => 45 def encrypted - @encrypted ||= EncryptedCookieJar.new(self, @key_generator, @options) + @encrypted ||= + if @options[:upgrade_legacy_signed_cookies] + UpgradeLegacyEncryptedCookieJar.new(self, @key_generator, @options) + else + EncryptedCookieJar.new(self, @key_generator, @options) + end + end + + # Returns the +signed+ or +encrypted jar, preferring +encrypted+ if +secret_key_base+ is set. + # Used by ActionDispatch::Session::CookieStore to avoid the need to introduce new cookie stores. + def signed_or_encrypted + @signed_or_encrypted ||= + if @options[:secret_key_base].present? + encrypted + else + signed + end + end + end + + module VerifyAndUpgradeLegacySignedMessage + def initialize(*args) + super + @legacy_verifier = ActiveSupport::MessageVerifier.new(@options[:secret_token]) + end + + def verify_and_upgrade_legacy_signed_message(name, signed_message) + @legacy_verifier.verify(signed_message).tap do |value| + self[name] = value + end + rescue ActiveSupport::MessageVerifier::InvalidSignature + nil end end @@ -179,7 +210,7 @@ module ActionDispatch encrypted_signed_cookie_salt: env[ENCRYPTED_SIGNED_COOKIE_SALT] || '', secret_token: env[SECRET_TOKEN], secret_key_base: env[SECRET_KEY_BASE], - upgrade_legacy_signed_cookie_jar: env[SECRET_TOKEN].present? && env[SECRET_KEY_BASE].present? + upgrade_legacy_signed_cookies: env[SECRET_TOKEN].present? && env[SECRET_KEY_BASE].present? } end @@ -354,10 +385,8 @@ module ActionDispatch def [](name) if signed_message = @parent_jar[name] - @verifier.verify(signed_message) + verify(signed_message) end - rescue ActiveSupport::MessageVerifier::InvalidSignature - nil end def []=(key, options) @@ -371,6 +400,14 @@ module ActionDispatch raise CookieOverflow if options[:value].size > MAX_COOKIE_SIZE @parent_jar[key] = options end + + private + + def verify(signed_message) + @verifier.verify(signed_message) + rescue ActiveSupport::MessageVerifier::InvalidSignature + nil + end end # UpgradeLegacySignedCookieJar is used instead of SignedCookieJar if @@ -378,30 +415,13 @@ module ActionDispatch # legacy cookies signed with the old dummy key generator and re-saves # them using the new key generator to provide a smooth upgrade path. class UpgradeLegacySignedCookieJar < SignedCookieJar #:nodoc: - def initialize(*args) - super - @legacy_verifier = ActiveSupport::MessageVerifier.new(@options[:secret_token]) - end + include VerifyAndUpgradeLegacySignedMessage def [](name) if signed_message = @parent_jar[name] - verify_signed_message(signed_message) || verify_and_upgrade_legacy_signed_message(name, signed_message) + verify(signed_message) || verify_and_upgrade_legacy_signed_message(name, signed_message) end end - - def verify_signed_message(signed_message) - @verifier.verify(signed_message) - rescue ActiveSupport::MessageVerifier::InvalidSignature - nil - end - - def verify_and_upgrade_legacy_signed_message(name, signed_message) - @legacy_verifier.verify(signed_message).tap do |value| - self[name] = value - end - rescue ActiveSupport::MessageVerifier::InvalidSignature - nil - end end class EncryptedCookieJar #:nodoc: @@ -409,8 +429,8 @@ module ActionDispatch def initialize(parent_jar, key_generator, options = {}) if ActiveSupport::DummyKeyGenerator === key_generator - raise "Encrypted Cookies must be used in conjunction with config.secret_key_base." + - "Set config.secret_key_base in config/initializers/secret_token.rb" + raise "You didn't set config.secret_key_base, which is required for this cookie jar. " + + "Read the upgrade documentation to learn more about this new config option." end @parent_jar = parent_jar @@ -422,11 +442,8 @@ module ActionDispatch def [](key) if encrypted_message = @parent_jar[key] - @encryptor.decrypt_and_verify(encrypted_message) + decrypt_and_verify(encrypted_message) end - rescue ActiveSupport::MessageVerifier::InvalidSignature, - ActiveSupport::MessageEncryptor::InvalidMessage - nil end def []=(key, options) @@ -440,6 +457,28 @@ module ActionDispatch raise CookieOverflow if options[:value].size > MAX_COOKIE_SIZE @parent_jar[key] = options end + + private + + def decrypt_and_verify(encrypted_message) + @encryptor.decrypt_and_verify(encrypted_message) + rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveSupport::MessageEncryptor::InvalidMessage + nil + end + end + + # UpgradeLegacyEncryptedCookieJar is used by ActionDispatch::Session::CookieStore + # instead of EncryptedCookieJar if config.secret_token and config.secret_key_base + # are both set. It reads legacy cookies signed with the old dummy key generator and + # encrypts and re-saves them using the new key generator to provide a smooth upgrade path. + class UpgradeLegacyEncryptedCookieJar < EncryptedCookieJar #:nodoc: + include VerifyAndUpgradeLegacySignedMessage + + def [](name) + if encrypted_or_signed_message = @parent_jar[name] + decrypt_and_verify(encrypted_or_signed_message) || verify_and_upgrade_legacy_signed_message(name, encrypted_or_signed_message) + end + end end def initialize(app) diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index 1e6ed624b0..b9eb8036e9 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -4,36 +4,51 @@ require 'rack/session/cookie' module ActionDispatch module Session - # This cookie-based session store is the Rails default. Sessions typically - # contain at most a user_id and flash message; both fit within the 4K cookie - # size limit. Cookie-based sessions are dramatically faster than the - # alternatives. + # This cookie-based session store is the Rails default. It is + # dramatically faster than the alternatives. # - # If you have more than 4K of session data or don't want your data to be - # visible to the user, pick another session store. + # Sessions typically contain at most a user_id and flash message; both fit + # within the 4K cookie size limit. A CookieOverflow exception is raised if + # you attempt to store more than 4K of data. # - # CookieOverflow is raised if you attempt to store more than 4K of data. + # The cookie jar used for storage is automatically configured to be the + # best possible option given your application's configuration. # - # A message digest is included with the cookie to ensure data integrity: - # a user cannot alter his +user_id+ without knowing the secret key - # included in the hash. New apps are generated with a pregenerated secret - # in config/environment.rb. Set your own for old apps you're upgrading. + # If you only have secret_token set, your cookies will be signed, but + # not encrypted. This means a user cannot alter his +user_id+ without + # knowing your app's secret key, but can easily read his +user_id+. This + # was the default for Rails 3 apps. # - # Session options: + # If you have secret_key_base set, your cookies will be encrypted. This + # goes a step further than signed cookies in that encrypted cookies cannot + # be altered or read by users. This is the default starting in Rails 4. # - # * <tt>:secret</tt>: An application-wide key string. It's important that - # the secret is not vulnerable to a dictionary attack. Therefore, you - # should choose a secret consisting of random numbers and letters and - # more than 30 characters. + # If you have both secret_token and secret_key base set, your cookies will + # be encrypted, and signed cookies generated by Rails 3 will be + # transparently read and encrypted to provide a smooth upgrade path. # - # secret: '449fe2e7daee471bffae2fd8dc02313d' + # Configure your session store in config/initializers/session_store.rb: # - # * <tt>:digest</tt>: The message digest algorithm used to verify session - # integrity defaults to 'SHA1' but may be any digest provided by OpenSSL, - # such as 'MD5', 'RIPEMD160', 'SHA256', etc. + # Myapp::Application.config.session_store :cookie_store, key: '_your_app_session' # - # To generate a secret key for an existing application, run - # "rake secret" and set the key in config/initializers/secret_token.rb. + # Configure your secret key in config/initializers/secret_token.rb: + # + # Myapp::Application.config.secret_key_base 'secret key' + # + # To generate a secret key for an existing application, run `rake secret`. + # + # If you are upgrading an existing Rails 3 app, you should leave your + # existing secret_token in place and simply add the new secret_key_base. + # Note that you should wait to set secret_key_base until you have 100% of + # your userbase on Rails 4 and are reasonably sure you will not need to + # rollback to Rails 3. This is because cookies signed based on the new + # secret_key_base in Rails 4 are not backwards compatible with Rails 3. + # You are free to leave your existing secret_token in place, not set the + # new secret_key_base, and ignore the deprecation warnings until you are + # reasonably sure that your upgrade is otherwise complete. Additionally, + # you should take care to make sure you are not relying on the ability to + # decode signed cookies generated by your app in external applications or + # Javascript before upgrading. # # Note that changing digest or secret invalidates all existing sessions! class CookieStore < Rack::Session::Abstract::ID @@ -100,42 +115,7 @@ module ActionDispatch def cookie_jar(env) request = ActionDispatch::Request.new(env) - request.cookie_jar.signed - end - end - - class EncryptedCookieStore < CookieStore - - private - - def cookie_jar(env) - request = ActionDispatch::Request.new(env) - request.cookie_jar.encrypted - end - end - - # This cookie store helps you upgrading apps that use +CookieStore+ to the new default +EncryptedCookieStore+ - # To use this CookieStore set - # - # Myapp::Application.config.session_store :upgrade_signature_to_encryption_cookie_store, key: '_myapp_session' - # - # in your config/initializers/session_store.rb - # - # You will also need to add - # - # Myapp::Application.config.secret_key_base = 'some secret' - # - # in your config/initializers/secret_token.rb, but do not remove +Myapp::Application.config.secret_token = 'some secret'+ - class UpgradeSignatureToEncryptionCookieStore < EncryptedCookieStore - private - - def get_cookie(env) - signed_using_old_secret_cookie_jar(env)[@key] || cookie_jar(env)[@key] - end - - def signed_using_old_secret_cookie_jar(env) - request = ActionDispatch::Request.new(env) - request.cookie_jar.signed_using_old_secret + request.cookie_jar.signed_or_encrypted end end end diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index d55eb8109a..550c7d0e7b 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -69,6 +69,22 @@ module ActionDispatch # <tt>Routing::Mapper::Scoping#namespace</tt>, and # <tt>Routing::Mapper::Scoping#scope</tt>. # + # == Non-resourceful routes + # + # For routes that don't fit the <tt>resources</tt> mold, you can use the HTTP helper + # methods <tt>get</tt>, <tt>post</tt>, <tt>patch</tt>, <tt>put</tt> and <tt>delete</tt>. + # + # get 'post/:id' => 'posts#show' + # post 'post/:id' => 'posts#create_comment' + # + # If your route needs to respond to more than one HTTP method (or all methods) then using the + # <tt>:via</tt> option on <tt>match</tt> is preferable. + # + # match 'post/:id' => 'posts#show', via: [:get, :post] + # + # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same + # URL will route to the <tt>show</tt> action. + # # == Named routes # # Routes can be named by passing an <tt>:as</tt> option, @@ -78,7 +94,7 @@ module ActionDispatch # Example: # # # In routes.rb - # match '/login' => 'accounts#login', as: 'login' + # get '/login' => 'accounts#login', as: 'login' # # # With render, redirect_to, tests, etc. # redirect_to login_url @@ -104,9 +120,9 @@ module ActionDispatch # # # In routes.rb # controller :blog do - # match 'blog/show' => :list - # match 'blog/delete' => :delete - # match 'blog/edit/:id' => :edit + # get 'blog/show' => :list + # get 'blog/delete' => :delete + # get 'blog/edit/:id' => :edit # end # # # provides named routes for show, delete, and edit @@ -116,7 +132,7 @@ module ActionDispatch # # Routes can generate pretty URLs. For example: # - # match '/articles/:year/:month/:day' => 'articles#find_by_id', constraints: { + # get '/articles/:year/:month/:day' => 'articles#find_by_id', constraints: { # year: /\d{4}/, # month: /\d{1,2}/, # day: /\d{1,2}/ @@ -131,7 +147,7 @@ module ActionDispatch # You can specify a regular expression to define a format for a parameter. # # controller 'geocode' do - # match 'geocode/:postalcode' => :show, constraints: { + # get 'geocode/:postalcode' => :show, constraints: { # postalcode: /\d{5}(-\d{4})?/ # } # @@ -139,13 +155,13 @@ module ActionDispatch # expression modifiers: # # controller 'geocode' do - # match 'geocode/:postalcode' => :show, constraints: { + # get 'geocode/:postalcode' => :show, constraints: { # postalcode: /hx\d\d\s\d[a-z]{2}/i # } # end # # controller 'geocode' do - # match 'geocode/:postalcode' => :show, constraints: { + # get 'geocode/:postalcode' => :show, constraints: { # postalcode: /# Postcode format # \d{5} #Prefix # (-\d{4})? #Suffix @@ -153,73 +169,21 @@ module ActionDispatch # } # end # - # Using the multiline match modifier will raise an +ArgumentError+. + # Using the multiline modifier will raise an +ArgumentError+. # Encoding regular expression modifiers are silently ignored. The # match will always use the default encoding or ASCII. # - # == Default route - # - # Consider the following route, which you will find commented out at the - # bottom of your generated <tt>config/routes.rb</tt>: - # - # match ':controller(/:action(/:id))(.:format)' - # - # This route states that it expects requests to consist of a - # <tt>:controller</tt> followed optionally by an <tt>:action</tt> that in - # turn is followed optionally by an <tt>:id</tt>, which in turn is followed - # optionally by a <tt>:format</tt>. - # - # Suppose you get an incoming request for <tt>/blog/edit/22</tt>, you'll end - # up with: - # - # params = { controller: 'blog', - # action: 'edit', - # id: '22' - # } - # - # By not relying on default routes, you improve the security of your - # application since not all controller actions, which includes actions you - # might add at a later time, are exposed by default. - # - # == HTTP Methods - # - # Using the <tt>:via</tt> option when specifying a route allows you to - # restrict it to a specific HTTP method. Possible values are <tt>:post</tt>, - # <tt>:get</tt>, <tt>:patch</tt>, <tt>:put</tt>, <tt>:delete</tt> and - # <tt>:any</tt>. If your route needs to respond to more than one method you - # can use an array, e.g. <tt>[ :get, :post ]</tt>. The default value is - # <tt>:any</tt> which means that the route will respond to any of the HTTP - # methods. - # - # match 'post/:id' => 'posts#show', via: :get - # match 'post/:id' => 'posts#create_comment', via: :post - # - # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same - # URL will route to the <tt>show</tt> action. - # - # === HTTP helper methods - # - # An alternative method of specifying which HTTP method a route should respond to is to use the helper - # methods <tt>get</tt>, <tt>post</tt>, <tt>patch</tt>, <tt>put</tt> and <tt>delete</tt>. - # - # get 'post/:id' => 'posts#show' - # post 'post/:id' => 'posts#create_comment' - # - # This syntax is less verbose and the intention is more apparent to someone else reading your code, - # however if your route needs to respond to more than one HTTP method (or all methods) then using the - # <tt>:via</tt> option on <tt>match</tt> is preferable. - # # == External redirects # # You can redirect any path to another path using the redirect helper in your router: # - # match "/stories" => redirect("/posts") + # get "/stories" => redirect("/posts") # # == Unicode character routes # # You can specify unicode character routes in your router: # - # match "こんにちは" => "welcome#index" + # get "こんにちは" => "welcome#index" # # == Routing to Rack Applications # @@ -227,7 +191,7 @@ module ActionDispatch # index action in the PostsController, you can specify any Rack application # as the endpoint for a matcher: # - # match "/application.js" => Sprockets + # get "/application.js" => Sprockets # # == Reloading routes # diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 7fb4719fa0..07203428d4 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -405,7 +405,7 @@ module ActionDispatch if name && named_routes[name] raise ArgumentError, "Invalid route name, already in use: '#{name}' \n" \ - "You may have defined two routes with the same name using the `:as` option, or " + "You may have defined two routes with the same name using the `:as` option, or " \ "you may be overriding a route already defined by a resource with the same naming. " \ "For the latter, you can restrict the routes created with `resources` as explained here: \n" \ "http://guides.rubyonrails.org/routing.html#restricting-the-routes-created" diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 6b6a7edc1d..36cfb7fca7 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -655,14 +655,6 @@ module ActionView # ... # <% end %> # - # When projects is already an association on Person you can use - # +accepts_nested_attributes_for+ to define the writer method for you: - # - # class Person < ActiveRecord::Base - # has_many :projects - # accepts_nested_attributes_for :projects - # end - # # If you want to destroy any of the associated models through the # form, you have to enable it first using the <tt>:allow_destroy</tt> # option for +accepts_nested_attributes_for+: @@ -1425,14 +1417,6 @@ module ActionView # ... # <% end %> # - # When projects is already an association on Person you can use - # +accepts_nested_attributes_for+ to define the writer method for you: - # - # class Person < ActiveRecord::Base - # has_many :projects - # accepts_nested_attributes_for :projects - # end - # # If you want to destroy any of the associated models through the # form, you have to enable it first using the <tt>:allow_destroy</tt> # option for +accepts_nested_attributes_for+: diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 377819a80c..7e65ebb4e4 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -565,7 +565,7 @@ module ActionView if priority_zones if priority_zones.is_a?(Regexp) - priority_zones = zones.grep(priority_zones) + priority_zones = zones.select { |z| z =~ priority_zones } end zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected) @@ -752,7 +752,7 @@ module ActionView end def prompt_text(prompt) - prompt = prompt.kind_of?(String) ? prompt : I18n.translate('helpers.select.prompt', :default => 'Please select') + prompt.kind_of?(String) ? prompt : I18n.translate('helpers.select.prompt', :default => 'Please select') end end diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 878d3e0eda..f7e15d0913 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -81,7 +81,7 @@ module ActionView # # => <input class="ok" onclick="alert('Hello world!');" type="button" value="Greeting" /> # def button_to_function(name, function=nil, html_options={}) - message = "button_to_function is deprecated and will be removed from Rails 4.1. We recomend to use Unobtrusive JavaScript instead. " + + message = "button_to_function is deprecated and will be removed from Rails 4.1. We recommend to use Unobtrusive JavaScript instead. " + "See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript" ActiveSupport::Deprecation.warn message @@ -103,7 +103,7 @@ module ActionView # # => <a class="nav_link" href="#" onclick="alert('Hello world!'); return false;">Greeting</a> # def link_to_function(name, function, html_options={}) - message = "link_to_function is deprecated and will be removed from Rails 4.1. We recomend to use Unobtrusive JavaScript instead. " + + message = "link_to_function is deprecated and will be removed from Rails 4.1. We recommend to use Unobtrusive JavaScript instead. " + "See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript" ActiveSupport::Deprecation.warn message diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 47bd011d5e..6b9b0a826b 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -255,7 +255,7 @@ module ActionView # # FileSystemResolver.new("/path/to/views", ":prefix/:action{.:locale,}{.:formats,}{.:handlers,}") # - # This one allows you to keep files with different formats in seperated subdirectories, + # This one allows you to keep files with different formats in separate subdirectories, # eg. `users/new.html` will be loaded from `users/html/new.erb` or `users/new.html.erb`, # `users/new.js` from `users/js/new.erb` or `users/new.js.erb`, etc. # diff --git a/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb b/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb index 60b6783b19..7f8609c408 100644 --- a/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb +++ b/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb @@ -537,7 +537,7 @@ module HTML # Get identifier, class, attribute name, pseudo or negation. while true # Element identifier. - next if statement.sub!(/^#(\?|[\w\-]+)/) do |match| + next if statement.sub!(/^#(\?|[\w\-]+)/) do id = $1 if id == "?" id = values.shift @@ -549,7 +549,7 @@ module HTML end # Class name. - next if statement.sub!(/^\.([\w\-]+)/) do |match| + next if statement.sub!(/^\.([\w\-]+)/) do class_name = $1 @source << ".#{class_name}" class_name = Regexp.new("(^|\s)#{Regexp.escape(class_name)}($|\s)") unless class_name.is_a?(Regexp) @@ -558,7 +558,7 @@ module HTML end # Attribute value. - next if statement.sub!(/^\[\s*([[:alpha:]][\w\-:]*)\s*((?:[~|^$*])?=)?\s*('[^']*'|"[^*]"|[^\]]*)\s*\]/) do |match| + next if statement.sub!(/^\[\s*([[:alpha:]][\w\-:]*)\s*((?:[~|^$*])?=)?\s*('[^']*'|"[^*]"|[^\]]*)\s*\]/) do name, equality, value = $1, $2, $3 if value == "?" value = values.shift @@ -575,7 +575,7 @@ module HTML end # Root element only. - next if statement.sub!(/^:root/) do |match| + next if statement.sub!(/^:root/) do pseudo << lambda do |element| element.parent.nil? || !element.parent.tag? end @@ -611,7 +611,7 @@ module HTML "" # Remove end # First/last child (of type). - next if statement.sub!(/^:(first|last)-(child|of-type)/) do |match| + next if statement.sub!(/^:(first|last)-(child|of-type)/) do reverse = $1 == "last" of_type = $2 == "of-type" pseudo << nth_child(0, 1, of_type, reverse) @@ -619,7 +619,7 @@ module HTML "" # Remove end # Only child (of type). - next if statement.sub!(/^:only-(child|of-type)/) do |match| + next if statement.sub!(/^:only-(child|of-type)/) do of_type = $1 == "of-type" pseudo << only_child(of_type) @source << ":only-#{$1}" @@ -628,7 +628,7 @@ module HTML # Empty: no child elements or meaningful content (whitespaces # are ignored). - next if statement.sub!(/^:empty/) do |match| + next if statement.sub!(/^:empty/) do pseudo << lambda do |element| empty = true for child in element.children @@ -644,7 +644,7 @@ module HTML end # Content: match the text content of the element, stripping # leading and trailing spaces. - next if statement.sub!(/^:content\(\s*(\?|'[^']*'|"[^"]*"|[^)]*)\s*\)/) do |match| + next if statement.sub!(/^:content\(\s*(\?|'[^']*'|"[^"]*"|[^)]*)\s*\)/) do content = $1 if content == "?" content = values.shift |