Skip to content

Commit

Permalink
changed square brackets to curly ones in column type definition, also…
Browse files Browse the repository at this point in the history
… added ability to specify (uniq|unique) in index definition, so now it's possible to write 'discount:decimal{5,2}:uniq' or 'user_uuid:uniq' while generating new model/migration
  • Loading branch information
Dmitrii Samoilov committed Dec 23, 2011
1 parent dc6c674 commit 51eded9
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 31 deletions.
Expand Up @@ -4,7 +4,7 @@ def change
<% attributes.each do |attribute| -%>
add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %>
<%- if attribute.has_index? -%>
add_index :<%= table_name %>, :<%= attribute.name %>
add_index :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_index_options %>
<%- end %>
<%- end -%>
end
Expand All @@ -14,7 +14,7 @@ def up
<%- if migration_action -%>
<%= migration_action %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'add' %>, :<%= attribute.type %><%= attribute.inject_options %><% end %>
<% if attribute.has_index? && migration_action == 'add' %>
add_index :<%= table_name %>, :<%= attribute.name %>
add_index :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_index_options %>
<% end -%>
<%- end -%>
<%- end -%>
Expand Down
Expand Up @@ -10,11 +10,11 @@ def change
end
<% if options[:indexes] -%>
<% attributes.select {|attr| attr.reference? }.each do |attribute| -%>
add_index :<%= table_name %>, :<%= attribute.name %>_id
add_index :<%= table_name %>, :<%= attribute.name %>_id<%= attribute.inject_index_options %>
<% end -%>
<% end -%>
<% attributes.select {|attr| attr.has_index? }.each do |attribute| -%>
add_index :<%= table_name %>, :<%= attribute.name %>
add_index :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_index_options %>
<% end -%>
end
end
37 changes: 30 additions & 7 deletions railties/lib/rails/generators/generated_attribute.rb
Expand Up @@ -6,9 +6,8 @@ module Generators
class GeneratedAttribute
attr_accessor :name, :type, :has_index, :attr_options

def initialize(name, type, has_index = false)
type = :string if type.blank?
@name, @type, @attr_options, @has_index = name, *parse_type_and_options(type), has_index.eql?("index")
def initialize(column_definition)
parse column_definition
end

def field_type
Expand Down Expand Up @@ -53,22 +52,46 @@ def has_index?
@has_index
end

def has_uniq_index?
@has_uniq_index
end

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
if type =~ /index|uniq|unique/i
has_index = type
type = nil
end
type = :string if type.blank?

@name = name
@type, @attr_options = *parse_type_and_options(type)
@has_index = ['index','uniq','unique'].include?(has_index)
@has_uniq_index = ['uniq','unique'].include?(has_index)
end

# parse possible attribute options like :limit for string/text/binary/integer or :precision/:scale for decimals
# when declaring options square brackets should be used since bash interpreter fails when parentheses are used
# when declaring options curly brackets should be used
def parse_type_and_options(type)
attribute_options = case type
when /(string|text|binary|integer)\[(\d+)\]/
when /(string|text|binary|integer){(\d+)}/
{:limit => $2.to_i}
when /decimal\[(\d+)\.(\d+)\]/
when /decimal{(\d+),(\d+)}/
{:precision => $1.to_i, :scale => $2.to_i}
else; {}
end
[type.to_s.gsub(/\[.*\]/,'').to_sym, attribute_options]
[type.to_s.gsub(/{.*}/,'').to_sym, attribute_options]
end

def inject_options
@attr_options.blank? ? '' : ", #{@attr_options.to_s.gsub(/[{}]/, '')}"
end

def inject_index_options
has_uniq_index? ? ", :unique => true" : ''
end
end
end
end
11 changes: 2 additions & 9 deletions railties/lib/rails/generators/named_base.rb
Expand Up @@ -153,15 +153,8 @@ def assign_names!(name) #:nodoc:

# Convert attributes array into GeneratedAttribute objects.
def parse_attributes! #:nodoc:
self.attributes = (attributes || []).map do |key_value|
name, type, has_index = key_value.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
if type.eql?("index")
has_index = type
type = nil
end
Rails::Generators::GeneratedAttribute.new(name, type, has_index)
self.attributes = (attributes || []).map do |attr|
Rails::Generators::GeneratedAttribute.new(attr)
end
end

Expand Down
2 changes: 1 addition & 1 deletion railties/lib/rails/generators/test_case.rb
Expand Up @@ -219,7 +219,7 @@ def generator(args=self.default_arguments, options={}, config={})
# create_generated_attribute(:string, 'name')
#
def create_generated_attribute(attribute_type, name = 'test')
Rails::Generators::GeneratedAttribute.new(name, attribute_type.to_s)
Rails::Generators::GeneratedAttribute.new([name, attribute_type.to_s].join(':'))
end

protected
Expand Down
2 changes: 1 addition & 1 deletion railties/test/generators/generated_attribute_test.rb
Expand Up @@ -69,7 +69,7 @@ def test_default_value_is_string
end

def test_default_value_for_type
att = Rails::Generators::GeneratedAttribute.new("type", "string")
att = Rails::Generators::GeneratedAttribute.new("type:string")
assert_equal("", att.default)
end

Expand Down
16 changes: 12 additions & 4 deletions railties/test/generators/migration_generator_test.rb
Expand Up @@ -60,55 +60,63 @@ def test_remove_migration_with_attributes

