Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PostgreSQL column type 'citext' not yet supported #2177

Closed
odigity opened this issue Jan 25, 2015 · 8 comments · Fixed by #3413
Closed

PostgreSQL column type 'citext' not yet supported #2177

odigity opened this issue Jan 25, 2015 · 8 comments · Fixed by #3413

Comments

@odigity
Copy link

odigity commented Jan 25, 2015

Rails 4.2 adding support for the PostreSQL column type 'citext':

http://www.raysrashmi.com/2014/09/02/new-features-in-rails-4-2

I just started using it, but as a consequence, my rails_admin views no longer work for models that have a citext column:

RuntimeError (Unsupported field datatype: citext):
  rails_admin (0.6.6) lib/rails_admin/config/fields/types.rb:12:in `load'
  rails_admin (0.6.6) lib/rails_admin/config/fields.rb:15:in `block in <module:Fields>'
  rails_admin (0.6.6) lib/rails_admin/config/fields.rb:54:in `call'
  rails_admin (0.6.6) lib/rails_admin/config/fields.rb:54:in `block (2 levels) in factory'
  rails_admin (0.6.6) lib/rails_admin/config/fields.rb:54:in `each'
  rails_admin (0.6.6) lib/rails_admin/config/fields.rb:54:in `detect'
  rails_admin (0.6.6) lib/rails_admin/config/fields.rb:54:in `block in factory'
  rails_admin (0.6.6) lib/rails_admin/config/fields.rb:50:in `each'
  rails_admin (0.6.6) lib/rails_admin/config/fields.rb:50:in `factory'
  rails_admin (0.6.6) lib/rails_admin/config/has_fields.rb:130:in `_fields'
  rails_admin (0.6.6) lib/rails_admin/config/has_fields.rb:133:in `_fields'
  rails_admin (0.6.6) lib/rails_admin/config/has_fields.rb:108:in `all_fields'
  rails_admin (0.6.6) lib/rails_admin/config/has_fields.rb:83:in `fields'
  rails_admin (0.6.6) app/controllers/rails_admin/main_controller.rb:121:in `get_collection'
  rails_admin (0.6.6) app/controllers/rails_admin/main_controller.rb:37:in `list_entries'
  rails_admin (0.6.6) lib/rails_admin/config/actions/index.rb:30:in `block (2 levels) in <class:Index>'
  (eval):8:in `instance_eval'
  (eval):8:in `index'
  actionpack (4.2.0) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
  actionpack (4.2.0) lib/abstract_controller/base.rb:198:in `process_action'
  actionpack (4.2.0) lib/action_controller/metal/rendering.rb:10:in `process_action'
  actionpack (4.2.0) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
  activesupport (4.2.0) lib/active_support/callbacks.rb:117:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:117:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `block in halting'
  activesupport (4.2.0) lib/active_support/callbacks.rb:151:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:151:in `block in halting_and_conditional'
  activesupport (4.2.0) lib/active_support/callbacks.rb:151:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:151:in `block in halting_and_conditional'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `block in halting'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `block in halting'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `block in halting'
  activesupport (4.2.0) lib/active_support/callbacks.rb:234:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:234:in `block in halting'
  activesupport (4.2.0) lib/active_support/callbacks.rb:234:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:234:in `block in halting'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `block in halting'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `block in halting'
  activesupport (4.2.0) lib/active_support/callbacks.rb:234:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:234:in `block in halting'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:169:in `block in halting'
  activesupport (4.2.0) lib/active_support/callbacks.rb:92:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:92:in `_run_callbacks'
  activesupport (4.2.0) lib/active_support/callbacks.rb:734:in `_run_process_action_callbacks'
  activesupport (4.2.0) lib/active_support/callbacks.rb:81:in `run_callbacks'
  actionpack (4.2.0) lib/abstract_controller/callbacks.rb:19:in `process_action'
  actionpack (4.2.0) lib/action_controller/metal/rescue.rb:29:in `process_action'
  actionpack (4.2.0) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
  activesupport (4.2.0) lib/active_support/notifications.rb:164:in `block in instrument'
  activesupport (4.2.0) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  activesupport (4.2.0) lib/active_support/notifications.rb:164:in `instrument'
  actionpack (4.2.0) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
  actionpack (4.2.0) lib/action_controller/metal/params_wrapper.rb:250:in `process_action'
  activerecord (4.2.0) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
  actionpack (4.2.0) lib/abstract_controller/base.rb:137:in `process'
  actionview (4.2.0) lib/action_view/rendering.rb:30:in `process'
  actionpack (4.2.0) lib/action_controller/metal.rb:195:in `dispatch'
  actionpack (4.2.0) lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'
  actionpack (4.2.0) lib/action_controller/metal.rb:236:in `block in action'
  actionpack (4.2.0) lib/action_dispatch/routing/route_set.rb:73:in `call'
  actionpack (4.2.0) lib/action_dispatch/routing/route_set.rb:73:in `dispatch'
  actionpack (4.2.0) lib/action_dispatch/routing/route_set.rb:42:in `serve'
  actionpack (4.2.0) lib/action_dispatch/journey/router.rb:43:in `block in serve'
  actionpack (4.2.0) lib/action_dispatch/journey/router.rb:30:in `each'
  actionpack (4.2.0) lib/action_dispatch/journey/router.rb:30:in `serve'
  actionpack (4.2.0) lib/action_dispatch/routing/route_set.rb:802:in `call'
  railties (4.2.0) lib/rails/engine.rb:518:in `call'
  railties (4.2.0) lib/rails/railtie.rb:194:in `public_send'
  railties (4.2.0) lib/rails/railtie.rb:194:in `method_missing'
  actionpack (4.2.0) lib/action_dispatch/routing/mapper.rb:51:in `serve'
  actionpack (4.2.0) lib/action_dispatch/journey/router.rb:43:in `block in serve'
  actionpack (4.2.0) lib/action_dispatch/journey/router.rb:30:in `each'
  actionpack (4.2.0) lib/action_dispatch/journey/router.rb:30:in `serve'
  actionpack (4.2.0) lib/action_dispatch/routing/route_set.rb:802:in `call'
  rack-pjax (0.8.0) lib/rack/pjax.rb:12:in `call'
  rack (1.6.0) lib/rack/etag.rb:24:in `call'
  rack (1.6.0) lib/rack/conditionalget.rb:25:in `call'
  rack (1.6.0) lib/rack/head.rb:13:in `call'
  remotipart (1.2.1) lib/remotipart/middleware.rb:27:in `call'
  actionpack (4.2.0) lib/action_dispatch/middleware/params_parser.rb:27:in `call'
  actionpack (4.2.0) lib/action_dispatch/middleware/flash.rb:260:in `call'
  rack (1.6.0) lib/rack/session/abstract/id.rb:225:in `context'
  rack (1.6.0) lib/rack/session/abstract/id.rb:220:in `call'
  actionpack (4.2.0) lib/action_dispatch/middleware/cookies.rb:560:in `call'
  activerecord (4.2.0) lib/active_record/query_cache.rb:36:in `call'
  activerecord (4.2.0) lib/active_record/connection_adapters/abstract/connection_pool.rb:647:in `call'
  actionpack (4.2.0) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:88:in `call'
  activesupport (4.2.0) lib/active_support/callbacks.rb:88:in `_run_callbacks'
  activesupport (4.2.0) lib/active_support/callbacks.rb:734:in `_run_call_callbacks'
  activesupport (4.2.0) lib/active_support/callbacks.rb:81:in `run_callbacks'
  actionpack (4.2.0) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
  actionpack (4.2.0) lib/action_dispatch/middleware/remote_ip.rb:78:in `call'
  actionpack (4.2.0) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
  actionpack (4.2.0) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
  railties (4.2.0) lib/rails/rack/logger.rb:38:in `call_app'
  railties (4.2.0) lib/rails/rack/logger.rb:20:in `block in call'
  activesupport (4.2.0) lib/active_support/tagged_logging.rb:68:in `block in tagged'
  activesupport (4.2.0) lib/active_support/tagged_logging.rb:26:in `tagged'
  activesupport (4.2.0) lib/active_support/tagged_logging.rb:68:in `tagged'
  railties (4.2.0) lib/rails/rack/logger.rb:20:in `call'
  actionpack (4.2.0) lib/action_dispatch/middleware/request_id.rb:21:in `call'
  rack (1.6.0) lib/rack/methodoverride.rb:22:in `call'
  rack (1.6.0) lib/rack/runtime.rb:18:in `call'
  activesupport (4.2.0) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
  actionpack (4.2.0) lib/action_dispatch/middleware/static.rb:113:in `call'
  rack (1.6.0) lib/rack/sendfile.rb:113:in `call'
  railties (4.2.0) lib/rails/engine.rb:518:in `call'
  railties (4.2.0) lib/rails/application.rb:164:in `call'
  puma (2.10.2) lib/puma/configuration.rb:74:in `call'
  puma (2.10.2) lib/puma/server.rb:492:in `handle_request'
  puma (2.10.2) lib/puma/server.rb:363:in `process_client'
  puma (2.10.2) lib/puma/server.rb:254:in `block in run'
  puma (2.10.2) lib/puma/thread_pool.rb:101:in `call'
  puma (2.10.2) lib/puma/thread_pool.rb:101:in `block in spawn_thread'
@soupmatt
Copy link
Contributor

I worked around this by adding a file called lib/rails_admin/config/fields/types/citext.rb with the following contents:

require 'rails_admin/config/fields/base'

module RailsAdmin::Config::Fields::Types
  class Citext < RailsAdmin::Config::Fields::Types::String
    RailsAdmin::Config::Fields::Types::register(:citext, self)
  end
end

and then requiring that file at the top of config/initializers/rails_admin.rb

@odigity
Copy link
Author

odigity commented Feb 18, 2015

Thanks! Will try that soon.

@wlipa
Copy link

wlipa commented Apr 10, 2015

@soupmatt That config works pretty well, but the columns aren't searchable because the statement builder doesn't know about :citext. Any way to fix that?

@stevenharman
Copy link

@wlipa I was able to work around this like so:

# lib/rails_admin/config/fields/types/citext.rb
require 'rails_admin/config/fields/base'

module RailsAdmin
  module Config
    module Fields
      module Types
        class Citext < RailsAdmin::Config::Fields::Types::String
          RailsAdmin::Config::Fields::Types::register(:citext, self)
        end
      end
    end
  end

  # Allow for searching/filtering of `citext` fields.
  module Adapters
    module ActiveRecord
      module CitextStatement
        private

        def build_statement_for_type
          if @type == :citext
            return build_statement_for_string_or_text
          else
            super
          end
        end
      end

      class StatementBuilder < RailsAdmin::AbstractModel::StatementBuilder
        prepend CitextStatement
      end
    end
  end
end

And then in your /config/initializers/rails_admin.rb

require Rails.root.join('lib/rails_admin/config/fields/types/citext')

I'd be happy to submit a PR with a proper fix, but I'm not sure how to handle Postgres-specific data types. Any guidance on that?

@sfcgeorge
Copy link

I just ran into this too, citext is pretty useful for saving usernames with desired capitalisation but allowing to login with any capitalisation. @stevenharman's fix worked perfectly for me, both to edit and search. It's fairly easy to stick in a lib monkeypatch, but it could easily be gemified too if it doesn't belong in core.

@sfcgeorge
Copy link

An additional monkeypatch is needed to make the Filters work (without it you get no operator options).

// app/assets/javascripts/rails_admin/custom/ui.js

$(document).on("rails_admin.dom_ready", function() {
  if (!$.filters.old_append) {
    $.filters.old_append = $.filters.append;

    $.filters.append = function(options) {
      options = options || {};
      options.type = options.type == "citext" ? "string" : options.type;

      return $.filters.old_append(options);
    };
  }
});

@tosbourn
Copy link
Contributor

Would there be anything philosophical stopping the above fixes making their way into core? Happy to attempt a PR for this (just ran into this issue).

I feel like Rails Admin wouldn't have an issue supporting what Rails supports out of the box.

@mshibuya
Copy link
Member

There's no specific reason, a PR with corresponding tests will be happily accepted.

jdufresne added a commit to jdufresne/rails_admin that referenced this issue Nov 14, 2021
jdufresne added a commit to jdufresne/rails_admin that referenced this issue Nov 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants