diff options
33 files changed, 154 insertions, 109 deletions
diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index 5d9eda2555..b218d923e5 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -287,7 +287,7 @@ class BaseTest < ActiveSupport::TestCase end end - assert_nothing_raised { LateAttachmentAccessorMailer.welcome } + assert_nothing_raised { LateAttachmentAccessorMailer.welcome.message } end # Implicit multipart diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 91ac7eef01..e977bbce99 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -22,7 +22,6 @@ module ActionController autoload :ForceSSL autoload :Head autoload :Helpers - autoload :HideActions autoload :HttpAuthentication autoload :ImplicitRender autoload :Instrumentation diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 929b161eb6..108a35f59f 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -58,27 +58,6 @@ class TestController < ActionController::Base end end - def conditional_hello_with_public_header - if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true) - render :action => 'hello_world' - end - end - - def conditional_hello_with_public_header_with_record - record = Struct.new(:updated_at, :cache_key).new(Time.now.utc.beginning_of_day, "foo/123") - - if stale?(record, :public => true) - render :action => 'hello_world' - end - end - - def conditional_hello_with_public_header_and_expires_at - expires_in 1.minute - if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true) - render :action => 'hello_world' - end - end - def conditional_hello_with_expires_in expires_in 60.1.seconds render :action => 'hello_world' @@ -129,50 +108,6 @@ class TestController < ActionController::Base fresh_when(:last_modified => Time.now.utc.beginning_of_day, :etag => [ :foo, 123 ]) end - def heading - head :ok - end - - # :ported: - def double_render - render :text => "hello" - render :text => "world" - end - - def double_redirect - redirect_to :action => "double_render" - redirect_to :action => "double_render" - end - - def render_and_redirect - render :text => "hello" - redirect_to :action => "double_render" - end - - def render_to_string_and_render - @stuff = render_to_string :text => "here is some cached stuff" - render :text => "Hi web users! #{@stuff}" - end - - def render_to_string_with_inline_and_render - render_to_string :inline => "<%= 'dlrow olleh'.reverse %>" - render :template => "test/hello_world" - end - - def rendering_with_conflicting_local_vars - @name = "David" - render :action => "potential_conflicts" - end - - def hello_world_from_rxml_using_action - render :action => "hello_world_from_rxml", :handlers => [:builder] - end - - # :deprecated: - def hello_world_from_rxml_using_template - render :template => "test/hello_world_from_rxml", :handlers => [:builder] - end - def head_created head :created end diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb index 7f1207eaed..9a6747fb8d 100644 --- a/actionpack/test/dispatch/static_test.rb +++ b/actionpack/test/dispatch/static_test.rb @@ -1,6 +1,5 @@ # encoding: utf-8 require 'abstract_unit' -require 'rbconfig' require 'zlib' module StaticTests diff --git a/actionview/test/actionpack/controller/layout_test.rb b/actionview/test/actionpack/controller/layout_test.rb index bd345fe873..7b8a83e2fe 100644 --- a/actionview/test/actionpack/controller/layout_test.rb +++ b/actionview/test/actionpack/controller/layout_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'rbconfig' require 'active_support/core_ext/array/extract_options' # The view_paths array must be set on Base and not LayoutTest so that LayoutTest's inherited diff --git a/activemodel/test/cases/dirty_test.rb b/activemodel/test/cases/dirty_test.rb index 8ffd62fd86..66ed8a350a 100644 --- a/activemodel/test/cases/dirty_test.rb +++ b/activemodel/test/cases/dirty_test.rb @@ -45,10 +45,6 @@ class DirtyTest < ActiveModel::TestCase def reload clear_changes_information end - - def deprecated_reload - reset_changes - end end setup do diff --git a/activemodel/test/cases/validations/callbacks_test.rb b/activemodel/test/cases/validations/callbacks_test.rb index 4b0dd58efb..cc50ffbbef 100644 --- a/activemodel/test/cases/validations/callbacks_test.rb +++ b/activemodel/test/cases/validations/callbacks_test.rb @@ -50,6 +50,14 @@ class DogWithMissingName < Dog validates_presence_of :name end +class DogValidatorWithOnCondition < Dog + before_validation :set_before_validation_marker, on: :create + after_validation :set_after_validation_marker, on: :create + + def set_before_validation_marker; self.history << 'before_validation_marker'; end + def set_after_validation_marker; self.history << 'after_validation_marker' ; end +end + class DogValidatorWithIfCondition < Dog before_validation :set_before_validation_marker1, if: -> { true } before_validation :set_before_validation_marker2, if: -> { false } @@ -73,6 +81,24 @@ class CallbacksWithMethodNamesShouldBeCalled < ActiveModel::TestCase assert_equal ["before_validation_marker1", "after_validation_marker1"], d.history end + def test_on_condition_is_respected_for_validation_with_matching_context + d = DogValidatorWithOnCondition.new + d.valid?(:create) + assert_equal ["before_validation_marker", "after_validation_marker"], d.history + end + + def test_on_condition_is_respected_for_validation_without_matching_context + d = DogValidatorWithOnCondition.new + d.valid?(:save) + assert_equal [], d.history + end + + def test_on_condition_is_respected_for_validation_without_context + d = DogValidatorWithOnCondition.new + d.valid? + assert_equal [], d.history + end + def test_before_validation_and_after_validation_callbacks_should_be_called d = DogWithMethodCallbacks.new d.valid? diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index c677c41727..8875b7ae25 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,15 @@ +* `nil` as a value for a binary column in a query no longer logs as + "<NULL binary data>", and instead logs as just "nil". + + *Sean Griffin* + +* `attribute_will_change!` will no longer cause non-persistable attributes to + be sent to the database. + + Fixes #18407. + + *Sean Griffin* + * Remove support for the `protected_attributes` gem. *Carlos Antonio da Silva*, *Roberto Miranda* diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index d5702accaf..ce7f575150 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -134,7 +134,7 @@ module ActiveRecord # Serialized attributes should always be written in case they've been # changed in place. def keys_for_partial_write - changed + changed & persistable_attribute_names end def _field_changed?(attr, old_value) diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb index aafb990bc1..b263a89d79 100644 --- a/activerecord/lib/active_record/attributes.rb +++ b/activerecord/lib/active_record/attributes.rb @@ -9,6 +9,8 @@ module ActiveRecord class_attribute :user_provided_defaults, instance_accessor: false # :internal: self.user_provided_columns = {} self.user_provided_defaults = {} + + delegate :persistable_attribute_names, to: :class end module ClassMethods # :nodoc: @@ -96,6 +98,10 @@ module ActiveRecord @columns_hash ||= Hash[columns.map { |c| [c.name, c] }] end + def persistable_attribute_names # :nodoc: + @persistable_attribute_names ||= connection.schema_cache.columns_hash(table_name).keys + end + def reset_column_information # :nodoc: super clear_caches_calculated_from_columns @@ -130,6 +136,7 @@ module ActiveRecord @columns_hash = nil @content_columns = nil @default_attributes = nil + @persistable_attribute_names = nil end def raw_default_values diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index 59cdd8e98c..6e631ed9f7 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -285,11 +285,11 @@ module ActiveRecord def insert_fixture(fixture, table_name) columns = schema_cache.columns_hash(table_name) - key_list = [] - value_list = fixture.map do |name, value| - key_list << quote_column_name(name) - quote(value, columns[name]) + binds = fixture.map do |name, value| + [columns[name], value] end + key_list = fixture.keys.map { |name| quote_column_name(name) } + value_list = prepare_binds_for_database(binds).map { |_, value| quote(value) } execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert' end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 143d7d9574..7c1a779577 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -10,6 +10,12 @@ module ActiveRecord return value.quoted_id if value.respond_to?(:quoted_id) if column + ActiveSupport::Deprecation.warn(<<-MSG.squish) + Passing a column to `quote` has been deprecated. It is only used + for type casting, which should be handled elsewhere. See + https://github.com/rails/arel/commit/6160bfbda1d1781c3b08a33ec4955f170e95be11 + for more information. + MSG value = column.cast_type.type_cast_for_database(value) end @@ -90,6 +96,16 @@ module ActiveRecord value.to_s(:db) end + def prepare_binds_for_database(binds) # :nodoc: + binds.map do |column, value| + if column + column_name = column.name + value = column.cast_type.type_cast_for_database(value) + end + [column_name, value] + end + end + private def types_which_need_no_typecasting diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index e52b666296..c941c9f1eb 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -113,7 +113,8 @@ module ActiveRecord class BindCollector < Arel::Collectors::Bind def compile(bvs, conn) - super(bvs.map { |bv| conn.quote(*bv.reverse) }) + casted_binds = conn.prepare_binds_for_database(bvs) + super(casted_binds.map { |_, value| conn.quote(value) }) end end diff --git a/activerecord/lib/active_record/log_subscriber.rb b/activerecord/lib/active_record/log_subscriber.rb index eb64d197f0..a5c7279db9 100644 --- a/activerecord/lib/active_record/log_subscriber.rb +++ b/activerecord/lib/active_record/log_subscriber.rb @@ -22,10 +22,10 @@ module ActiveRecord def render_bind(column, value) if column - if column.binary? + if column.binary? && value # This specifically deals with the PG adapter that casts bytea columns into a Hash. value = value[:value] if value.is_a?(Hash) - value = value ? "<#{value.bytesize} bytes of binary data>" : "<NULL binary data>" + value = "<#{value.bytesize} bytes of binary data>" end [column.name, value] diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index ab3debc03b..dd78814c6a 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -558,8 +558,9 @@ module ActiveRecord end arel = relation.arel - binds = (arel.bind_values + relation.bind_values).dup - binds.map! { |bv| connection.quote(*bv.reverse) } + binds = arel.bind_values + relation.bind_values + binds = connection.prepare_binds_for_database(binds) + binds.map! { |_, value| connection.quote(value) } collect = visitor.accept(arel.ast, Arel::Collectors::Bind.new) collect.substitute_binds(binds).join end diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb index 768a72a947..313e767dcb 100644 --- a/activerecord/lib/active_record/sanitization.rb +++ b/activerecord/lib/active_record/sanitization.rb @@ -3,14 +3,11 @@ module ActiveRecord extend ActiveSupport::Concern module ClassMethods - def quote_value(value, column) #:nodoc: - connection.quote(value, column) - end - # Used to sanitize objects before they're used in an SQL SELECT statement. Delegates to <tt>connection.quote</tt>. def sanitize(object) #:nodoc: connection.quote(object) end + alias_method :quote_value, :sanitize protected @@ -156,7 +153,7 @@ module ActiveRecord # TODO: Deprecate this def quoted_id - self.class.quote_value(id, column_for_attribute(self.class.primary_key)) + self.class.quote_value(@attributes[self.class.primary_key].value_for_database) end end end diff --git a/activerecord/lib/active_record/secure_token.rb b/activerecord/lib/active_record/secure_token.rb index b1a13fe673..be3c3bc847 100644 --- a/activerecord/lib/active_record/secure_token.rb +++ b/activerecord/lib/active_record/secure_token.rb @@ -24,7 +24,7 @@ module ActiveRecord # validates_presence_of can. You're encouraged to add a unique index in the database to deal with # this even more unlikely scenario. def has_secure_token(attribute = :token) - # Load securerandom only when has_secure_key is used. + # Load securerandom only when has_secure_token is used. require 'active_support/core_ext/securerandom' define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token } before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token) } diff --git a/activerecord/lib/active_record/statement_cache.rb b/activerecord/lib/active_record/statement_cache.rb index 192a19f05d..3047a81ec4 100644 --- a/activerecord/lib/active_record/statement_cache.rb +++ b/activerecord/lib/active_record/statement_cache.rb @@ -47,8 +47,8 @@ module ActiveRecord def sql_for(binds, connection) val = @values.dup - binds = binds.dup - @indexes.each { |i| val[i] = connection.quote(*binds.shift.reverse) } + binds = connection.prepare_binds_for_database(binds) + @indexes.each { |i| val[i] = connection.quote(binds.shift.last) } val.join end end diff --git a/activerecord/lib/rails/generators/active_record/migration/templates/create_table_migration.rb b/activerecord/lib/rails/generators/active_record/migration/templates/create_table_migration.rb index fd94a2d038..5b3e57dcf6 100644 --- a/activerecord/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +++ b/activerecord/lib/rails/generators/active_record/migration/templates/create_table_migration.rb @@ -4,6 +4,8 @@ class <%= migration_class_name %> < ActiveRecord::Migration <% attributes.each do |attribute| -%> <% if attribute.password_digest? -%> t.string :password_digest<%= attribute.inject_options %> +<% elsif attribute.token? -%> + t.string :<%= attribute.name %><%= attribute.inject_options %> <% else -%> t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %> <% end -%> @@ -12,6 +14,9 @@ class <%= migration_class_name %> < ActiveRecord::Migration t.timestamps <% end -%> end +<% attributes.select(&:token?).each do |attribute| -%> + add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>, unique: true +<% end -%> <% attributes_with_index.each do |attribute| -%> add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %> <% end -%> diff --git a/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb b/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb index ae9c74fd05..23a377db6a 100644 --- a/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb +++ b/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb @@ -4,6 +4,9 @@ class <%= migration_class_name %> < ActiveRecord::Migration <% attributes.each do |attribute| -%> <%- if attribute.reference? -%> add_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %> + <%- elsif attribute.token? -%> + add_column :<%= table_name %>, :<%= attribute.name %>, :string<%= attribute.inject_options %> + add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>, unique: true <%- else -%> add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %> <%- if attribute.has_index? -%> diff --git a/activerecord/lib/rails/generators/active_record/model/templates/model.rb b/activerecord/lib/rails/generators/active_record/model/templates/model.rb index 539d969fce..55dc65c8ad 100644 --- a/activerecord/lib/rails/generators/active_record/model/templates/model.rb +++ b/activerecord/lib/rails/generators/active_record/model/templates/model.rb @@ -3,6 +3,9 @@ class <%= class_name %> < <%= parent_class_name.classify %> <% attributes.select(&:reference?).each do |attribute| -%> belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %><%= ', required: true' if attribute.required? %> <% end -%> +<% attributes.select(&:token?).each do |attribute| -%> + has_secure_token<% if attribute.name != "token" %> :<%= attribute.name %><% end %> +<% end -%> <% if attributes.any?(&:password_digest?) -%> has_secure_password <% end -%> diff --git a/activerecord/test/cases/adapters/postgresql/quoting_test.rb b/activerecord/test/cases/adapters/postgresql/quoting_test.rb index 9ac0036d66..894cf1ffa2 100644 --- a/activerecord/test/cases/adapters/postgresql/quoting_test.rb +++ b/activerecord/test/cases/adapters/postgresql/quoting_test.rb @@ -34,13 +34,14 @@ module ActiveRecord def test_quote_range range = "1,2]'; SELECT * FROM users; --".."a" - c = PostgreSQLColumn.new(nil, nil, OID::Range.new(Type::Integer.new, :int8range)) - assert_equal "'[1,0]'", @conn.quote(range, c) + type = OID::Range.new(Type::Integer.new, :int8range) + assert_equal "'[1,0]'", @conn.quote(type.type_cast_for_database(range)) end def test_quote_bit_string - c = PostgreSQLColumn.new(nil, 1, OID::Bit.new) - assert_equal nil, @conn.quote("'); SELECT * FROM users; /*\n01\n*/--", c) + value = "'); SELECT * FROM users; /*\n01\n*/--" + type = OID::Bit.new + assert_equal nil, @conn.quote(type.type_cast_for_database(value)) end end end diff --git a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb index df497e761c..274e358e4a 100644 --- a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb @@ -85,9 +85,9 @@ module ActiveRecord def test_quoting_binary_strings value = "hello".encode('ascii-8bit') - column = Column.new(nil, 1, SQLite3String.new) + type = SQLite3String.new - assert_equal "'hello'", @conn.quote(value, column) + assert_equal "'hello'", @conn.quote(type.type_cast_for_database(value)) end end end diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index 5b71bd7e67..ae4a8aab2c 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -708,6 +708,19 @@ class DirtyTest < ActiveRecord::TestCase assert model.first_name_changed? end + test "attribute_will_change! doesn't try to save non-persistable attributes" do + klass = Class.new(ActiveRecord::Base) do + self.table_name = 'people' + attribute :non_persisted_attribute, ActiveRecord::Type::String.new + end + + record = klass.new(first_name: "Sean") + record.non_persisted_attribute_will_change! + + assert record.non_persisted_attribute_changed? + assert record.save + end + private def with_partial_writes(klass, on = true) old = klass.partial_writes? diff --git a/activerecord/test/cases/log_subscriber_test.rb b/activerecord/test/cases/log_subscriber_test.rb index a578e81844..97c0350911 100644 --- a/activerecord/test/cases/log_subscriber_test.rb +++ b/activerecord/test/cases/log_subscriber_test.rb @@ -125,12 +125,5 @@ class LogSubscriberTest < ActiveRecord::TestCase wait assert_match(/<16 bytes of binary data>/, @logger.logged(:debug).join) end - - def test_nil_binary_data_is_logged - binary = Binary.create(data: "") - binary.update_attributes(data: nil) - wait - assert_match(/<NULL binary data>/, @logger.logged(:debug).join) - end end end diff --git a/activesupport/lib/active_support/core_ext/kernel/reporting.rb b/activesupport/lib/active_support/core_ext/kernel/reporting.rb index eb44646848..9189e6d977 100644 --- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb +++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb @@ -1,4 +1,3 @@ -require 'rbconfig' require 'tempfile' module Kernel diff --git a/guides/source/caching_with_rails.md b/guides/source/caching_with_rails.md index 61b991df61..d5477eb72d 100644 --- a/guides/source/caching_with_rails.md +++ b/guides/source/caching_with_rails.md @@ -184,6 +184,10 @@ class ProductsController < ApplicationController end ``` +The second time the same query is run against the database, it's not actually going to hit the database. The first time the result is returned from the query it is stored in the query cache (in memory) and the second time it's pulled from memory. + +However, it's important to note that query caches are created at the start of an action and destroyed at the end of that action and thus persist only for the duration of the action. If you'd like to store query results in a more persistent fashion, you can in Rails by using low level caching. + Cache Stores ------------ diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb index 0d8b3de0eb..63bf8b11ba 100644 --- a/railties/lib/rails/commands/dbconsole.rb +++ b/railties/lib/rails/commands/dbconsole.rb @@ -1,7 +1,6 @@ require 'erb' require 'yaml' require 'optparse' -require 'rbconfig' module Rails class DBConsole diff --git a/railties/lib/rails/commands/runner.rb b/railties/lib/rails/commands/runner.rb index 3a71f8d3f8..86bce9b2fe 100644 --- a/railties/lib/rails/commands/runner.rb +++ b/railties/lib/rails/commands/runner.rb @@ -1,5 +1,4 @@ require 'optparse' -require 'rbconfig' options = { environment: (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development").dup } code_or_file = nil diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 5373121835..e35015f630 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -1,5 +1,4 @@ require 'open-uri' -require 'rbconfig' module Rails module Generators diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb index 77a3dbf9a2..8145a26e22 100644 --- a/railties/lib/rails/generators/generated_attribute.rb +++ b/railties/lib/rails/generators/generated_attribute.rb @@ -142,7 +142,11 @@ module Rails end def password_digest? - name == 'password' && type == :digest + name == 'password' && type == :digest + end + + def token? + type == :token end def inject_options diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb index 413d457d54..57bc220558 100644 --- a/railties/test/generators/migration_generator_test.rb +++ b/railties/test/generators/migration_generator_test.rb @@ -276,6 +276,30 @@ class MigrationGeneratorTest < Rails::Generators::TestCase end end + def test_create_table_migration_with_token_option + run_generator ["create_users", "token:token", "auth_token:token"] + assert_migration "db/migrate/create_users.rb" do |content| + assert_method :change, content do |change| + assert_match(/create_table :users/, change) + assert_match(/ t\.string :token/, change) + assert_match(/ t\.string :auth_token/, change) + assert_match(/add_index :users, :token, unique: true/, change) + assert_match(/add_index :users, :auth_token, unique: true/, change) + end + end + end + + def test_add_migration_with_token_option + migration = "add_token_to_users" + run_generator [migration, "auth_token:token"] + assert_migration "db/migrate/#{migration}.rb" do |content| + assert_method :change, content do |change| + assert_match(/add_column :users, :auth_token, :string/, change) + assert_match(/add_index :users, :auth_token, unique: true/, change) + end + end + end + private def with_singular_table_name diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb index f3b699101f..17a13fbf1f 100644 --- a/railties/test/generators/model_generator_test.rb +++ b/railties/test/generators/model_generator_test.rb @@ -438,6 +438,17 @@ class ModelGeneratorTest < Rails::Generators::TestCase end end + def test_token_option_adds_has_secure_token + run_generator ["user", "token:token", "auth_token:token"] + expected_file = <<-FILE.strip_heredoc + class User < ActiveRecord::Base + has_secure_token + has_secure_token :auth_token + end + FILE + assert_file "app/models/user.rb", expected_file + end + private def assert_generated_fixture(path, parsed_contents) fixture_file = File.new File.expand_path(path, destination_root) |