diff --git a/.travis.yml b/.travis.yml index 98e8060..15ca6f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,20 +3,18 @@ before_script: - psql -c 'create database activeuuid_test;' -U postgres rvm: - - 1.9.3 - - 2.0.0 - - 2.1.5 - - 2.2.0 - - rbx-2 - - jruby + - 2.1.10 + - 2.2.6 + - 2.3.3 + - 2.4.0 + - jruby-9.1.5.0 gemfile: - Gemfile - - gemfiles/Gemfile.rails-3-1 - - gemfiles/Gemfile.rails-3-2 - gemfiles/Gemfile.rails-4-0 - gemfiles/Gemfile.rails-4-1 - gemfiles/Gemfile.rails-4-2 + - gemfiles/Gemfile.rails-5-0 - gemfiles/Gemfile.rails-head env: @@ -27,21 +25,33 @@ env: matrix: allow_failures: - gemfile: gemfiles/Gemfile.rails-head + - rvm: jruby-9.1.5.0 + gemfile: gemfiles/Gemfile.rails-4-0 + - rvm: jruby-9.1.5.0 + gemfile: gemfiles/Gemfile.rails-4-1 exclude: - - rvm: 2.2.0 + - rvm: 2.1.10 + gemfile: Gemfile + - rvm: 2.2.5 + gemfile: gemfiles/Gemfile.rails-3-1 + - rvm: 2.3.1 gemfile: gemfiles/Gemfile.rails-3-1 - - rvm: 2.2.0 - gemfile: gemfiles/Gemfile.rails-3-2 - rvm: jruby gemfile: gemfiles/Gemfile.rails-3-1 env: DB=postgresql - - rvm: jruby + - rvm: 2.2.5 gemfile: gemfiles/Gemfile.rails-3-2 - env: DB=postgresql - - rvm: jruby + - rvm: 2.3.1 + gemfile: gemfiles/Gemfile.rails-3-2 + - rvm: 2.1.10 + gemfile: gemfiles/Gemfile.rails-5-0 + - rvm: 2.4.0 gemfile: gemfiles/Gemfile.rails-4-0 - env: DB=postgresql - - rvm: jruby + - rvm: 2.4.0 gemfile: gemfiles/Gemfile.rails-4-1 - env: DB=postgresql - + - rvm: 2.4.0 + gemfile: gemfiles/Gemfile.rails-4-2 + - rvm: jruby-9.1.5.0 + gemfile: Gemfile + - rvm: jruby-9.1.5.0 + gemfile: gemfiles/Gemfile.rails-5-0 diff --git a/Gemfile b/Gemfile index 5562177..9607a9c 100644 --- a/Gemfile +++ b/Gemfile @@ -2,5 +2,5 @@ source "http://rubygems.org" # Specify your gem's dependencies in activeuuid.gemspec gemspec - -gem "activerecord" +gem 'rake', '< 11.0' +gem "activerecord", "~>5.0" diff --git a/README.mkd b/README.mkd index 4448040..da4b52d 100644 --- a/README.mkd +++ b/README.mkd @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/jashmenn/activeuuid.png)](http://travis-ci.org/jashmenn/activeuuid) +[![Build Status](https://travis-ci.org/inbeom/activeuuid.png)](http://travis-ci.org/inbeom/activeuuid) # activeuuid @@ -131,7 +131,7 @@ Add this to your `Gemfile` gem "activeuuid" -Or get the code here: https://github.com/jashmenn/activeuuid +Or get the code here: https://github.com/inbeom/activeuuid ## References @@ -144,7 +144,7 @@ Or get the code here: https://github.com/jashmenn/activeuuid * [7] http://tools.ietf.org/html/rfc4122.html#appendix-C ## Dependencies -Rails ~> 3.1.0 +Rails >= 4.0.0 ## Authors diff --git a/Rakefile b/Rakefile index 5ed955d..3222e8e 100644 --- a/Rakefile +++ b/Rakefile @@ -3,6 +3,13 @@ require "bundler/gem_tasks" require 'rspec/core' require 'rspec/core/rake_task' +module TempFixForRakeLastComment + def last_comment + last_description + end +end +Rake::Application.send :include, TempFixForRakeLastComment + RSpec::Core::RakeTask.new(:spec) task :default => :spec diff --git a/activeuuid.gemspec b/activeuuid.gemspec index 29e7acf..b0f2ae4 100644 --- a/activeuuid.gemspec +++ b/activeuuid.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.require_paths = ["lib"] s.add_development_dependency "rake" - s.add_development_dependency "rspec", "~> 2.99.0" + s.add_development_dependency "rspec", "~> 3.5.0" s.add_development_dependency "rspec-its" s.add_development_dependency "activesupport" s.add_development_dependency "database_cleaner" @@ -35,5 +35,5 @@ Gem::Specification.new do |s| end s.add_runtime_dependency "uuidtools" - s.add_runtime_dependency "activerecord", '>= 3.1' + s.add_runtime_dependency "activerecord", '>= 4.0' end diff --git a/gemfiles/Gemfile.rails-3-2 b/gemfiles/Gemfile.rails-3-2 deleted file mode 100644 index bf6b722..0000000 --- a/gemfiles/Gemfile.rails-3-2 +++ /dev/null @@ -1,5 +0,0 @@ -source "http://rubygems.org" - -gemspec path: '../' - -gem 'activerecord', '~> 3.2.0' diff --git a/gemfiles/Gemfile.rails-4-0 b/gemfiles/Gemfile.rails-4-0 index 1e2870c..274eef5 100644 --- a/gemfiles/Gemfile.rails-4-0 +++ b/gemfiles/Gemfile.rails-4-0 @@ -2,4 +2,5 @@ source "http://rubygems.org" gemspec path: '../' +gem 'mysql2', '~> 0.3.21', '~> 0.3.21', platforms: [:mri, :rbx] gem 'activerecord', '~> 4.0.0' diff --git a/gemfiles/Gemfile.rails-4-1 b/gemfiles/Gemfile.rails-4-1 index 4d380fd..7e7e2d6 100644 --- a/gemfiles/Gemfile.rails-4-1 +++ b/gemfiles/Gemfile.rails-4-1 @@ -2,4 +2,5 @@ source "http://rubygems.org" gemspec path: '../' +gem 'mysql2', '~> 0.3.21', platforms: [:mri, :rbx] gem 'activerecord', '~> 4.1.0' diff --git a/gemfiles/Gemfile.rails-3-1 b/gemfiles/Gemfile.rails-5-0 similarity index 62% rename from gemfiles/Gemfile.rails-3-1 rename to gemfiles/Gemfile.rails-5-0 index 07f13bd..79c197c 100644 --- a/gemfiles/Gemfile.rails-3-1 +++ b/gemfiles/Gemfile.rails-5-0 @@ -2,4 +2,4 @@ source "http://rubygems.org" gemspec path: '../' -gem 'activerecord', '~> 3.1.0' +gem 'activerecord', '~> 5.0.0' diff --git a/lib/activeuuid/patches.rb b/lib/activeuuid/patches.rb index dfb7903..84b1591 100644 --- a/lib/activeuuid/patches.rb +++ b/lib/activeuuid/patches.rb @@ -1,7 +1,8 @@ require 'active_record' require 'active_support/concern' -if ActiveRecord::VERSION::MAJOR == 4 and ActiveRecord::VERSION::MINOR == 2 +if (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 2) || + (ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR == 0) module ActiveRecord module Type class UUID < Binary # :nodoc: @@ -9,6 +10,11 @@ def type :uuid end + def serialize(value) + return if value.nil? + UUIDTools::UUID.serialize(value) + end + def cast_value(value) UUIDTools::UUID.serialize(value) end @@ -24,7 +30,6 @@ class Uuid < Type::Value # :nodoc: def type_cast_from_user(value) UUIDTools::UUID.serialize(value) if value end - alias_method :type_cast_from_database, :type_cast_from_user end end end @@ -47,25 +52,21 @@ def uuid(*column_names) module Column extend ActiveSupport::Concern - included do + def self.prepended(klass) def type_cast_with_uuid(value) return UUIDTools::UUID.serialize(value) if type == :uuid - type_cast_without_uuid(value) + super end def type_cast_code_with_uuid(var_name) return "UUIDTools::UUID.serialize(#{var_name})" if type == :uuid - type_cast_code_without_uuid(var_name) + super end def simplified_type_with_uuid(field_type) return :uuid if field_type == 'binary(16)' || field_type == 'binary(16,0)' - simplified_type_without_uuid(field_type) + super end - - alias_method_chain :type_cast, :uuid - alias_method_chain :type_cast_code, :uuid if ActiveRecord::VERSION::MAJOR < 4 - alias_method_chain :simplified_type, :uuid end end @@ -98,102 +99,116 @@ def simplified_type(field_type) module PostgreSQLColumn extend ActiveSupport::Concern - included do + def self.prepended(klass) def type_cast_with_uuid(value) return UUIDTools::UUID.serialize(value) if type == :uuid - type_cast_without_uuid(value) + super end alias_method_chain :type_cast, :uuid if ActiveRecord::VERSION::MAJOR >= 4 def simplified_type_with_pguuid(field_type) return :uuid if field_type == 'uuid' - simplified_type_without_pguuid(field_type) + super end - - alias_method_chain :simplified_type, :pguuid end end module Quoting extend ActiveSupport::Concern - included do + def self.prepended(klass) def quote_with_visiting(value, column = nil) value = UUIDTools::UUID.serialize(value) if column && column.type == :uuid - quote_without_visiting(value, column) + super end def type_cast_with_visiting(value, column = nil) value = UUIDTools::UUID.serialize(value) if column && column.type == :uuid - type_cast_without_visiting(value, column) + super end def native_database_types_with_uuid @native_database_types ||= native_database_types_without_uuid.merge(uuid: { name: 'binary', limit: 16 }) end - - alias_method_chain :quote, :visiting - alias_method_chain :type_cast, :visiting - alias_method_chain :native_database_types, :uuid end end module PostgreSQLQuoting extend ActiveSupport::Concern - included do + def self.prepended(klass) def quote_with_visiting(value, column = nil) value = UUIDTools::UUID.serialize(value) if column && column.type == :uuid value = value.to_s if value.is_a? UUIDTools::UUID - quote_without_visiting(value, column) + super end def type_cast_with_visiting(value, column = nil, *args) value = UUIDTools::UUID.serialize(value) if column && column.type == :uuid value = value.to_s if value.is_a? UUIDTools::UUID - type_cast_without_visiting(value, column, *args) + super end def native_database_types_with_pguuid @native_database_types ||= native_database_types_without_pguuid.merge(uuid: { name: 'uuid' }) end + end + end - alias_method_chain :quote, :visiting - alias_method_chain :type_cast, :visiting - alias_method_chain :native_database_types, :pguuid + module PostgresqlTypeOverride + def deserialize(value) + UUIDTools::UUID.serialize(value) if value end + + alias_method :cast, :deserialize end - module AbstractAdapter - extend ActiveSupport::Concern + module TypeMapOverride + def initialize_type_map(m) + super - included do - def initialize_type_map_with_uuid(m) - initialize_type_map_without_uuid(m) - register_class_with_limit m, /binary\(16(,0)?\)/i, ::ActiveRecord::Type::UUID - end + register_class_with_limit m, /binary\(16(,0)?\)/i, ::ActiveRecord::Type::UUID + end + end - alias_method_chain :initialize_type_map, :uuid + module MysqlTypeToSqlOverride + def type_to_sql(type, limit = nil, precision = nil, scale = nil, unsigned = nil) + type.to_s == 'uuid' ? 'binary(16)' : super end end - def self.apply! - ActiveRecord::ConnectionAdapters::Table.send :include, Migrations if defined? ActiveRecord::ConnectionAdapters::Table - ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Migrations if defined? ActiveRecord::ConnectionAdapters::TableDefinition - - if ActiveRecord::VERSION::MAJOR == 4 and ActiveRecord::VERSION::MINOR == 2 - ActiveRecord::ConnectionAdapters::Mysql2Adapter.send :include, AbstractAdapter if defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter - ActiveRecord::ConnectionAdapters::SQLite3Adapter.send :include, AbstractAdapter if defined? ActiveRecord::ConnectionAdapters::SQLite3Adapter - else - ActiveRecord::ConnectionAdapters::Column.send :include, Column - ActiveRecord::ConnectionAdapters::PostgreSQLColumn.send :include, PostgreSQLColumn if defined? ActiveRecord::ConnectionAdapters::PostgreSQLColumn + module ConnectionHandling + def establish_connection(_ = nil) + super + + ActiveRecord::ConnectionAdapters::Table.send :include, Migrations if defined? ActiveRecord::ConnectionAdapters::Table + ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Migrations if defined? ActiveRecord::ConnectionAdapters::TableDefinition + + if ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR == 0 + if defined? ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter + ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.prepend TypeMapOverride + ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.prepend MysqlTypeToSqlOverride + end + + ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend TypeMapOverride if defined? ActiveRecord::ConnectionAdapters::SQLite3Adapter + ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Uuid.prepend PostgresqlTypeOverride if defined? ActiveRecord::ConnectionAdapters::PostgreSQLAdapter + elsif ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 2 + ActiveRecord::ConnectionAdapters::Mysql2Adapter.prepend TypeMapOverride if defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter + ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend TypeMapOverride if defined? ActiveRecord::ConnectionAdapters::SQLite3Adapter + else + ActiveRecord::ConnectionAdapters::Column.send :include, Column + ActiveRecord::ConnectionAdapters::PostgreSQLColumn.send :include, PostgreSQLColumn if defined? ActiveRecord::ConnectionAdapters::PostgreSQLColumn + end + + ActiveRecord::ConnectionAdapters::MysqlAdapter.send :include, Quoting if defined? ActiveRecord::ConnectionAdapters::MysqlAdapter + ActiveRecord::ConnectionAdapters::Mysql2Adapter.send :include, Quoting if defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter + ActiveRecord::ConnectionAdapters::SQLite3Adapter.send :include, Quoting if defined? ActiveRecord::ConnectionAdapters::SQLite3Adapter + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send :include, PostgreSQLQuoting if defined? ActiveRecord::ConnectionAdapters::PostgreSQLAdapter end - ArJdbc::MySQL::Column.send :include, MysqlJdbcColumn if defined? ArJdbc::MySQL::Column + end - ActiveRecord::ConnectionAdapters::MysqlAdapter.send :include, Quoting if defined? ActiveRecord::ConnectionAdapters::MysqlAdapter - ActiveRecord::ConnectionAdapters::Mysql2Adapter.send :include, Quoting if defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter - ActiveRecord::ConnectionAdapters::SQLite3Adapter.send :include, Quoting if defined? ActiveRecord::ConnectionAdapters::SQLite3Adapter - ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send :include, PostgreSQLQuoting if defined? ActiveRecord::ConnectionAdapters::PostgreSQLAdapter + def self.apply! + ActiveRecord::Base.singleton_class.prepend ConnectionHandling end end -end +end \ No newline at end of file diff --git a/lib/activeuuid/uuid.rb b/lib/activeuuid/uuid.rb index 48feaa7..e8ede90 100644 --- a/lib/activeuuid/uuid.rb +++ b/lib/activeuuid/uuid.rb @@ -103,7 +103,7 @@ module UUID class_attribute :_uuid_generator, instance_writer: false self._uuid_generator = :random - singleton_class.alias_method_chain :instantiate, :uuid + singleton_class.prepend Instantiation before_create :generate_uuids_if_needed end @@ -128,15 +128,18 @@ def uuids(*attributes) EOS end - def instantiate_with_uuid(record, record_models = nil) + def uuid_columns + @uuid_columns ||= columns.select { |c| c.type == :uuid }.map(&:name) + end + end + + module Instantiation + def instantiate(record, record_models = nil) uuid_columns.each do |uuid_column| record[uuid_column] = UUIDTools::UUID.serialize(record[uuid_column]).to_s if record[uuid_column] end - instantiate_without_uuid(record) - end - def uuid_columns - @uuid_columns ||= columns.select { |c| c.type == :uuid }.map(&:name) + super(record) end end diff --git a/spec/lib/activerecord_spec.rb b/spec/lib/activerecord_spec.rb index 7d74e72..a1e78eb 100644 --- a/spec/lib/activerecord_spec.rb +++ b/spec/lib/activerecord_spec.rb @@ -2,11 +2,17 @@ describe ActiveRecord::Base do context '.connection' do + def table_exists?(connection, table_name) + connection.respond_to?(:data_source_exists?) ? + connection.data_source_exists?(table_name) : + connection.table_exists?(table_name) + end + let!(:connection) { ActiveRecord::Base.connection } let(:table_name) { :test_uuid_field_creation } before do - connection.drop_table(table_name) if connection.table_exists?(table_name) + connection.drop_table(table_name) if table_exists?(connection, table_name) connection.create_table(table_name) end @@ -14,7 +20,7 @@ connection.drop_table table_name end - specify { connection.table_exists?(table_name).should be_truthy } + specify { table_exists?(connection, table_name).should be_truthy } context '#add_column' do let(:column_name) { :uuid_column } @@ -43,7 +49,6 @@ spec_for_adapter do |adapters| adapters.sqlite3 { connection.change_column table_name, column_name, :uuid } adapters.mysql2 { connection.change_column table_name, column_name, :uuid } - # adapters.postgresql { connection.change_column table_name, column_name, :uuid } end end @@ -51,7 +56,7 @@ spec_for_adapter do |adapters| adapters.sqlite3 { column.sql_type.should == 'binary(16)' } adapters.mysql2 { column.sql_type.should == 'binary(16)' } - adapters.postgresql { pending('postgresql can`t change column type to uuid') } + adapters.postgresql { skip('postgresql can`t change column type to uuid') } end end end @@ -105,7 +110,7 @@ describe UuidArticle do let!(:article) { Fabricate :uuid_article } let!(:id) { article.id } - let(:model) { described_class } + let(:model) { UuidArticle } subject { model } context 'model' do @@ -218,4 +223,3 @@ its(:id) { should == uuid } end end - diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2754d95..5def763 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,10 +8,23 @@ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log") ActiveRecord::Base.configurations = YAML::load(File.read(File.dirname(__FILE__) + "/support/database.yml")) -ActiveRecord::Base.establish_connection((ENV["DB"] || "sqlite3").to_sym) require 'activeuuid' +ActiveRecord::Base.establish_connection((ENV["DB"] || "sqlite3").to_sym) + +if ENV['DB'] == 'mysql' + if ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR <= 1 + class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter + NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY" + end + elsif ActiveRecord::VERSION::MAJOR == 3 + class ActiveRecord::ConnectionAdapters::Mysql2Adapter + NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY" + end + end +end + ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + "/support/migrate") ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, STDOUT)