Skip to content

Commit

Permalink
Add a required option to the model generator
Browse files Browse the repository at this point in the history
Syntax was chosen to follow the passing of multiple options to
decimal/numeric types. Curly braces, and allowing any of `,`, `.`, or
`-` to be used as a separator to avoid the need for shell quoting. (I'm
intending to expand this to all columns, but that's another PR.

The `required` option will cause 2 things to change. `required: true`
will be added to the association. `null: false` will be added to the
column in the migration.
  • Loading branch information
sgrif committed Aug 8, 2014
1 parent c69e21d commit fdfc0fc
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def index_name_for(attribute)
def attributes_with_index
attributes.select { |a| !a.reference? && a.has_index? }
end

def validate_file_name!
unless file_name =~ /^[_a-z0-9]+$/
raise IllegalMigrationNameError.new(file_name)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<% module_namespacing do -%>
class <%= class_name %> < <%= parent_class_name.classify %>
<% attributes.select(&:reference?).each do |attribute| -%>
belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %><%= ', required: true' if attribute.required? %>
<% end -%>
<% if attributes.any?(&:password_digest?) -%>
has_secure_password
Expand Down
4 changes: 4 additions & 0 deletions railties/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
* Add a `required` option to the model generator for associations

*Sean Griffin*

* Add `after_bundle` callbacks in Rails templates. Useful for allowing the
generated binstubs to be added to version control.

Expand Down
24 changes: 20 additions & 4 deletions railties/lib/rails/generators/generated_attribute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ def parse_type_and_options(type)
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
when /(references|belongs_to)\{(.+)\}/
type = $1
provided_options = $2.split(/[,.-]/)
options = Hash[provided_options.map { |opt| [opt.to_sym, true] }]
return type, options
else
return type, {}
end
Expand Down Expand Up @@ -123,7 +126,11 @@ def reference?
end

def polymorphic?
self.attr_options.has_key?(:polymorphic)
self.attr_options[:polymorphic]
end

def required?
self.attr_options[:required]
end

def has_index?
Expand All @@ -139,12 +146,21 @@ def password_digest?
end

def inject_options
"".tap { |s| @attr_options.each { |k,v| s << ", #{k}: #{v.inspect}" } }
"".tap { |s| options_for_migration.each { |k,v| s << ", #{k}: #{v.inspect}" } }
end

def inject_index_options
has_uniq_index? ? ", unique: true" : ""
end

def options_for_migration
@attr_options.dup.tap do |options|
if required?
options.delete(:required)
options[:null] = false
end
end
end
end
end
end
12 changes: 12 additions & 0 deletions railties/test/generators/migration_generator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,18 @@ def test_add_migration_with_references_options
end
end

def test_add_migration_with_required_references
migration = "add_references_to_books"
run_generator [migration, "author:belongs_to{required}", "distributor:references{polymorphic,required}"]

assert_migration "db/migrate/#{migration}.rb" do |content|
assert_method :change, content do |change|
assert_match(/add_reference :books, :author, index: true, null: false/, change)
assert_match(/add_reference :books, :distributor, polymorphic: true, index: true, null: false/, change)
end
end
end

def test_create_join_table_migration
migration = "add_media_join_table"
run_generator [migration, "artist_id", "musics:uniq"]
Expand Down
44 changes: 44 additions & 0 deletions railties/test/generators/model_generator_test.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'generators/generators_test_helper'
require 'rails/generators/rails/model/model_generator'
require 'active_support/core_ext/string/strip'

class ModelGeneratorTest < Rails::Generators::TestCase
include GeneratorsTestHelper
Expand Down Expand Up @@ -363,6 +364,49 @@ def test_index_is_skipped_for_references_association
end
end

def test_required_belongs_to_adds_required_association
run_generator ["account", "supplier:references{required}"]

expected_file = <<-FILE.strip_heredoc
class Account < ActiveRecord::Base
belongs_to :supplier, required: true
end
FILE
assert_file "app/models/account.rb", expected_file
end

def test_required_polymorphic_belongs_to_generages_correct_model
run_generator ["account", "supplier:references{required,polymorphic}"]

expected_file = <<-FILE.strip_heredoc
class Account < ActiveRecord::Base
belongs_to :supplier, polymorphic: true, required: true
end
FILE
assert_file "app/models/account.rb", expected_file
end

def test_required_and_polymorphic_are_order_independent
run_generator ["account", "supplier:references{polymorphic.required}"]

expected_file = <<-FILE.strip_heredoc
class Account < ActiveRecord::Base
belongs_to :supplier, polymorphic: true, required: true
end
FILE
assert_file "app/models/account.rb", expected_file
end

def test_required_adds_null_false_to_column
run_generator ["account", "supplier:references{required}"]

assert_migration "db/migrate/create_accounts.rb" do |m|
assert_method :change, m do |up|
assert_match(/t\.references :supplier,.*\snull: false/, up)
end
end
end

private
def assert_generated_fixture(path, parsed_contents)
fixture_file = File.new File.expand_path(path, destination_root)
Expand Down

0 comments on commit fdfc0fc

Please sign in to comment.