Skip to content

Commit

Permalink
Change SQLite3Adapter to always represent boolean values as integers
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelfranca committed Jan 17, 2019
1 parent 0bef23e commit f59b081
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 109 deletions.
8 changes: 8 additions & 0 deletions activerecord/CHANGELOG.md
@@ -1,3 +1,11 @@
* Deprecate `config.activerecord.sqlite3.represent_boolean_as_integer`.

*Rafael Mendonça França*

* Change `SQLite3Adapter` to always represent boolean values as integers.

*Rafael Mendonça França*

* Remove ability to specify a timestamp name for `#cache_key`.

*Rafael Mendonça França*
Expand Down
Expand Up @@ -30,19 +30,19 @@ def quoted_binary(value)
end

def quoted_true
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? "1" : "'t'"
"1"
end

def unquoted_true
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? 1 : "t"
1
end

def quoted_false
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? "0" : "'f'"
"0"
end

def unquoted_false
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer ? 0 : "f"
0
end

private
Expand Down
Expand Up @@ -76,22 +76,15 @@ class SQLite3Adapter < AbstractAdapter
json: { name: "json" },
}

##
# :singleton-method:
# Indicates whether boolean values are stored in sqlite3 databases as 1
# and 0 or 't' and 'f'. Leaving <tt>ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer</tt>
# set to false is deprecated. SQLite databases have used 't' and 'f' to
# serialize boolean values and must have old data converted to 1 and 0
# (its native boolean serialization) before setting this flag to true.
# Conversion can be accomplished by setting up a rake task which runs
#
# ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
# ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
# for all models and all boolean columns, after which the flag must be set
# to true by adding the following to your <tt>application.rb</tt> file:
#
# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
class_attribute :represent_boolean_as_integer, default: false
def self.represent_boolean_as_integer=(value) # :nodoc:
if value == false
raise "`.represent_boolean_as_integer=` is now always true, so make sure your application can work with it and remove this settings."
end

ActiveSupport::Deprecation.warn(
"`.represent_boolean_as_integer=` is now always true, so setting this is deprecated and will be removed in Rails 6.1."
)
end

class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
private
Expand Down
41 changes: 11 additions & 30 deletions activerecord/lib/active_record/railtie.rb
Expand Up @@ -167,8 +167,18 @@ class Railtie < Rails::Railtie # :nodoc:

initializer "active_record.set_configs" do |app|
ActiveSupport.on_load(:active_record) do
configs = app.config.active_record.dup
configs = app.config.active_record

represent_boolean_as_integer = configs.sqlite3.delete(:represent_boolean_as_integer)

unless represent_boolean_as_integer.nil?
ActiveSupport.on_load(:active_record_sqlite3adapter) do
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
end
end

configs.delete(:sqlite3)

configs.each do |k, v|
send "#{k}=", v
end
Expand Down Expand Up @@ -236,35 +246,6 @@ class Railtie < Rails::Railtie # :nodoc:
end
end

initializer "active_record.check_represent_sqlite3_boolean_as_integer" do
config.after_initialize do
ActiveSupport.on_load(:active_record_sqlite3adapter) do
represent_boolean_as_integer = Rails.application.config.active_record.sqlite3.delete(:represent_boolean_as_integer)
unless represent_boolean_as_integer.nil?
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
end

unless ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
ActiveSupport::Deprecation.warn <<-MSG
Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
boolean values and must have old data converted to 1 and 0 (its native boolean
serialization) before setting this flag to true. Conversion can be accomplished
by setting up a rake task which runs
ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
for all models and all boolean columns, after which the flag must be set to
true by adding the following to your application.rb file:
Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
MSG
end
end
end
end

initializer "active_record.set_filter_attributes" do
ActiveSupport.on_load(:active_record) do
self.filter_attributes += Rails.application.config.filter_parameters
Expand Down
14 changes: 1 addition & 13 deletions activerecord/test/cases/adapters/sqlite3/quoting_test.rb
Expand Up @@ -6,12 +6,8 @@

class SQLite3QuotingTest < ActiveRecord::SQLite3TestCase
def setup
super
@conn = ActiveRecord::Base.connection
@initial_represent_boolean_as_integer = ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
end

