2010-05-17 20:43:06 +00:00
require 'active_support/time'
2009-06-23 16:12:37 +00:00
module Rails
module Generators
2012-10-07 20:36:39 +00:00
class GeneratedAttribute # :nodoc:
2012-01-14 13:35:57 +00:00
INDEX_OPTIONS = %w( index uniq )
UNIQ_INDEX_OPTIONS = %w( uniq )
2011-12-24 09:38:19 +00:00
attr_accessor :name , :type
attr_reader :attr_options
2012-07-10 21:38:21 +00:00
attr_writer :index_name
2009-06-23 16:12:37 +00:00
2011-12-24 09:38:19 +00:00
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
2012-01-15 12:49:31 +00:00
has_index , type = type , nil if INDEX_OPTIONS . include? ( type )
2011-12-24 09:38:19 +00:00
type , attr_options = * parse_type_and_options ( type )
2012-04-23 00:53:18 +00:00
type = type . to_sym if type
2012-03-03 01:59:23 +00:00
2012-04-23 00:53:18 +00:00
if type && reference? ( type )
2012-10-14 10:03:39 +00:00
references_index = UNIQ_INDEX_OPTIONS . include? ( has_index ) ? { unique : true } : true
2012-04-23 00:53:18 +00:00
attr_options [ :index ] = references_index
2012-04-17 20:46:44 +00:00
end
2012-03-03 01:59:23 +00:00
2011-12-24 09:38:19 +00:00
new ( name , type , has_index , attr_options )
end
2012-04-23 00:53:18 +00:00
def reference? ( type )
[ :references , :belongs_to ] . include? type
end
2011-12-24 09:38:19 +00:00
private
2012-06-25 18:01:31 +00:00
# parse possible attribute options like :limit for string/text/binary/integer, :precision/:scale for decimals or :polymorphic for references/belongs_to
2011-12-24 09:38:19 +00:00
# when declaring options curly brackets should be used
def parse_type_and_options ( type )
case type
2011-12-24 11:53:27 +00:00
when / (string|text|binary|integer) \ {( \ d+) \ } /
2012-10-14 10:03:39 +00:00
return $1 , limit : $2 . to_i
2012-01-30 21:13:04 +00:00
when / decimal \ {( \ d+)[,.-]( \ d+) \ } /
2012-10-14 10:03:39 +00:00
return :decimal , precision : $1 . to_i , scale : $2 . to_i
2014-07-04 21:16:00 +00:00
when / (references|belongs_to) \ {(.+) \ } /
type = $1
provided_options = $2 . split ( / [,.-] / )
options = Hash [ provided_options . map { | opt | [ opt . to_sym , true ] } ]
return type , options
2011-12-24 09:38:19 +00:00
else
return type , { }
end
end
end
def initialize ( name , type = nil , index_type = false , attr_options = { } )
@name = name
2012-04-23 00:53:18 +00:00
@type = type || :string
2012-01-14 13:35:57 +00:00
@has_index = INDEX_OPTIONS . include? ( index_type )
@has_uniq_index = UNIQ_INDEX_OPTIONS . include? ( index_type )
2011-12-24 09:38:19 +00:00
@attr_options = attr_options
2009-06-23 16:12:37 +00:00
end
def field_type
@field_type || = case type
2011-05-16 14:43:05 +00:00
when :integer then :number_field
when :float , :decimal then :text_field
when :time then :time_select
when :datetime , :timestamp then :datetime_select
when :date then :date_select
when :text then :text_area
when :boolean then :check_box
2009-06-23 16:12:37 +00:00
else
:text_field
end
end
def default
@default || = case type
when :integer then 1
when :float then 1 . 5
when :decimal then " 9.99 "
when :datetime , :timestamp , :time then Time . now . to_s ( :db )
when :date then Date . today . to_s ( :db )
2011-03-05 21:25:20 +00:00
when :string then name == " type " ? " " : " MyString "
2009-06-23 16:12:37 +00:00
when :text then " MyText "
when :boolean then false
2009-07-13 14:18:56 +00:00
when :references , :belongs_to then nil
2009-06-23 16:12:37 +00:00
else
" "
end
end
2012-07-18 20:24:21 +00:00
def plural_name
name . sub ( / _id$ / , '' ) . pluralize
end
2014-03-25 14:57:37 +00:00
def singular_name
name . sub ( / _id$ / , '' ) . singularize
end
2009-07-01 16:33:22 +00:00
def human_name
2012-07-18 20:24:21 +00:00
name . humanize
2009-07-01 16:33:22 +00:00
end
2011-12-24 09:38:19 +00:00
def index_name
2012-12-09 20:01:03 +00:00
@index_name || = if polymorphic?
%w( id type ) . map { | t | " #{ name } _ #{ t } " }
2012-06-25 18:01:31 +00:00
else
2012-12-09 20:01:03 +00:00
column_name
2012-06-25 18:01:31 +00:00
end
2011-12-24 09:38:19 +00:00
end
2012-12-09 20:01:03 +00:00
def column_name
@column_name || = reference? ? " #{ name } _id " : name
end
2012-07-18 20:24:21 +00:00
def foreign_key?
! ! ( name =~ / _id$ / )
end
2009-06-23 16:12:37 +00:00
def reference?
2012-04-23 00:53:18 +00:00
self . class . reference? ( type )
2009-06-23 16:12:37 +00:00
end
2011-12-24 09:38:19 +00:00
2012-06-25 18:01:31 +00:00
def polymorphic?
2014-07-04 21:16:00 +00:00
self . attr_options [ :polymorphic ]
end
def required?
self . attr_options [ :required ]
2012-06-25 18:01:31 +00:00
end
2011-08-17 09:16:04 +00:00
def has_index?
@has_index
end
def has_uniq_index?
@has_uniq_index
end
2013-03-13 12:08:56 +00:00
def password_digest?
name == 'password' && type == :digest
end
2011-08-17 09:16:04 +00:00
def inject_options
2014-07-04 21:16:00 +00:00
" " . tap { | s | options_for_migration . each { | k , v | s << " , #{ k } : #{ v . inspect } " } }
2011-08-17 09:16:04 +00:00
end
def inject_index_options
2011-12-24 21:06:25 +00:00
has_uniq_index? ? " , unique: true " : " "
2011-08-17 09:16:04 +00:00
end
2014-07-04 21:16:00 +00:00
def options_for_migration
@attr_options . dup . tap do | options |
if required?
options . delete ( :required )
options [ :null ] = false
end
end
end
2009-06-23 16:12:37 +00:00
end
end
end