diff options
-rw-r--r-- | actionpack/CHANGELOG.md | 7 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/mime_type.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/date_helper.rb | 14 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/text_helper.rb | 54 | ||||
-rw-r--r-- | actionpack/test/dispatch/request/session_test.rb | 9 | ||||
-rw-r--r-- | actionpack/test/dispatch/response_test.rb | 57 | ||||
-rw-r--r-- | actionpack/test/dispatch/session/cookie_store_test.rb | 20 | ||||
-rw-r--r-- | actionpack/test/template/text_helper_test.rb | 13 | ||||
-rw-r--r-- | activerecord/CHANGELOG.md | 28 | ||||
-rw-r--r-- | activerecord/lib/active_record/attribute_methods/query.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/nested_attributes.rb | 23 | ||||
-rw-r--r-- | activerecord/lib/active_record/schema.rb | 8 | ||||
-rw-r--r-- | activerecord/lib/active_record/schema_dumper.rb | 20 | ||||
-rw-r--r-- | activerecord/test/cases/finder_test.rb | 1 | ||||
-rw-r--r-- | activerecord/test/cases/schema_dumper_test.rb | 88 | ||||
-rw-r--r-- | guides/source/migrations.textile | 6 |
16 files changed, 229 insertions, 122 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 1232370439..8c7089cf57 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,12 @@ ## Rails 4.0.0 (unreleased) ## +* Add `separator` option for `ActionView::Helpers::TextHelper#excerpt`: + + excerpt('This is a very beautiful morning', 'very', :separator => ' ', :radius => 1) + # => ...a very beautiful... + + *Guirec Corbel* + * Added controller-level etag additions that will be part of the action etag computation *Jeremy Kemper/DHH* class InvoicesController < ApplicationController diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 3c1f1458ea..f86ae26b8a 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -1,5 +1,6 @@ require 'set' require 'active_support/core_ext/class/attribute_accessors' +require 'active_support/core_ext/string/starts_ends_with' module Mime class Mimes < Array diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 795440cacc..387dfeab17 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -904,10 +904,13 @@ module ActionView # <option value="3">3</option> # <option value="5">5</option>..." def build_options(selected, options = {}) + options = { + leading_zeros: true, ampm: false, use_two_digit_numbers: false + }.merge!(options) + start = options.delete(:start) || 0 stop = options.delete(:end) || 59 step = options.delete(:step) || 1 - options.reverse_merge!({:leading_zeros => true, :ampm => false, :use_two_digit_numbers => false}) leading_zeros = options.delete(:leading_zeros) select_options = [] @@ -919,6 +922,7 @@ module ActionView text = options[:ampm] ? AMPM_TRANSLATION[i] : text select_options << content_tag(:option, text, tag_options) end + (select_options.join("\n") + "\n").html_safe end @@ -931,8 +935,8 @@ module ActionView select_options = { :id => input_id_from_type(type), :name => input_name_from_type(type) - }.merge(@html_options) - select_options.merge!(:disabled => 'disabled') if @options[:disabled] + }.merge!(@html_options) + select_options[:disabled] = 'disabled' if @options[:disabled] select_html = "\n" select_html << content_tag(:option, '', :value => '') + "\n" if @options[:include_blank] @@ -968,8 +972,8 @@ module ActionView :id => input_id_from_type(type), :name => input_name_from_type(type), :value => value - }.merge(@html_options.slice(:disabled)) - select_options.merge!(:disabled => 'disabled') if @options[:disabled] + }.merge!(@html_options.slice(:disabled)) + select_options[:disabled] = 'disabled' if @options[:disabled] tag(:input, select_options) + "\n".html_safe end diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 0f599d5f41..527bfe0cab 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -126,8 +126,9 @@ module ActionView # Extracts an excerpt from +text+ that matches the first instance of +phrase+. # The <tt>:radius</tt> option expands the excerpt on each side of the first occurrence of +phrase+ by the number of characters # defined in <tt>:radius</tt> (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+, - # then the <tt>:omission</tt> option (which defaults to "...") will be prepended/appended accordingly. The resulting string - # will be stripped in any case. If the +phrase+ isn't found, nil is returned. + # then the <tt>:omission</tt> option (which defaults to "...") will be prepended/appended accordingly. The + # <tt>:separator</tt> enable to choose the delimation. The resulting string will be stripped in any case. If the +phrase+ + # isn't found, nil is returned. # # excerpt('This is an example', 'an', :radius => 5) # # => ...s is an exam... @@ -143,21 +144,32 @@ module ActionView # # excerpt('This is also an example', 'an', :radius => 8, :omission => '<chop> ') # # => <chop> is also an example + # + # excerpt('This is a very beautiful morning', 'very', :separator => ' ', :radius => 1) + # # => ...a very beautiful... def excerpt(text, phrase, options = {}) return unless text && phrase - radius = options.fetch(:radius, 100) - omission = options.fetch(:omission, "...") - phrase = Regexp.escape(phrase) - return unless found_pos = text =~ /(#{phrase})/i + separator = options.fetch(:separator, "") + phrase = Regexp.escape(phrase) + regex = /#{phrase}/i + + return unless matches = text.match(regex) + phrase = matches[0] + + text.split(separator).each do |value| + if value.match(regex) + regex = phrase = value + break + end + end - start_pos = [ found_pos - radius, 0 ].max - end_pos = [ [ found_pos + phrase.length + radius - 1, 0].max, text.length ].min + first_part, second_part = text.split(regex, 2) - prefix = start_pos > 0 ? omission : "" - postfix = end_pos < text.length - 1 ? omission : "" + prefix, first_part = cut_excerpt_part(:first, first_part, separator, options) + postfix, second_part = cut_excerpt_part(:second, second_part, separator, options) - prefix + text[start_pos..end_pos].strip + postfix + prefix + (first_part + separator + phrase + separator + second_part).strip + postfix end # Attempts to pluralize the +singular+ word unless +count+ is 1. If @@ -402,6 +414,26 @@ module ActionView t.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') || t end end + + def cut_excerpt_part(part_position, part, separator, options) + return "", "" unless part + + radius = options.fetch(:radius, 100) + omission = options.fetch(:omission, "...") + + part = part.split(separator) + part.delete("") + affix = part.size > radius ? omission : "" + + part = if part_position == :first + drop_index = [part.length - radius, 0].max + part.drop(drop_index) + else + part.first(radius) + end + + return affix, part.join(separator) + end end end end diff --git a/actionpack/test/dispatch/request/session_test.rb b/actionpack/test/dispatch/request/session_test.rb index 80d5a13171..3f36d4f1a9 100644 --- a/actionpack/test/dispatch/request/session_test.rb +++ b/actionpack/test/dispatch/request/session_test.rb @@ -52,6 +52,15 @@ module ActionDispatch assert_equal %w[ftw awesome], s.values end + def test_clear + env = {} + s = Session.create(store, env, {}) + s['rails'] = 'ftw' + s['adequate'] = 'awesome' + s.clear + assert_equal([], s.values) + end + private def store Class.new { diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 4d699bd739..185a9e9b18 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -178,33 +178,40 @@ class ResponseTest < ActiveSupport::TestCase end test "read x_frame_options, x_content_type_options and x_xss_protection" do - ActionDispatch::Response.default_headers = { - 'X-Frame-Options' => 'DENY', - 'X-Content-Type-Options' => 'nosniff', - 'X-XSS-Protection' => '1;' - } - resp = ActionDispatch::Response.new.tap { |response| - response.body = 'Hello' - } - resp.to_a - - assert_equal('DENY', resp.headers['X-Frame-Options']) - assert_equal('nosniff', resp.headers['X-Content-Type-Options']) - assert_equal('1;', resp.headers['X-XSS-Protection']) - end + begin + ActionDispatch::Response.default_headers = { + 'X-Frame-Options' => 'DENY', + 'X-Content-Type-Options' => 'nosniff', + 'X-XSS-Protection' => '1;' + } + resp = ActionDispatch::Response.new.tap { |response| + response.body = 'Hello' + } + resp.to_a + + assert_equal('DENY', resp.headers['X-Frame-Options']) + assert_equal('nosniff', resp.headers['X-Content-Type-Options']) + assert_equal('1;', resp.headers['X-XSS-Protection']) + ensure + ActionDispatch::Response.default_headers = nil + end + end test "read custom default_header" do - ActionDispatch::Response.default_headers = { - 'X-XX-XXXX' => 'Here is my phone number' - } - resp = ActionDispatch::Response.new.tap { |response| - response.body = 'Hello' - } - resp.to_a - - assert_equal('Here is my phone number', resp.headers['X-XX-XXXX']) - end - + begin + ActionDispatch::Response.default_headers = { + 'X-XX-XXXX' => 'Here is my phone number' + } + resp = ActionDispatch::Response.new.tap { |response| + response.body = 'Hello' + } + resp.to_a + + assert_equal('Here is my phone number', resp.headers['X-XX-XXXX']) + ensure + ActionDispatch::Response.default_headers = nil + end + end end class ResponseIntegrationTest < ActionDispatch::IntegrationTest diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index 631974d6c4..41fa036a92 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -30,6 +30,11 @@ class CookieStoreTest < ActionDispatch::IntegrationTest render :text => "id: #{request.session_options[:id]}" end + def get_class_after_reset_session + reset_session + render :text => "class: #{session.class}" + end + def call_session_clear session.clear head :ok @@ -187,6 +192,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest get '/call_reset_session' assert_response :success assert_not_equal [], headers['Set-Cookie'] + assert_not_nil session_payload assert_not_equal session_payload, cookies[SessionKey] get '/get_session_value' @@ -195,6 +201,20 @@ class CookieStoreTest < ActionDispatch::IntegrationTest end end + def test_class_type_after_session_reset + with_test_route_set do + get '/set_session_value' + assert_response :success + assert_equal "_myapp_session=#{response.body}; path=/; HttpOnly", + headers['Set-Cookie'] + + get '/get_class_after_reset_session' + assert_response :success + assert_not_equal [], headers['Set-Cookie'] + assert_equal 'class: ActionDispatch::Request::Session', response.body + end + end + def test_getting_from_nonexistent_session with_test_route_set do get '/get_session_value' diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index c0f694b2bf..4525efe73c 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -303,6 +303,19 @@ class TextHelperTest < ActionView::TestCase assert_equal options, passed_options end + def test_excerpt_with_separator + options = { :separator => ' ', :radius => 1 } + assert_equal('...a very beautiful...', excerpt('This is a very beautiful morning', 'very', options)) + assert_equal('This is...', excerpt('This is a very beautiful morning', 'this', options)) + assert_equal('...beautiful morning', excerpt('This is a very beautiful morning', 'morning', options)) + + options = { :separator => "\n", :radius => 0 } + assert_equal("...very long...", excerpt("my very\nvery\nvery long\nstring", 'long', options)) + + options = { :separator => "\n", :radius => 1 } + assert_equal("...very\nvery long\nstring", excerpt("my very\nvery\nvery long\nstring", 'long', options)) + end + def test_word_wrap assert_equal("my very very\nvery long\nstring", word_wrap("my very very very long string", :line_width => 15)) end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 5dd1e8d76e..6f7b2cb108 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,16 @@ ## Rails 4.0.0 (unreleased) ## +* Attribute predicate methods, such as `article.title?`, will now raise + `ActiveModel::MissingAttributeError` if the attribute being queried for + truthiness was not read from the database, instead of just returning false. + + *Ernie Miller* + +* `ActiveRecord::SchemaDumper` uses Ruby 1.9 style hash, which means that the + schema.rb file will be generated using this new syntax from now on. + + *Konstantin Shabanov* + * Map interval with precision to string datatype in PostgreSQL. Fixes #7518. *Yves Senn* * Fix eagerly loading associations without primary keys. Fixes #4976. *Kelley Reynolds* @@ -24,7 +35,7 @@ *Ian Lesperance* -* Allow JSON columns to be created in PostgreSQL and properly encoded/decoded +* Allow JSON columns to be created in PostgreSQL and properly encoded/decoded. to/from database. *Dickson S. Guedes* @@ -33,7 +44,7 @@ *Adam Meehan* -* Allow to pass Symbol or Proc into :limit option of #accepts_nested_attributes_for +* Allow to pass Symbol or Proc into :limit option of #accepts_nested_attributes_for. *Mikhail Dieterle* @@ -74,10 +85,11 @@ *Dave Yeu* -* Fixed table name prefix that is generated in engines for namespaced models +* Fixed table name prefix that is generated in engines for namespaced models. + *Wojciech Wnętrzak* -* Make sure `:environment` task is executed before `db:schema:load` or `db:structure:load` +* Make sure `:environment` task is executed before `db:schema:load` or `db:structure:load`. Fixes #4772. *Seamus Abshere* @@ -102,7 +114,7 @@ *Jon Leighton* -* Add CollectionProxy#scope +* Add CollectionProxy#scope. This can be used to get a Relation from an association. @@ -120,7 +132,7 @@ *Jon Leighton* -* Add `Relation#load` +* Add `Relation#load`. This method explicitly loads the records and then returns `self`. @@ -136,7 +148,7 @@ *Jon Leighton* * `Model.all` now returns an `ActiveRecord::Relation`, rather than an - array of records. Use ``Relation#to_a` if you really want an array. + array of records. Use `Relation#to_a` if you really want an array. In some specific cases, this may cause breakage when upgrading. However in most cases the `ActiveRecord::Relation` will just act as a @@ -160,7 +172,7 @@ * `:insert_sql` and `:delete_sql` options on `has_and_belongs_to_many` associations are deprecated. Please transition to using `has_many - :through` + :through`. *Jon Leighton* diff --git a/activerecord/lib/active_record/attribute_methods/query.rb b/activerecord/lib/active_record/attribute_methods/query.rb index 483fd8f4f8..0f9723febb 100644 --- a/activerecord/lib/active_record/attribute_methods/query.rb +++ b/activerecord/lib/active_record/attribute_methods/query.rb @@ -8,7 +8,7 @@ module ActiveRecord end def query_attribute(attr_name) - value = read_attribute(attr_name) + value = read_attribute(attr_name) { |n| missing_attribute(n, caller) } case value when true then true diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index f91e41b535..3005dc042c 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -389,17 +389,19 @@ module ActiveRecord raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})" end - limit = case options[:limit] - when Symbol - send(options[:limit]) - when Proc - options[:limit].call - else - options[:limit] - end + if limit = options[:limit] + limit = case limit + when Symbol + send(limit) + when Proc + limit.call + else + limit + end - if limit && attributes_collection.size > limit - raise TooManyRecords, "Maximum #{limit} records are allowed. Got #{attributes_collection.size} records instead." + if limit && attributes_collection.size > limit + raise TooManyRecords, "Maximum #{limit} records are allowed. Got #{attributes_collection.size} records instead." + end end if attributes_collection.is_a? Hash @@ -438,7 +440,6 @@ module ActiveRecord else association.add_to_target(existing_record) end - end if !call_reject_if(association_name, attributes) diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index a540bc0a3b..eaa4aa7086 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -11,16 +11,16 @@ module ActiveRecord # # ActiveRecord::Schema.define do # create_table :authors do |t| - # t.string :name, :null => false + # t.string :name, null: false # end # # add_index :authors, :name, :unique # # create_table :posts do |t| - # t.integer :author_id, :null => false + # t.integer :author_id, null: false # t.string :subject # t.text :body - # t.boolean :private, :default => false + # t.boolean :private, default: false # end # # add_index :posts, :author_id @@ -50,7 +50,7 @@ module ActiveRecord # The +info+ hash is optional, and if given is used to define metadata # about the current schema (currently, only the schema's version): # - # ActiveRecord::Schema.define(:version => 20380119000001) do + # ActiveRecord::Schema.define(version: 20380119000001) do # ... # end def self.define(info={}, &block) diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index a25a8d79bd..310b4c1459 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -38,7 +38,7 @@ module ActiveRecord end def header(stream) - define_params = @version ? ":version => #{@version}" : "" + define_params = @version ? "version: #{@version}" : "" if stream.respond_to?(:external_encoding) && stream.external_encoding stream.puts "# encoding: #{stream.external_encoding.name}" @@ -95,12 +95,12 @@ HEADER tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}" if columns.detect { |c| c.name == pk } if pk != 'id' - tbl.print %Q(, :primary_key => "#{pk}") + tbl.print %Q(, primary_key: "#{pk}") end else - tbl.print ", :id => false" + tbl.print ", id: false" end - tbl.print ", :force => true" + tbl.print ", force: true" tbl.puts " do |t|" # then dump all non-primary key columns @@ -122,7 +122,7 @@ HEADER spec[:scale] = column.scale.inspect if column.scale spec[:null] = 'false' unless column.null spec[:default] = default_string(column.default) if column.has_default? - (spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")} + (spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.to_s}: ")} spec end.compact @@ -187,17 +187,17 @@ HEADER statement_parts = [ ('add_index ' + remove_prefix_and_suffix(index.table).inspect), index.columns.inspect, - (':name => ' + index.name.inspect), + ('name: ' + index.name.inspect), ] - statement_parts << ':unique => true' if index.unique + statement_parts << 'unique: true' if index.unique index_lengths = (index.lengths || []).compact - statement_parts << (':length => ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty? + statement_parts << ('length: ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty? index_orders = (index.orders || {}) - statement_parts << (':order => ' + index.orders.inspect) unless index_orders.empty? + statement_parts << ('order: ' + index.orders.inspect) unless index_orders.empty? - statement_parts << (':where => ' + index.where.inspect) if index.where + statement_parts << ('where: ' + index.where.inspect) if index.where ' ' + statement_parts.join(', ') end diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 20c8e8894d..d44ac21b05 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -276,6 +276,7 @@ class FinderTest < ActiveRecord::TestCase def test_find_only_some_columns topic = Topic.all.merge!(:select => "author_name").find(1) assert_raise(ActiveModel::MissingAttributeError) {topic.title} + assert_raise(ActiveModel::MissingAttributeError) {topic.title?} assert_nil topic.read_attribute("title") assert_equal "David", topic.author_name assert !topic.attribute_present?("title") diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 68e88372f3..80d2670f94 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -96,7 +96,7 @@ class SchemaDumperTest < ActiveRecord::TestCase ActiveRecord::SchemaDumper.ignore_tables = [/^[^r]/] ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) output = stream.string - assert_match %r{:null => false}, output + assert_match %r{null: false}, output end def test_schema_dump_includes_limit_constraint_for_integer_columns @@ -107,46 +107,46 @@ class SchemaDumperTest < ActiveRecord::TestCase output = stream.string if current_adapter?(:PostgreSQLAdapter) - assert_match %r{c_int_1.*:limit => 2}, output - assert_match %r{c_int_2.*:limit => 2}, output + assert_match %r{c_int_1.*limit: 2}, output + assert_match %r{c_int_2.*limit: 2}, output # int 3 is 4 bytes in postgresql assert_match %r{c_int_3.*}, output - assert_no_match %r{c_int_3.*:limit}, output + assert_no_match %r{c_int_3.*limit:}, output assert_match %r{c_int_4.*}, output - assert_no_match %r{c_int_4.*:limit}, output + assert_no_match %r{c_int_4.*limit:}, output elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) - assert_match %r{c_int_1.*:limit => 1}, output - assert_match %r{c_int_2.*:limit => 2}, output - assert_match %r{c_int_3.*:limit => 3}, output + assert_match %r{c_int_1.*limit: 1}, output + assert_match %r{c_int_2.*limit: 2}, output + assert_match %r{c_int_3.*limit: 3}, output assert_match %r{c_int_4.*}, output assert_no_match %r{c_int_4.*:limit}, output elsif current_adapter?(:SQLite3Adapter) - assert_match %r{c_int_1.*:limit => 1}, output - assert_match %r{c_int_2.*:limit => 2}, output - assert_match %r{c_int_3.*:limit => 3}, output - assert_match %r{c_int_4.*:limit => 4}, output + assert_match %r{c_int_1.*limit: 1}, output + assert_match %r{c_int_2.*limit: 2}, output + assert_match %r{c_int_3.*limit: 3}, output + assert_match %r{c_int_4.*limit: 4}, output end assert_match %r{c_int_without_limit.*}, output - assert_no_match %r{c_int_without_limit.*:limit}, output + assert_no_match %r{c_int_without_limit.*limit:}, output if current_adapter?(:SQLite3Adapter) - assert_match %r{c_int_5.*:limit => 5}, output - assert_match %r{c_int_6.*:limit => 6}, output - assert_match %r{c_int_7.*:limit => 7}, output - assert_match %r{c_int_8.*:limit => 8}, output + assert_match %r{c_int_5.*limit: 5}, output + assert_match %r{c_int_6.*limit: 6}, output + assert_match %r{c_int_7.*limit: 7}, output + assert_match %r{c_int_8.*limit: 8}, output elsif current_adapter?(:OracleAdapter) - assert_match %r{c_int_5.*:limit => 5}, output - assert_match %r{c_int_6.*:limit => 6}, output - assert_match %r{c_int_7.*:limit => 7}, output - assert_match %r{c_int_8.*:limit => 8}, output + assert_match %r{c_int_5.*limit: 5}, output + assert_match %r{c_int_6.*limit: 6}, output + assert_match %r{c_int_7.*limit: 7}, output + assert_match %r{c_int_8.*limit: 8}, output else - assert_match %r{c_int_5.*:limit => 8}, output - assert_match %r{c_int_6.*:limit => 8}, output - assert_match %r{c_int_7.*:limit => 8}, output - assert_match %r{c_int_8.*:limit => 8}, output + assert_match %r{c_int_5.*limit: 8}, output + assert_match %r{c_int_6.*limit: 8}, output + assert_match %r{c_int_7.*limit: 8}, output + assert_match %r{c_int_8.*limit: 8}, output end end @@ -182,15 +182,15 @@ class SchemaDumperTest < ActiveRecord::TestCase def test_schema_dumps_index_columns_in_right_order index_definition = standard_dump.split(/\n/).grep(/add_index.*companies/).first.strip - assert_equal 'add_index "companies", ["firm_id", "type", "rating"], :name => "company_index"', index_definition + assert_equal 'add_index "companies", ["firm_id", "type", "rating"], name: "company_index"', index_definition end def test_schema_dumps_partial_indices index_definition = standard_dump.split(/\n/).grep(/add_index.*company_partial_index/).first.strip if current_adapter?(:PostgreSQLAdapter) - assert_equal 'add_index "companies", ["firm_id", "type"], :name => "company_partial_index", :where => "(rating > 10)"', index_definition + assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)"', index_definition else - assert_equal 'add_index "companies", ["firm_id", "type"], :name => "company_partial_index"', index_definition + assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index"', index_definition end end @@ -198,25 +198,25 @@ class SchemaDumperTest < ActiveRecord::TestCase output = standard_dump match = output.match(%r{create_table "movies"(.*)do}) assert_not_nil(match, "nonstandardpk table not found") - assert_match %r(:primary_key => "movieid"), match[1], "non-standard primary key not preserved" + assert_match %r(primary_key: "movieid"), match[1], "non-standard primary key not preserved" end if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) def test_schema_dump_should_not_add_default_value_for_mysql_text_field output = standard_dump - assert_match %r{t.text\s+"body",\s+:null => false$}, output + assert_match %r{t.text\s+"body",\s+null: false$}, output end def test_schema_dump_includes_length_for_mysql_blob_and_text_fields output = standard_dump - assert_match %r{t.binary\s+"tiny_blob",\s+:limit => 255$}, output + assert_match %r{t.binary\s+"tiny_blob",\s+limit: 255$}, output assert_match %r{t.binary\s+"normal_blob"$}, output - assert_match %r{t.binary\s+"medium_blob",\s+:limit => 16777215$}, output - assert_match %r{t.binary\s+"long_blob",\s+:limit => 2147483647$}, output - assert_match %r{t.text\s+"tiny_text",\s+:limit => 255$}, output + assert_match %r{t.binary\s+"medium_blob",\s+limit: 16777215$}, output + assert_match %r{t.binary\s+"long_blob",\s+limit: 2147483647$}, output + assert_match %r{t.text\s+"tiny_text",\s+limit: 255$}, output assert_match %r{t.text\s+"normal_text"$}, output - assert_match %r{t.text\s+"medium_text",\s+:limit => 16777215$}, output - assert_match %r{t.text\s+"long_text",\s+:limit => 2147483647$}, output + assert_match %r{t.text\s+"medium_text",\s+limit: 16777215$}, output + assert_match %r{t.text\s+"long_text",\s+limit: 2147483647$}, output end end @@ -225,7 +225,7 @@ class SchemaDumperTest < ActiveRecord::TestCase ActiveRecord::SchemaDumper.ignore_tables = [/^[^n]/] ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) output = stream.string - assert_match %r{:precision => 3,[[:space:]]+:scale => 2,[[:space:]]+:default => 2.78}, output + assert_match %r{precision: 3,[[:space:]]+scale: 2,[[:space:]]+default: 2.78}, output end if current_adapter?(:PostgreSQLAdapter) @@ -239,7 +239,7 @@ class SchemaDumperTest < ActiveRecord::TestCase def test_schema_dump_includes_json_shorthand_definition output = standard_dump if %r{create_table "postgresql_json_data_type"} =~ output - assert_match %r|t.json "json_data", :default => {}|, output + assert_match %r|t.json "json_data", default: {}|, output end end @@ -274,7 +274,7 @@ class SchemaDumperTest < ActiveRecord::TestCase def test_schema_dump_includes_hstores_shorthand_definition output = standard_dump if %r{create_table "postgresql_hstores"} =~ output - assert_match %r[t.hstore "hash_store", :default => {}], output + assert_match %r[t.hstore "hash_store", default: {}], output end end @@ -290,9 +290,9 @@ class SchemaDumperTest < ActiveRecord::TestCase output = standard_dump # Oracle supports precision up to 38 and it identifies decimals with scale 0 as integers if current_adapter?(:OracleAdapter) - assert_match %r{t.integer\s+"atoms_in_universe",\s+:precision => 38,\s+:scale => 0}, output + assert_match %r{t.integer\s+"atoms_in_universe",\s+precision: 38,\s+scale: 0}, output else - assert_match %r{t.decimal\s+"atoms_in_universe",\s+:precision => 55,\s+:scale => 0}, output + assert_match %r{t.decimal\s+"atoms_in_universe",\s+precision: 55,\s+scale: 0}, output end end @@ -300,13 +300,13 @@ class SchemaDumperTest < ActiveRecord::TestCase output = standard_dump match = output.match(%r{create_table "goofy_string_id"(.*)do.*\n(.*)\n}) assert_not_nil(match, "goofy_string_id table not found") - assert_match %r(:id => false), match[1], "no table id not preserved" - assert_match %r{t.string[[:space:]]+"id",[[:space:]]+:null => false$}, match[2], "non-primary key id column not preserved" + assert_match %r(id: false), match[1], "no table id not preserved" + assert_match %r{t.string[[:space:]]+"id",[[:space:]]+null: false$}, match[2], "non-primary key id column not preserved" end def test_schema_dump_keeps_id_false_when_id_is_false_and_unique_not_null_column_added output = standard_dump - assert_match %r{create_table "subscribers", :id => false}, output + assert_match %r{create_table "subscribers", id: false}, output end class CreateDogMigration < ActiveRecord::Migration diff --git a/guides/source/migrations.textile b/guides/source/migrations.textile index a7de21b754..587be269f7 100644 --- a/guides/source/migrations.textile +++ b/guides/source/migrations.textile @@ -912,14 +912,14 @@ If +:ruby+ is selected then the schema is stored in +db/schema.rb+. If you look at this file you'll find that it looks an awful lot like one very big migration: <ruby> -ActiveRecord::Schema.define(:version => 20080906171750) do - create_table "authors", :force => true do |t| +ActiveRecord::Schema.define(version: 20080906171750) do + create_table "authors", force: true do |t| t.string "name" t.datetime "created_at" t.datetime "updated_at" end - create_table "products", :force => true do |t| + create_table "products", force: true do |t| t.string "name" t.text "description" t.datetime "created_at" |