def teardown
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = @initial_represent_boolean_as_integer
end

def test_type_cast_binary_encoding_without_logger
Expand All @@ -22,18 +18,10 @@ def test_type_cast_binary_encoding_without_logger
end

def test_type_cast_true
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = false
assert_equal "t", @conn.type_cast(true)

ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
assert_equal 1, @conn.type_cast(true)
end

def test_type_cast_false
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = false
assert_equal "f", @conn.type_cast(false)

ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
assert_equal 0, @conn.type_cast(false)
end

Expand Down
23 changes: 0 additions & 23 deletions guides/source/configuring.md
Expand Up @@ -387,28 +387,6 @@ The PostgreSQL adapter adds one additional configuration option:
highly recommended that you do not enable this in a production environment.
Defaults to `false` in all environments.

The SQLite3Adapter adapter adds one additional configuration option:

* `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
indicates whether boolean values are stored in sqlite3 databases as 1 and 0 or
't' and 'f'. Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
boolean values and must have old data converted to 1 and 0 (its native boolean
serialization) before setting this flag to true. Conversion can be accomplished
by setting up a Rake task which runs

```ruby
ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
```

for all models and all boolean columns, after which the flag must be set to true
by adding the following to your `application.rb` file:

```ruby
Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
```

The schema dumper adds two additional configuration options:

* `ActiveRecord::SchemaDumper.ignore_tables` accepts an array of tables that should _not_ be included in any generated schema file.
Expand Down Expand Up @@ -896,7 +874,6 @@ text/javascript image/svg+xml application/postscript application/x-shockwave-fla
#### With '5.2':

- `config.active_record.cache_versioning`: `true`
- `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`: `true`
- `action_dispatch.use_authenticated_cookie_encryption`: `true`
- `config.active_support.use_authenticated_message_encryption`: `true`
- `config.active_support.use_sha1_digests`: `true`
Expand Down
4 changes: 0 additions & 4 deletions railties/lib/rails/application/configuration.rb
Expand Up @@ -97,10 +97,6 @@ def load_defaults(target_version)

if respond_to?(:active_record)
active_record.cache_versioning = true
# Remove the temporary load hook from SQLite3Adapter when this is removed
ActiveSupport.on_load(:active_record_sqlite3adapter) do
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
end
end

if respond_to?(:action_dispatch)
Expand Down
30 changes: 11 additions & 19 deletions railties/test/application/configuration_test.rb
Expand Up @@ -1941,37 +1941,29 @@ def index
assert_equal({}, Rails.application.config.my_custom_config)
end

test "default SQLite3Adapter.represent_boolean_as_integer for 5.1 is false" do
test "represent_boolean_as_integer is deprecated" do
remove_from_config '.*config\.load_defaults.*\n'

app_file "app/models/post.rb", <<-RUBY
class Post < ActiveRecord::Base
end
app_file "config/initializers/new_framework_defaults_6_0.rb", <<-RUBY
Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
RUBY

app "development"
force_lazy_load_hooks { Post }

assert_not ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
end

test "default SQLite3Adapter.represent_boolean_as_integer for new installs is true" do
app_file "app/models/post.rb", <<-RUBY
class Post < ActiveRecord::Base
end
RUBY

app "development"
force_lazy_load_hooks { Post }

assert ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
assert_deprecated do
force_lazy_load_hooks { Post }
end
end

test "represent_boolean_as_integer should be able to set via config.active_record.sqlite3.represent_boolean_as_integer" do
test "represent_boolean_as_integer raises when the value is false" do
remove_from_config '.*config\.load_defaults.*\n'

app_file "config/initializers/new_framework_defaults_6_0.rb", <<-RUBY
Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = false
RUBY

app_file "app/models/post.rb", <<-RUBY
Expand All @@ -1980,9 +1972,9 @@ class Post < ActiveRecord::Base
RUBY

app "development"
force_lazy_load_hooks { Post }

assert ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
assert_raises(RuntimeError) do
force_lazy_load_hooks { Post }
end
end

test "config_for containing ERB tags should evaluate" do
Expand Down

0 comments on commit f59b081

Please sign in to comment.