Permalink
Browse files

Merge branch 'master' into railstest

* master: (44 commits)
  Improve the changelog entry [ci skip]
  Fix explicit names on multiple file fields
  Correctly parse bigint defaults in PostgreSQL
  Move changelog to the top [ci skip]
  Fix indent and remove extra white spaces
  Fix scope chaining + STI
  failing test for #9869
  Improve `belongs_to touch: true` timestamp test
  Sort modules in alphabetical order.
  Avoid an attempt to fetch old record when id was not present in touch callback
  Use the correct pk field from the reflected class to find the old record
  Refactor mail_to to not generate intermediate hashes when adding href
  Ensure mail_to helper does not modify the given html options hash
  Use inspect when writing the foreign key from the reflection
  Use a space after the comment sign when showing the result of commands
  Exclude template files for rdoc API [ci skip]
  template should have generic name
  use | to have more intent revealing code
  Revert "Merge pull request #10034 from benofsky/fix_skipping_object_callback_filters"
  stop depending on callbacks
  ...

Conflicts:
	railties/test/application/rake_test.rb
  • Loading branch information...
2 parents c037659 + 096ee15 commit 01034d3be0d7c8c09b551ac612c4b18f86086dc5 @tenderlove tenderlove committed Apr 5, 2013
Showing with 345 additions and 94 deletions.
  1. +12 −0 actionpack/CHANGELOG.md
  2. +7 −8 actionpack/lib/action_view/helpers/tags/base.rb
  3. +18 −6 actionpack/lib/action_view/helpers/url_helper.rb
  4. 0 actionpack/test/fixtures/test/{change_priorty.html.erb → change_priority.html.erb}
  5. +10 −0 actionpack/test/template/form_helper_test.rb
  6. +17 −15 actionpack/test/template/form_options_helper_test.rb
  7. +1 −1 actionpack/test/template/render_test.rb
  8. +16 −0 actionpack/test/template/url_helper_test.rb
  9. +47 −0 activerecord/CHANGELOG.md
  10. +2 −2 activerecord/lib/active_record.rb
  11. +1 −0 activerecord/lib/active_record/associations/association.rb
  12. +1 −0 activerecord/lib/active_record/associations/association_scope.rb
  13. +12 −1 activerecord/lib/active_record/associations/builder/belongs_to.rb
  14. +2 −4 activerecord/lib/active_record/associations/collection_proxy.rb
  15. +1 −1 activerecord/lib/active_record/associations/join_dependency.rb
  16. +4 −4 activerecord/lib/active_record/associations/join_dependency/join_association.rb
  17. +1 −1 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
  18. +12 −6 activerecord/lib/active_record/fixtures.rb
  19. +30 −2 activerecord/lib/active_record/reflection.rb
  20. +1 −1 activerecord/lib/active_record/relation.rb
  21. +2 −2 activerecord/lib/active_record/scoping.rb
  22. +2 −7 activerecord/lib/active_record/scoping/named.rb
  23. +1 −1 activerecord/test/cases/associations/eager_test.rb
  24. +7 −1 activerecord/test/cases/associations/has_many_through_associations_test.rb
  25. +16 −0 activerecord/test/cases/associations/inverse_associations_test.rb
  26. +0 −1 activerecord/test/cases/base_test.rb
  27. +1 −1 activerecord/test/cases/persistence_test.rb
  28. +5 −0 activerecord/test/cases/schema_dumper_test.rb
  29. +5 −0 activerecord/test/cases/scoping/named_scoping_test.rb
  30. +46 −0 activerecord/test/cases/timestamp_test.rb
  31. +5 −0 activerecord/test/fixtures/pets.yml
  32. +10 −0 activerecord/test/fixtures/toys.yml
  33. +1 −1 activerecord/test/models/owner.rb
  34. +0 −2 activerecord/test/models/pet.rb
  35. +1 −0 activerecord/test/schema/postgresql_specific_schema.rb
  36. +1 −0 activesupport/lib/active_support/core_ext/big_decimal/conversions.rb
  37. +1 −1 activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
  38. +2 −3 activesupport/lib/active_support/log_subscriber.rb
  39. +2 −4 activesupport/test/core_ext/enumerable_test.rb
  40. +1 −1 guides/bug_report_templates/active_record_gem.rb
  41. +1 −1 guides/bug_report_templates/active_record_master.rb
  42. +2 −1 railties/lib/rails/api/task.rb
  43. +1 −1 railties/lib/rails/generators/named_base.rb
  44. +16 −10 railties/lib/rails/generators/rails/model/USAGE
  45. +4 −0 railties/lib/rails/test_unit/testing.rake
  46. +10 −0 railties/test/application/rake_test.rb
  47. +3 −2 railties/test/commands/console_test.rb
  48. +3 −1 railties/test/commands/dbconsole_test.rb
  49. +1 −1 railties/test/generators/plugin_new_generator_test.rb
@@ -1,5 +1,17 @@
## Rails 4.0.0 (unreleased) ##
+* Fix explicit names on multiple file fields. If a file field tag has
+ the multiple option, it is turned into an array field (appending `[]`),
+ but if an explicit name is passed to `file_field` the `[]` is not
+ appended.
+ Fixes #9830.
+
+ *Ryan McGeary*
+
+* Add block support for the `mail_to` helper, similar to the `link_to` helper.
+
+ *Sam Pohlenz*
+
* Automatically configure cookie-based sessions to be encrypted if
`secret_key_base` is set, falling back to signed if only `secret_token`
is set. Automatically upgrade existing signed cookie-based sessions from
@@ -73,27 +73,26 @@ def add_default_name_and_id_for_value(tag_value, options)
def add_default_name_and_id(options)
if options.has_key?("index")
- options["name"] ||= options.fetch("name"){ tag_name_with_index(options["index"]) }
+ options["name"] ||= options.fetch("name"){ tag_name_with_index(options["index"], options["multiple"]) }
options["id"] = options.fetch("id"){ tag_id_with_index(options["index"]) }
options.delete("index")
elsif defined?(@auto_index)
- options["name"] ||= options.fetch("name"){ tag_name_with_index(@auto_index) }
+ options["name"] ||= options.fetch("name"){ tag_name_with_index(@auto_index, options["multiple"]) }
options["id"] = options.fetch("id"){ tag_id_with_index(@auto_index) }
else
- options["name"] ||= options.fetch("name"){ tag_name }
+ options["name"] ||= options.fetch("name"){ tag_name(options["multiple"]) }
options["id"] = options.fetch("id"){ tag_id }
end
- options["name"] += "[]" if options["multiple"] && !options["name"].ends_with?("[]")
options["id"] = [options.delete('namespace'), options["id"]].compact.join("_").presence
end
- def tag_name
- "#{@object_name}[#{sanitized_method_name}]"
+ def tag_name(multiple = false)
+ "#{@object_name}[#{sanitized_method_name}]#{"[]" if multiple}"
end
- def tag_name_with_index(index)
- "#{@object_name}[#{index}][#{sanitized_method_name}]"
+ def tag_name_with_index(index, multiple = false)
+ "#{@object_name}[#{index}][#{sanitized_method_name}]#{"[]" if multiple}"
end
def tag_id
@@ -425,8 +425,8 @@ def link_to_if(condition, name, options = {}, html_options = {}, &block)
# * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email.
#
# ==== Obfuscation
- # Prior to Rails 4.0, +mail_to+ provided options for encoding the address
- # in order to hinder email harvesters. To take advantage of these options,
+ # Prior to Rails 4.0, +mail_to+ provided options for encoding the address
+ # in order to hinder email harvesters. To take advantage of these options,
# install the +actionview-encoded_mail_to+ gem.
#
# ==== Examples
@@ -439,18 +439,30 @@ def link_to_if(condition, name, options = {}, html_options = {}, &block)
# mail_to "me@domain.com", "My email", cc: "ccaddress@domain.com",
# subject: "This is an example email"
# # => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">My email</a>
- def mail_to(email_address, name = nil, html_options = {})
+ #
+ # You can use a block as well if your link target is hard to fit into the name parameter. ERB example:
+ #
+ # <%= mail_to "me@domain.com" do %>
+ # <strong>Email me:</strong> <span>me@domain.com</span>
+ # <% end %>
+ # # => <a href="mailto:me@domain.com">
+ # <strong>Email me:</strong> <span>me@domain.com</span>
+ # </a>
+ def mail_to(email_address, name = nil, html_options = {}, &block)
email_address = ERB::Util.html_escape(email_address)
- html_options.stringify_keys!
+ html_options, name = name, nil if block_given?
+ html_options = (html_options || {}).stringify_keys
extras = %w{ cc bcc body subject }.map { |item|
option = html_options.delete(item) || next
"#{item}=#{Rack::Utils.escape_path(option)}"
}.compact
extras = extras.empty? ? '' : '?' + ERB::Util.html_escape(extras.join('&'))
-
- content_tag "a", name || email_address.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe)
+
+ html_options["href"] = "mailto:#{email_address}#{extras}".html_safe
+
+ content_tag(:a, name || email_address.html_safe, html_options, &block)
end
# True if the current request URI was generated by the given +options+.
@@ -361,6 +361,16 @@ def test_file_field_has_no_size
assert_dom_equal expected, file_field("user", "avatar")
end
+ def test_file_field_with_multiple_behavior
+ expected = '<input id="import_file" multiple="multiple" name="import[file][]" type="file" />'
+ assert_dom_equal expected, file_field("import", "file", :multiple => true)
+ end
+
+ def test_file_field_with_multiple_behavior_and_explicit_name
+ expected = '<input id="import_file" multiple="multiple" name="custom" type="file" />'
+ assert_dom_equal expected, file_field("import", "file", :multiple => true, :name => "custom")
+ end
+
def test_hidden_field
assert_dom_equal(
'<input id="post_title" name="post[title]" type="hidden" value="Hello World" />',
@@ -1110,15 +1110,15 @@ def test_time_zone_select_with_priority_zones_as_regexp
"</select>",
html
end
-
+
def test_time_zone_select_with_priority_zones_as_regexp_using_grep_finds_no_zones
@firm = Firm.new("D")
-
+
priority_zones = /A|D/
@fake_timezones.each do |tz|
priority_zones.stubs(:===).with(tz).raises(Exception)
end
-
+
html = time_zone_select("firm", "time_zone", priority_zones)
assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" +
"<option value=\"\" disabled=\"disabled\">-------------</option>\n" +
@@ -1134,8 +1134,9 @@ def test_time_zone_select_with_priority_zones_as_regexp_using_grep_finds_no_zone
def test_time_zone_select_with_default_time_zone_and_nil_value
@firm = Firm.new()
@firm.time_zone = nil
- html = time_zone_select( "firm", "time_zone", nil, :default => 'B' )
- assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" +
+
+ html = time_zone_select( "firm", "time_zone", nil, :default => 'B' )
+ assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" +
"<option value=\"A\">A</option>\n" +
"<option value=\"B\" selected=\"selected\">B</option>\n" +
"<option value=\"C\">C</option>\n" +
@@ -1146,16 +1147,17 @@ def test_time_zone_select_with_default_time_zone_and_nil_value
end
def test_time_zone_select_with_default_time_zone_and_value
- @firm = Firm.new('D')
- html = time_zone_select( "firm", "time_zone", nil, :default => 'B' )
- assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" +
- "<option value=\"A\">A</option>\n" +
- "<option value=\"B\">B</option>\n" +
- "<option value=\"C\">C</option>\n" +
- "<option value=\"D\" selected=\"selected\">D</option>\n" +
- "<option value=\"E\">E</option>" +
- "</select>",
- html
+ @firm = Firm.new('D')
+
+ html = time_zone_select( "firm", "time_zone", nil, :default => 'B' )
+ assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" +
+ "<option value=\"A\">A</option>\n" +
+ "<option value=\"B\">B</option>\n" +
+ "<option value=\"C\">C</option>\n" +
+ "<option value=\"D\" selected=\"selected\">D</option>\n" +
+ "<option value=\"E\">E</option>" +
+ "</select>",
+ html
end
def test_options_for_select_with_element_attributes
@@ -61,7 +61,7 @@ def test_render_partial_implicitly_use_format_of_the_rendered_partial
def test_render_partial_use_last_prepended_format_for_partials_with_the_same_names
@view.lookup_context.formats = [:html]
- assert_equal "\nHTML Template, but JSON partial", @view.render(:template => "test/change_priorty")
+ assert_equal "\nHTML Template, but JSON partial", @view.render(:template => "test/change_priority")
end
def test_render_template_with_a_missing_partial_of_another_format
@@ -538,6 +538,22 @@ def test_mail_to_returns_html_safe_string
assert mail_to("david@loudthinking.com").html_safe?
end
+ def test_mail_to_with_block
+ assert_dom_equal %{<a href="mailto:me@example.com"><span>Email me</span></a>},
+ mail_to('me@example.com') { content_tag(:span, 'Email me') }
+ end
+
+ def test_mail_to_with_block_and_options
+ assert_dom_equal %{<a class="special" href="mailto:me@example.com?cc=ccaddress%40example.com"><span>Email me</span></a>},
+ mail_to('me@example.com', cc: "ccaddress@example.com", class: "special") { content_tag(:span, 'Email me') }
+ end
+
+ def test_mail_to_does_not_modify_html_options_hash
+ options = { class: 'special' }
+ mail_to 'me@example.com', 'ME!', options
+ assert_equal({ class: 'special' }, options)
+ end
+
def protect_against_forgery?
self.request_forgery
end
@@ -1,5 +1,52 @@
## Rails 4.0.0 (unreleased) ##
+* Default values for PostgreSQL bigint types now get parsed and dumped to the
+ schema correctly.
+
+ *Erik Peterson*
+
+* Fix associations with `:inverse_of` option when building association
+ with a block. Inside the block the parent object was different then
+ after the block.
+
+ Example:
+
+ parent.association.build do |child|
+ child.parent.equal?(parent) # false
+ end
+
+ # vs
+
+ child = parent.association.build
+ child.parent.equal?(parent) # true
+
+ *Michal Cichra*
+
+* `has_many` using `:through` now obeys the order clause mentioned in
+ through association. Fixes #10016.
+
+ *Neeraj Singh*
+
+* `belongs_to :touch` behavior now touches old association when
+ transitioning to new association.
+
+ class Passenger < ActiveRecord::Base
+ belongs_to :car, touch: true
+ end
+
+ car_1 = Car.create
+ car_2 = Car.create
+
+ passenger = Passenger.create car: car_1
+
+ passenger.car = car_2
+ passenger.save
+
+ Previously only car_2 would be touched. Now both car_1 and car_2
+ will be touched.
+
+ *Adam Gamble*
+
* Extract and deprecate Firebird / Sqlserver / Oracle database tasks, because
These tasks should be supported by 3rd-party adapter.
@@ -35,8 +35,8 @@ module ActiveRecord
autoload :Base
autoload :Callbacks
autoload :Core
- autoload :CounterCache
autoload :ConnectionHandling
+ autoload :CounterCache
autoload :DynamicMatchers
autoload :Explain
autoload :Inheritance
@@ -69,8 +69,8 @@ module ActiveRecord
autoload :Aggregations
autoload :Associations
- autoload :AttributeMethods
autoload :AttributeAssignment
+ autoload :AttributeMethods
autoload :AutosaveAssociation
autoload :Relation
@@ -236,6 +236,7 @@ def build_record(attributes)
skip_assign = [reflection.foreign_key, reflection.type].compact
attributes = create_scope.except(*(record.changed - skip_assign))
record.assign_attributes(attributes)
+ set_inverse_instance(record)
end
end
end
@@ -101,6 +101,7 @@ def add_constraints(scope)
scope.includes! item.includes_values
scope.where_values += item.where_values
+ scope.order_values |= item.order_values
end
end
@@ -66,8 +66,19 @@ def belongs_to_counter_cache_after_update_for_#{name}
def add_touch_callbacks(reflection)
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
def belongs_to_touch_after_save_or_destroy_for_#{name}
- record = #{name}
+ foreign_key_field = #{reflection.foreign_key.inspect}
+ old_foreign_id = attribute_was(foreign_key_field)
+
+ if old_foreign_id
+ reflection_klass = #{reflection.klass}
+ old_record = reflection_klass.find_by(reflection_klass.primary_key => old_foreign_id)
+
+ if old_record
+ old_record.touch #{options[:touch].inspect if options[:touch] != true}
+ end
+ end
+ record = #{name}
unless record.nil? || record.new_record?
record.touch #{options[:touch].inspect if options[:touch] != true}
end
@@ -847,10 +847,8 @@ def scoping
# Returns a <tt>Relation</tt> object for the records in this association
def scope
- association = @association
-
- @association.scope.extending! do
- define_method(:proxy_association) { association }
+ @association.scope.tap do |scope|
+ scope.proxy_association = @association
end
end
@@ -109,7 +109,7 @@ def build(associations, parent = nil, join_type = Arel::InnerJoin)
case associations
when Symbol, String
reflection = parent.reflections[associations.intern] or
- raise ConfigurationError, "Association named '#{ associations }' was not found; perhaps you misspelled it?"
+ raise ConfigurationError, "Association named '#{ associations }' was not found on #{ parent.active_record.name }; perhaps you misspelled it?"
unless join_association = find_join_association(reflection, parent)
@reflections << reflection
join_association = build_join_association(reflection, parent)
@@ -59,7 +59,7 @@ def find_parent_in(other_join_dependency)
end
end
- def join_to(relation)
+ def join_to(manager)
tables = @tables.dup
foreign_table = parent_table
foreign_klass = parent.active_record
@@ -75,7 +75,7 @@ def join_to(relation)
foreign_key = reflection.foreign_key
when :has_and_belongs_to_many
# Join the join table first...
- relation.from(join(
+ manager.from(join(
table,
table[reflection.foreign_key].
eq(foreign_table[reflection.active_record_primary_key])
@@ -109,13 +109,13 @@ def join_to(relation)
constraint = constraint.and(item.arel.constraints) unless item.arel.constraints.empty?
end
- relation.from(join(table, constraint))
+ manager.from(join(table, constraint))
# The current table in this iteration becomes the foreign table in the next
foreign_table, foreign_klass = table, reflection.klass
end
- relation
+ manager
end
def build_constraint(reflection, table, key, foreign_table, foreign_key)
@@ -80,7 +80,7 @@ def self.extract_value_from_default(default)
when /\A'(.*)'::(num|date|tstz|ts|int4|int8)range\z/m
$1
# Numeric types
- when /\A\(?(-?\d+(\.\d*)?\)?)\z/
+ when /\A\(?(-?\d+(\.\d*)?\)?(::bigint)?)\z/
$1
# Character types
when /\A\(?'(.*)'::.*\b(?:character varying|bpchar|text)\z/m
Oops, something went wrong.

0 comments on commit 01034d3

Please sign in to comment.