diff options
26 files changed, 168 insertions, 45 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 0dfda417c2..0c6973f9b6 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,9 +1,10 @@ ## Rails 4.0.0 (unreleased) ## -* Fixed ActionController#action_missing not being called. - Fixes GH#9799. +* Allow default url options to accept host with protocol such as `http://` - *Janko Luin* + config.action_mailer.default_url_options = { host: "http://mydomain.com" } + + *Richard Schneeman* * Ensure that digest authentication responds with a 401 status when a basic header is received. diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index aff2172788..ebd87c40b5 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -158,29 +158,27 @@ module ActionDispatch # Returns the +String+ full path including params of the last URL requested. # - # app.get "/articles" - # app.request.fullpath # => "/articles" + # # get "/articles" + # request.fullpath # => "/articles" # - # app.get "/articles?page=2" - # app.request.fullpath # => "/articles?page=2" + # # get "/articles?page=2" + # request.fullpath # => "/articles?page=2" def fullpath @fullpath ||= super end - # Returns the original request URL as a +String+ + # Returns the original request URL as a +String+. # - # app.get "/articles?page=2" - # app.request.original_url - # # => "http://www.example.com/articles?page=2" + # # get "/articles?page=2" + # request.original_url # => "http://www.example.com/articles?page=2" def original_url base_url + original_fullpath end - # The +String+ MIME type of the request + # The +String+ MIME type of the request. # - # app.get "/articles" - # app.request.media_type - # # => "application/x-www-form-urlencoded" + # # get "/articles" + # request.media_type # => "application/x-www-form-urlencoded" def media_type content_mime_type.to_s end diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 97ac462411..ab5399c8ea 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -59,8 +59,9 @@ module ActionDispatch result = "" unless options[:only_path] + protocol = extract_protocol(options) unless options[:protocol] == false - result << (options[:protocol] || "http") + result << protocol result << ":" unless result.match(%r{:|//}) end result << "//" unless result.match("//") @@ -83,6 +84,16 @@ module ActionDispatch end end + # Extracts protocol http:// or https:// from options[:host] + # needs to be called whether the :protocol is being used or not + def extract_protocol(options) + if options[:host] && match = options[:host].match(/(^.*:\/\/)(.*)/) + options[:protocol] ||= match[1] + options[:host] = match[2] + end + options[:protocol] || "http" + end + def host_or_subdomain_and_domain(options) return options[:host] if !named_host?(options[:host]) || (options[:subdomain].nil? && options[:domain].nil?) diff --git a/actionpack/test/dispatch/url_generation_test.rb b/actionpack/test/dispatch/url_generation_test.rb index e56e8ddc57..4123529092 100644 --- a/actionpack/test/dispatch/url_generation_test.rb +++ b/actionpack/test/dispatch/url_generation_test.rb @@ -48,6 +48,14 @@ module TestUrlGeneration https! assert_equal "http://www.example.com/foo", foo_url(:protocol => "http") end + + test "extracting protocol from host when protocol not present" do + assert_equal "httpz://www.example.com/foo", foo_url(host: "httpz://www.example.com", protocol: nil) + end + + test "formatting host when protocol is present" do + assert_equal "http://www.example.com/foo", foo_url(host: "httpz://www.example.com", protocol: "http://") + end end end diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 6ba0c7cd6b..62d684fd0b 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,5 +1,26 @@ ## Rails 4.0.0 (unreleased) ## +* Added a method so that validations can be easily cleared on a model. + For example: + + class Person + include ActiveModel::Validations + + validates_uniqueness_of :first_name + validate :cannot_be_robot + + def cannot_be_robot + errors.add(:base, 'A person cannot be a robot') if person_is_robot + end + end + + Now, if someone runs `Person.clear_validators!`, then the following occurs: + + Person.validators # => [] + Person._validate_callbacks.empty? # => true + + *John Wang* + * `has_secure_password` does not fail the confirmation validation when assigning empty String to `password` and `password_confirmation`. diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 2db4a25f61..72e3cf310a 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -169,6 +169,49 @@ module ActiveModel _validators.values.flatten.uniq end + # Clears all of the validators and validations. + # + # Note that this will clear anything that is being used to validate + # the model for both the +validates_with+ and +validate+ methods. + # It clears the validators that are created with an invocation of + # +validates_with+ and the callbacks that are set by an invocation + # of +validate+. + # + # class Person + # include ActiveModel::Validations + # + # validates_with MyValidator + # validates_with OtherValidator, on: :create + # validates_with StrictValidator, strict: true + # validate :cannot_be_robot + # + # def cannot_be_robot + # errors.add(:base, 'A person cannot be a robot') if person_is_robot + # end + # end + # + # Person.validators + # # => [ + # # #<MyValidator:0x007fbff403e808 @options={}>, + # # #<OtherValidator:0x007fbff403d930 @options={on: :create}>, + # # #<StrictValidator:0x007fbff3204a30 @options={strict:true}> + # # ] + # + # If one runs Person.clear_validators! and then checks to see what + # validators this class has, you would obtain: + # + # Person.validators # => [] + # + # Also, the callback set by +validate :cannot_be_robot+ will be erased + # so that: + # + # Person._validate_callbacks.empty? # => true + # + def clear_validators! + reset_callbacks(:validate) + _validators.clear + end + # List all validators that are being used to validate a specific attribute. # # class Person diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index e5ab6bac58..3e368407f2 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,15 @@ ## Rails 4.0.0 (unreleased) ## +* If inverse_of is true on an association, then when one calls +find()+ on + the association, ActiveRecord will first look through the in-memory objects + in the association for a particular id. Then, it will go to the DB if it + is not found. This is accomplished by calling +find_by_scan+ in + collection associations whenever +options[:inverse_of]+ is not nil. + + Fixes #9470. + + *John Wang* + * `rake db:create` does not change permissions of the MySQL root user. Fixes #8079. @@ -515,7 +525,7 @@ *Justin George* -* The database adpters now converts the options passed thought `DATABASE_URL` +* The database adapters now converts the options passed thought `DATABASE_URL` environment variable to the proper Ruby types before using. For example, SQLite requires that the timeout value is an integer, and PostgreSQL requires that the prepared_statements option is a boolean. These now work as expected: @@ -614,7 +624,7 @@ *John Wang* -* Collection associations `#empty?` always respects builded records. +* Collection associations `#empty?` always respects built records. Fixes #8879. Example: @@ -1493,7 +1503,7 @@ * Move HABTM validity checks to `ActiveRecord::Reflection`. One side effect of this is to move when the exceptions are raised from the point of declaration - to when the association is built. This is consistant with other association + to when the association is built. This is consistent with other association validity checks. *Andrew White* diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 0c670bdaa1..eb08f72286 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -966,7 +966,7 @@ module ActiveRecord # For +has_and_belongs_to_many+, <tt>delete</tt> and <tt>destroy</tt> are the same: they # cause the records in the join table to be removed. # - # For +has_many+, <tt>destroy</tt> and <tt>destory_all</tt> will always call the <tt>destroy</tt> method of the + # For +has_many+, <tt>destroy</tt> and <tt>destroy_all</tt> will always call the <tt>destroy</tt> method of the # record(s) being removed so that callbacks are run. However <tt>delete</tt> and <tt>delete_all</tt> will either # do the deletion according to the strategy specified by the <tt>:dependent</tt> option, or # if no <tt>:dependent</tt> option is given, then it will follow the default strategy. diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 906560bd44..51bcac61c7 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -79,7 +79,7 @@ module ActiveRecord if block_given? load_target.find(*args) { |*block_args| yield(*block_args) } else - if options[:finder_sql] + if options[:finder_sql] || options[:inverse_of] find_by_scan(*args) else scope.find(*args) @@ -507,8 +507,8 @@ module ActiveRecord records.flatten.each do |record| raise_on_type_mismatch(record) - add_to_target(record) do |r| - result &&= insert_record(record) unless owner.new_record? + add_to_target(record) do |rec| + result &&= insert_record(rec) unless owner.new_record? end end @@ -567,7 +567,8 @@ module ActiveRecord end end - # If using a custom finder_sql, #find scans the entire collection. + # If using a custom finder_sql or if the :inverse_of option has been + # specified, then #find scans the entire collection. def find_by_scan(*args) expects_array = args.first.kind_of?(Array) ids = args.flatten.compact.map{ |arg| arg.to_i }.uniq diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 9137504d15..bf2f945448 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -238,7 +238,7 @@ module ActiveRecord @checkout_timeout = spec.config[:checkout_timeout] || 5 @dead_connection_timeout = spec.config[:dead_connection_timeout] || 5 - @reaper = Reaper.new(self, spec.config[:reaping_frequency] || 10) + @reaper = Reaper.new self, spec.config[:reaping_frequency] @reaper.run # default max pool size to 5 @@ -406,7 +406,9 @@ module ActiveRecord synchronize do stale = Time.now - @dead_connection_timeout connections.dup.each do |conn| - remove conn if conn.in_use? && stale > conn.last_use && !conn.active? + if conn.in_use? && stale > conn.last_use && !conn.active? + remove conn + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index dfa4c3967a..940de7e4f6 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -519,8 +519,7 @@ module ActiveRecord # Is this connection alive and ready for queries? def active? - @connection.query 'SELECT 1' - true + @connection.connect_poll != PG::PGRES_POLLING_FAILED rescue PGError false end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 5d7762ec3a..27d37766b7 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -858,7 +858,7 @@ module ActiveRecord end def current_version - migrated.sort.last || 0 + migrated.max || 0 end def current_migration diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 10a31109d5..257221174b 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -614,7 +614,7 @@ module ActiveRecord # # The returned <tt>ActiveRecord::NullRelation</tt> inherits from Relation and implements the # Null Object pattern. It is an object with defined null behavior and always returns an empty - # array of records without quering the database. + # array of records without querying the database. # # Any subsequent condition chained to the returned relation will continue # generating an empty relation and will not fire any query to the database. diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb index 8812cf1b7d..5d71effb1f 100644 --- a/activerecord/test/cases/adapters/mysql/active_schema_test.rb +++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb @@ -70,8 +70,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase def test_add_timestamps with_real_execute do begin - ActiveRecord::Base.connection.create_table :delete_me do |t| - end + ActiveRecord::Base.connection.create_table :delete_me ActiveRecord::Base.connection.add_timestamps :delete_me assert column_present?('delete_me', 'updated_at', 'datetime') assert column_present?('delete_me', 'created_at', 'datetime') diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb index 8c9b4fb921..c8cad84013 100644 --- a/activerecord/test/cases/associations/inverse_associations_test.rb +++ b/activerecord/test/cases/associations/inverse_associations_test.rb @@ -278,6 +278,31 @@ class InverseHasManyTests < ActiveRecord::TestCase assert interests[1].man.equal? man end + def test_parent_instance_should_find_child_instance_using_child_instance_id + man = Man.create! + interest = Interest.create! + man.interests = [interest] + + assert interest.equal?(man.interests.first), "The inverse association should use the interest already created and held in memory" + assert interest.equal?(man.interests.find(interest.id)), "The inverse association should use the interest already created and held in memory" + assert man.equal?(man.interests.first.man), "Two inversion should lead back to the same object that was originally held" + assert man.equal?(man.interests.find(interest.id).man), "Two inversions should lead back to the same object that was originally held" + end + + def test_parent_instance_should_find_child_instance_using_child_instance_id_when_created + man = Man.create! + interest = Interest.create!(man: man) + + assert man.equal?(man.interests.first.man), "Two inverses should lead back to the same object that was originally held" + assert man.equal?(man.interests.find(interest.id).man), "Two inversions should lead back to the same object that was originally held" + + assert_equal man.name, man.interests.find(interest.id).man.name, "The name of the man should match before the name is changed" + man.name = "Ben Bitdiddle" + assert_equal man.name, man.interests.find(interest.id).man.name, "The name of the man should match after the parent name is changed" + man.interests.find(interest.id).man.name = "Alyssa P. Hacker" + assert_equal man.name, man.interests.find(interest.id).man.name, "The name of the man should match after the child name is changed" + end + def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.first.secret_interests } end diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index c05481dd91..aabeea025f 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -464,7 +464,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase assert saved_post.reload.tags(true).include?(new_tag) - new_post = Post.new(:title => "Association replacmenet works!", :body => "You best believe it.") + new_post = Post.new(:title => "Association replacement works!", :body => "You best believe it.") saved_tag = tags(:general) new_post.tags << saved_tag diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 445322486c..7fb50e9617 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -141,13 +141,13 @@ class BasicsTest < ActiveRecord::TestCase end end - def test_limit_should_sanitize_sql_injection_for_limit_without_comas + def test_limit_should_sanitize_sql_injection_for_limit_without_commas assert_raises(ArgumentError) do Topic.limit("1 select * from schema").to_a end end - def test_limit_should_sanitize_sql_injection_for_limit_with_comas + def test_limit_should_sanitize_sql_injection_for_limit_with_commas assert_raises(ArgumentError) do Topic.limit("1, 7 procedure help()").to_a end diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb index 7457bafd4e..187cad9599 100644 --- a/activerecord/test/cases/callbacks_test.rb +++ b/activerecord/test/cases/callbacks_test.rb @@ -520,7 +520,7 @@ class CallbacksTest < ActiveRecord::TestCase ], david.history end - def test_inheritence_of_callbacks + def test_inheritance_of_callbacks parent = ParentDeveloper.new assert !parent.after_save_called parent.save diff --git a/activerecord/test/cases/validations_repair_helper.rb b/activerecord/test/cases/validations_repair_helper.rb index 11912ca1cc..c02b3241cd 100644 --- a/activerecord/test/cases/validations_repair_helper.rb +++ b/activerecord/test/cases/validations_repair_helper.rb @@ -6,7 +6,7 @@ module ActiveRecord def repair_validations(*model_classes) teardown do model_classes.each do |k| - k.reset_callbacks(:validate) + k.clear_validators! end end end @@ -16,7 +16,7 @@ module ActiveRecord yield ensure model_classes.each do |k| - k.reset_callbacks(:validate) + k.clear_validators! end end end diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index edbe697962..6bfac15289 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -344,7 +344,7 @@ module ActiveSupport # Options are passed to the underlying cache implementation. def write(name, value, options = nil) options = merged_options(options) - instrument(:write, name, options) do |payload| + instrument(:write, name, options) do entry = Entry.new(value, options) write_entry(namespaced_key(name, options), entry, options) end @@ -355,7 +355,7 @@ module ActiveSupport # Options are passed to the underlying cache implementation. def delete(name, options = nil) options = merged_options(options) - instrument(:delete, name) do |payload| + instrument(:delete, name) do delete_entry(namespaced_key(name, options), options) end end @@ -365,7 +365,7 @@ module ActiveSupport # Options are passed to the underlying cache implementation. def exist?(name, options = nil) options = merged_options(options) - instrument(:exist?, name) do |payload| + instrument(:exist?, name) do entry = read_entry(namespaced_key(name, options), options) entry && !entry.expired? end diff --git a/activesupport/test/xml_mini/jdom_engine_test.rb b/activesupport/test/xml_mini/jdom_engine_test.rb index 4d44b72df6..2dfdde5c62 100644 --- a/activesupport/test/xml_mini/jdom_engine_test.rb +++ b/activesupport/test/xml_mini/jdom_engine_test.rb @@ -43,7 +43,7 @@ if RUBY_PLATFORM =~ /java/ assert_equal 'x', Hash.from_xml(attack_xml)["member"] end - def test_not_allowed_to_expand_parameter_entities_to_files + def test_not_allowed_to_expand_parameter_entities_to_files attack_xml = <<-EOT <!DOCTYPE member [ <!ENTITY % b SYSTEM "file://#{FILES_DIR}/jdom_entities.txt"> diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md index 7e0a8a43d4..e01d0d57ea 100644 --- a/guides/source/action_controller_overview.md +++ b/guides/source/action_controller_overview.md @@ -194,7 +194,7 @@ class PeopleController < ActionController::Base # This will pass with flying colors as long as there's a person key # in the parameters, otherwise it'll raise a - # ActionController::MissingParameter exception, which will get + # ActionController::ParameterMissing exception, which will get # caught by ActionController::Base and turned into that 400 Bad # Request reply. def update diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 60a823de15..3a81e0861b 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,5 +1,9 @@ ## Rails 4.0.0 (unreleased) ## +* Don't generate a scaffold.css when --no-assets is specified + + *Kevin Glowacz* + * Add support for generate scaffold password:digest * adds password_digest attribute to the migration diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt index e5caab3672..efccf72d3d 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt @@ -1,6 +1,6 @@ # Be sure to restart your server when you modify this file. -# Your secret key for verifying the integrity of signed cookies. +# Your secret key is used for verifying the integrity of signed cookies. # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, diff --git a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb index 36589d65e2..2a0522e81c 100644 --- a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb +++ b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb @@ -10,6 +10,7 @@ module Rails class_option :stylesheet_engine, desc: "Engine for Stylesheets" def handle_skip + @options = @options.merge(stylesheets: false) unless options[:assets] @options = @options.merge(stylesheet_engine: false) unless options[:stylesheets] end diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb index b29d1e018e..25f299118c 100644 --- a/railties/test/generators/scaffold_generator_test.rb +++ b/railties/test/generators/scaffold_generator_test.rb @@ -241,7 +241,7 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase def test_scaffold_generator_no_assets run_generator [ "posts", "--no-assets" ] - assert_file "app/assets/stylesheets/scaffold.css" + assert_no_file "app/assets/stylesheets/scaffold.css" assert_no_file "app/assets/javascripts/posts.js" assert_no_file "app/assets/stylesheets/posts.css" end |