Module: Mongoid::Symbolize::ClassMethods

Defined in:
lib/symbolize/mongoid.rb

Overview

Symbolize Mongoid attributes. Add:

symbolize :attr_name

to your model class, to make an attribute return symbols instead of string values. Setting such an attribute will accept symbols as well as strings.

There’s no need for ‘field :attr_name’, symbolize will do it.

Example:

class User
  include Mongoid::Document
  symbolize :gender, :in => [:female, :male]
  symbolize :so, :in => {
    :linux   => "Linux",
    :mac     => "Mac OS X"
  }
  symbolize :gui, , :in => [:gnome, :kde, :xfce], :allow_blank => true
  symbolize :browser, :in => [:firefox, :opera], :i18n => false
end

It will automattically lookup for i18n:

models:

symbolizes:
  user:
    gender:
      female: Girl
      male: Boy

You can skip i18n lookup with :i18n => false

symbolize :gender, :in => [:female, :male], :i18n => false

Its possible to use boolean fields also.

symbolize :switch, :in => [true, false]

...
  switch:
    "true": On
    "false": Off
    "nil": Unknown

Instance Method Summary collapse

Instance Method Details

#symbolize(*attr_names) ⇒ Object

Specifies that values of the given attributes should be returned as symbols. The table column should be created of type string.



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/symbolize/mongoid.rb', line 53

def symbolize(*attr_names) # rubocop:disable Metrics/AbcSize
  configuration = attr_names.extract_options!
  configuration.assert_valid_keys(:in, :within, :i18n, :scopes, :methods, :capitalize, :validate, :default, :allow_blank, :allow_nil, :type)

  enum           = configuration[:in] || configuration[:within]
  i18n           = configuration[:i18n]
  i18n           = enum && !enum.is_a?(Hash) if i18n.nil?
  scopes         = configuration[:scopes]
  methods        = configuration[:methods]
  capitalize     = configuration[:capitalize]
  validation     = configuration[:validate] != false
  default_option = configuration[:default]

  field_type     = configuration[:type] || Symbol
  enum           = [true, false] if [Boolean, ::Boolean].include?(field_type)

  attr_names.each do |attr_name|
    attr_name_str = attr_name.to_s

    if enum
      enum_hash = \
      if enum.is_a?(Hash)
        enum
      else
        enum.each_with_object({}) do |e, a|
          a.store(e.respond_to?(:to_sym) ? e.to_sym : e,
                    capitalize ? e.to_s.capitalize : e.to_s)
        end
      end

      #
      # Builds Mongoid 'field :name, type: type, :default'
      #
      { :type => field_type }.tap do |field_opts|
        field_opts.merge!(:default => default_option) if default_option
        field attr_name, field_opts
      end

      values_name = attr_name_str + '_values'
      values_const_name = values_name.upcase

      # Get the values of :in
      const_set values_const_name, enum_hash unless const_defined? values_const_name

      [
        'get_' + values_name, attr_name_str + '_enum'
      ].each do |enum_method_name|

        define_singleton_method(enum_method_name) do
          if i18n
            enum_hash.each_key.map do |symbol|
              [i18n_translation_for(attr_name_str, symbol), symbol]
            end
          else
            enum_hash.map(&:reverse)
          end
        end
      end

      if methods
        enum_hash.each_key do |key|
          define_method("#{key}?") do
            send(attr_name_str) == key.to_sym
          end
        end
      end

      if scopes
        if scopes == :shallow
          enum_hash.each_key do |name|
            next unless name.respond_to?(:to_sym)
            scope name, -> { where(attr_name_str => name) }
          end
        else # scoped scopes
          scope attr_name_str, ->(val) { where(attr_name_str => val) }
        end
      end

      if validation
        validates(*attr_names, configuration.slice(:allow_nil, :allow_blank).merge(:inclusion => { :in => enum_hash.keys }))
      end
    end

    #
    # Creates <attribute>_text helper, human text for attribute.
    #
    define_method(attr_name_str + '_text') do
      if i18n
        read_i18n_attribute(attr_name_str)
      else
        attr_value = send(attr_name_str)
        if enum
          enum_hash[attr_value]
        else
          attr_value.to_s
        end
      end
    end

    def i18n_translation_for(attr_name, attr_value)
      I18n.translate("mongoid.symbolizes.#{model_name.to_s.underscore}.#{attr_name}.#{attr_value}")
    end
  end
end