def test_add_migration_with_attributes_and_indices
migration = "add_title_with_index_and_body_to_posts"
run_generator [migration, "title:string:index", "body:text"]
run_generator [migration, "title:string:index", "body:text", "user_id:integer:unique"]

assert_migration "db/migrate/#{migration}.rb" do |content|
assert_method :change, content do |up|
assert_match(/add_column :posts, :title, :string/, up)
assert_match(/add_column :posts, :body, :text/, up)
assert_match(/add_column :posts, :user_id, :integer/, up)
end
assert_match(/add_index :posts, :title/, content)
assert_match(/add_index :posts, :user_id, :unique => true/, content)
end
end

def test_add_migration_with_attributes_and_wrong_index_declaration
migration = "add_title_and_content_to_books"
run_generator [migration, "title:string:inex", "content:text"]
run_generator [migration, "title:string:inex", "content:text", "user_id:integer:unik"]

assert_migration "db/migrate/#{migration}.rb" do |content|
assert_method :change, content do |up|
assert_match(/add_column :books, :title, :string/, up)
assert_match(/add_column :books, :content, :text/, up)
assert_match(/add_column :books, :user_id, :integer/, up)
end
assert_not_match(/add_index :books, :title/, content)
assert_not_match(/add_index :books, :user_id/, content)
end
end

def test_add_migration_with_attributes_without_type_and_index
migration = "add_title_with_index_and_body_to_posts"
run_generator [migration, "title:index", "body:text"]
run_generator [migration, "title:index", "body:text", "user_uuid:uniq"]

assert_migration "db/migrate/#{migration}.rb" do |content|
assert_method :change, content do |up|
assert_match(/add_column :posts, :title, :string/, up)
assert_match(/add_column :posts, :body, :text/, up)
assert_match(/add_column :posts, :user_uuid, :string/, up)
end
assert_match(/add_index :posts, :title/, content)
assert_match(/add_index :posts, :user_uuid, :unique => true/, content)
end
end

def test_add_migration_with_attributes_index_declaration_and_attribute_options
migration = "add_title_and_content_to_books"
run_generator [migration, "title:string[40]:index", "content:string[255]", "price:decimal[5.2]:index"]
run_generator [migration, "title:string{40}:index", "content:string{255}", "price:decimal{5,2}:index", "discount:decimal{3,2}:uniq"]

assert_migration "db/migrate/#{migration}.rb" do |content|
assert_method :change, content do |up|
assert_match(/add_column :books, :title, :string, :limit=>40/, up)
assert_match(/add_column :books, :content, :string, :limit=>255/, up)
assert_match(/add_column :books, :price, :decimal, :precision=>5, :scale=>2/, up)
assert_match(/add_column :books, :discount, :decimal, :precision=>3, :scale=>2/, up)
end
assert_match(/add_index :books, :title/, content)
assert_match(/add_index :books, :price/, content)
assert_match(/add_index :books, :discount, :unique => true/, content)
end
end

Expand Down
17 changes: 12 additions & 5 deletions railties/test/generators/model_generator_test.rb
Expand Up @@ -114,31 +114,37 @@ def test_migration_with_attributes
end

def test_migration_with_attributes_and_with_index
run_generator ["product", "name:string:index", "supplier_id:integer:index"]
run_generator ["product", "name:string:index", "supplier_id:integer:index", "user_id:integer:uniq", "order_id:unique"]

assert_migration "db/migrate/create_products.rb" do |m|
assert_method :change, m do |up|
assert_match(/create_table :products/, up)
assert_match(/t\.string :name/, up)
assert_match(/t\.integer :supplier_id/, up)

assert_match(/t\.integer :user_id/, up)
assert_match(/t\.string :order_id/, up)

assert_match(/add_index :products, :name/, up)
assert_match(/add_index :products, :supplier_id/, up)
assert_match(/add_index :products, :user_id, :unique => true/, up)
assert_match(/add_index :products, :order_id, :unique => true/, up)
end
end
end

def test_migration_with_attributes_and_with_wrong_index_declaration
run_generator ["product", "name:string", "supplier_id:integer:inex"]
run_generator ["product", "name:string", "supplier_id:integer:inex", "user_id:integer:unqu"]

assert_migration "db/migrate/create_products.rb" do |m|
assert_method :change, m do |up|
assert_match(/create_table :products/, up)
assert_match(/t\.string :name/, up)
assert_match(/t\.integer :supplier_id/, up)

assert_match(/t\.integer :user_id/, up)

assert_not_match(/add_index :products, :name/, up)
assert_not_match(/add_index :products, :supplier_id/, up)
assert_not_match(/add_index :products, :user_id/, up)
end
end
end
Expand All @@ -160,7 +166,7 @@ def test_migration_with_missing_attribute_type_and_with_index
end

def test_add_migration_with_attributes_index_declaration_and_attribute_options
run_generator ["product", "title:string[40]:index", "content:string[255]", "price:decimal[5.2]:index"]
run_generator ["product", "title:string{40}:index", "content:string{255}", "price:decimal{5,2}:index", "discount:decimal{5,2}:uniq"]

assert_migration "db/migrate/create_products.rb" do |content|
assert_method :change, content do |up|
Expand All @@ -171,6 +177,7 @@ def test_add_migration_with_attributes_index_declaration_and_attribute_options
end
assert_match(/add_index :products, :title/, content)
assert_match(/add_index :products, :price/, content)
assert_match(/add_index :products, :discount, :unique => true/, content)
end
end

Expand Down

0 comments on commit 51eded9

Please sign in to comment.