lib/rails/generators/generated_attribute.rb in railties-3.2.22.5 vs lib/rails/generators/generated_attribute.rb in railties-4.0.0.beta1

- old
+ new

@@ -1,49 +1,64 @@ require 'active_support/time' -require 'active_support/core_ext/object/inclusion' -require 'active_support/core_ext/object/blank' module Rails module Generators - class GeneratedAttribute + class GeneratedAttribute # :nodoc: + INDEX_OPTIONS = %w(index uniq) + UNIQ_INDEX_OPTIONS = %w(uniq) + attr_accessor :name, :type attr_reader :attr_options + attr_writer :index_name class << self def parse(column_definition) name, type, has_index = column_definition.split(':') # if user provided "name:index" instead of "name:string:index" # type should be set blank so GeneratedAttribute's constructor # could set it to :string - has_index, type = type, nil if %w(index uniq).include?(type) + has_index, type = type, nil if INDEX_OPTIONS.include?(type) type, attr_options = *parse_type_and_options(type) + type = type.to_sym if type + + if type && reference?(type) + references_index = UNIQ_INDEX_OPTIONS.include?(has_index) ? { unique: true } : true + attr_options[:index] = references_index + end + new(name, type, has_index, attr_options) end + def reference?(type) + [:references, :belongs_to].include? type + end + private - # parse possible attribute options like :limit for string/text/binary/integer or :precision/:scale for decimals + # parse possible attribute options like :limit for string/text/binary/integer, :precision/:scale for decimals or :polymorphic for references/belongs_to # when declaring options curly brackets should be used def parse_type_and_options(type) case type when /(string|text|binary|integer)\{(\d+)\}/ - return $1, :limit => $2.to_i - when /decimal\{(\d+)(,|\.|\-)(\d+)\}/ - return :decimal, :precision => $1.to_i, :scale => $3.to_i + return $1, limit: $2.to_i + when /decimal\{(\d+)[,.-](\d+)\}/ + return :decimal, precision: $1.to_i, scale: $2.to_i + when /(references|belongs_to)\{polymorphic\}/ + return $1, polymorphic: true else return type, {} end end end def initialize(name, type=nil, index_type=false, attr_options={}) @name = name - @type = (type.presence || :string).to_sym - @has_index = %w(index uniq).include?(index_type) - @has_uniq_index = %w(uniq).include?(index_type) + @type = type || :string + @has_index = INDEX_OPTIONS.include?(index_type) + @has_uniq_index = UNIQ_INDEX_OPTIONS.include?(index_type) @attr_options = attr_options end def field_type @field_type ||= case type @@ -73,35 +88,55 @@ else "" end end + def plural_name + name.sub(/_id$/, '').pluralize + end + def human_name - name.to_s.humanize + name.humanize end def index_name - reference? ? "#{name}_id" : name + @index_name ||= if polymorphic? + %w(id type).map { |t| "#{name}_#{t}" } + else + column_name + end end + def column_name + @column_name ||= reference? ? "#{name}_id" : name + end + + def foreign_key? + !!(name =~ /_id$/) + end + def reference? - self.type.in?([:references, :belongs_to]) + self.class.reference?(type) end + def polymorphic? + self.attr_options.has_key?(:polymorphic) + end + def has_index? @has_index end def has_uniq_index? @has_uniq_index end def inject_options - "".tap { |s| @attr_options.each { |k,v| s << ", :#{k} => #{v.inspect}" } } + "".tap { |s| @attr_options.each { |k,v| s << ", #{k}: #{v.inspect}" } } end def inject_index_options - has_uniq_index? ? ", :unique => true" : '' + has_uniq_index? ? ", unique: true" : "" end end end end