-
-
Save clarkdave/5936375 to your computer and use it in GitHub Desktop.
## | |
# This provides `create_enum` and `drop_enum` methods for migrations, which creates | |
# a Postgres ENUM type with the provided values. | |
# | |
# It'll also dump these into the schema.rb to be loaded into another DB (e.g. rake db:test:load) | |
# | |
# In order to reference the new enums as actual types, ActiveRecord needs to know about them, so | |
# make sure they are all represented in the `types` array below | |
# | |
# Then you can reference them in your migrations, e.g. | |
# | |
# create_table :example do | |
# t.state :state | |
# t.location :location | |
# t.method :method | |
# end | |
## | |
types = %w(state location method) | |
module PgEnum | |
# provide the enum DDL methods | |
module PostgreSQLAdapter | |
def create_enum(name, values) | |
values = values.map {|v| "'#{v}'"} | |
execute "CREATE TYPE #{name} AS ENUM (#{values.join(', ')})" | |
end | |
def drop_enum(name) | |
execute "DROP TYPE #{name}" | |
end | |
end | |
# provide support for writing out the 'create_enum' calls in schema.rb | |
module SchemaDumper | |
extend ActiveSupport::Concern | |
included do | |
alias_method_chain :tables, :enums | |
end | |
def tables_with_enums(stream) | |
enums(stream) | |
tables_without_enums(stream) | |
end | |
private | |
def enums(stream) | |
enums = @connection.select_all("SELECT typname FROM pg_type WHERE typtype = 'e'").map{|r| r['typname']} | |
statements = [] | |
enums.each do |enum| | |
values = @connection.select_all( | |
"SELECT e.enumlabel FROM pg_enum e JOIN pg_type t ON e.enumtypid = t.oid WHERE t.typname = '#{enum}'" | |
).map {|v| v['enumlabel'].inspect }.join(', ') | |
statements << " create_enum(#{enum.inspect}, [#{values}])" | |
end | |
stream.puts statements.join("\n") | |
stream.puts | |
end | |
end | |
end | |
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter | |
include PgEnum::PostgreSQLAdapter | |
end | |
module ActiveRecord::ConnectionAdapters | |
include PgEnum::PostgreSQLAdapter | |
end | |
class ActiveRecord::SchemaDumper | |
include PgEnum::SchemaDumper | |
end | |
# make activerecord aware of our enum types | |
types.each do |type| | |
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[type.to_sym] = { name: type } | |
ActiveRecord::ConnectionAdapters::Column.class_eval do | |
define_method("simplified_type_with_#{type}") do |field_type| | |
if field_type == type | |
field_type.to_sym | |
else | |
send("simplified_type_without_#{type}", field_type) | |
end | |
end | |
alias_method_chain :simplified_type, type | |
end | |
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::TableDefinition.class_eval do | |
define_method(type) do |*args| | |
options = args.extract_options! | |
column(args[0], type, options) | |
end | |
end | |
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID.alias_type type, 'text' | |
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.tap do |clazz| | |
clazz::OID.register_type(type, clazz::OID::Identity.new) | |
end | |
end |
works great (rails 4.1.4), had used this before, then lost it, finally found it again!
I'm getting this error, after placing the above code into RAILS_APP/config/initializers/postgis.rb
, under rails 4.2.1:
NameError: undefined method `simplified_type' for class `ActiveRecord::ConnectionAdapters::Column'
any pointers?
I get the same error as @aks:
rake aborted!
NameError: undefined method `simplified_type' for class `ActiveRecord::ConnectionAdapters::Column'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/core_ext/module/aliasing.rb:32:in `alias_method'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/core_ext/module/aliasing.rb:32:in `alias_method_chain'
/Users/eliduke/web/vhosts/sandbox.api.evanta365.com/config/initializers/schema_enums.rb:96:in `block (2 levels) in <top (required)>'
/Users/eliduke/web/vhosts/sandbox.api.evanta365.com/config/initializers/schema_enums.rb:86:in `class_eval'
/Users/eliduke/web/vhosts/sandbox.api.evanta365.com/config/initializers/schema_enums.rb:86:in `block in <top (required)>'
/Users/eliduke/web/vhosts/sandbox.api.evanta365.com/config/initializers/schema_enums.rb:83:in `each'
/Users/eliduke/web/vhosts/sandbox.api.evanta365.com/config/initializers/schema_enums.rb:83:in `<top (required)>'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:268:in `load'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:268:in `block in load'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:240:in `load_dependency'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:268:in `load'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/engine.rb:652:in `block in load_config_initializer'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/notifications.rb:166:in `instrument'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/engine.rb:651:in `load_config_initializer'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/engine.rb:616:in `block (2 levels) in <class:Engine>'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/engine.rb:615:in `each'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/engine.rb:615:in `block in <class:Engine>'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/initializable.rb:30:in `instance_exec'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/initializable.rb:30:in `run'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/initializable.rb:55:in `block in run_initializers'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/initializable.rb:44:in `each'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/initializable.rb:44:in `tsort_each_child'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/initializable.rb:54:in `run_initializers'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/application.rb:352:in `initialize!'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/railtie.rb:194:in `public_send'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/railtie.rb:194:in `method_missing'
/Users/eliduke/web/vhosts/sandbox.api.evanta365.com/config/environment.rb:5:in `<top (required)>'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:274:in `require'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:274:in `block in require'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:240:in `load_dependency'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:274:in `require'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/application.rb:328:in `require_environment!'
/Users/eliduke/.rvm/gems/ruby-2.2.2/gems/railties-4.2.3/lib/rails/application.rb:457:in `block in run_tasks_blocks'
I'm running Rails 4.2.3 and Ruby 2.2.2.
Looks like the simplified_type
method was deprecated back in Rails 3.0.9:
http://apidock.com/rails/v2.3.8/ActiveRecord/ConnectionAdapters/Column/simplified_type
Unfortunately, I don't know enough about how to fix the initializer to still function correctly.
Any thoughts, @clarkdave?
Have a look at this @eliduke,
I had the same issue regarding the simplified_type
method absense. i've perfectioned the implementation for rails 4.2 and improved support for schema.rb
when dumping tables with pg enum columns. I hope this saves someone time:
https://gist.github.com/khamusa/77ada9895db15dbee4e57cb715830a48
Is there a way to make this work in Rails 3.2?