-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds Support for Model Generation #207
Changes from all commits
8cf6be5
671dde6
4e7b325
4ce5b39
2f6efb3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
require "napa/cli/generate/api" | ||
require "napa/cli/generate/readme" | ||
require "napa/cli/migration" | ||
require "napa/cli/model" | ||
|
||
module Napa | ||
module CLI | ||
|
@@ -13,6 +14,13 @@ class Generate < Thor | |
'Create a Database Migration' | ||
) | ||
|
||
register( | ||
Model, | ||
'model', | ||
'model <NAME> [field[:type][:index] field[:type][:index]] [options]', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. |
||
'Create a Model, including its database migration and test scaffolding' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. |
||
) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra empty line detected at class body end. |
||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
module Napa | ||
module CLI | ||
# directly ported with slight modification from | ||
# https://github.com/rails/rails/blob/76883f92374c6395f13c16628e1d87d40b6d2399/railties/lib/rails/generators/generated_attribute.rb | ||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assignment Branch Condition size for parse is too high. [15.26/15] |
||
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 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line is too long. [95/80] |
||
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, :precision/:scale for decimals or :polymorphic for references/belongs_to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line is too long. [159/80] |
||
# 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: $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 || :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 | ||
when :integer then :number_field | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indent |
||
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 | ||
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) | ||
when :string then name == "type" ? "" : "MyString" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line is too long. [81/80] |
||
when :text then "MyText" | ||
when :boolean then false | ||
when :references, :belongs_to then nil | ||
else | ||
"" | ||
end | ||
end | ||
|
||
def factory_stub | ||
case type | ||
when :integer then "1" | ||
when :float then "1.5" | ||
when :decimal then "9.99" | ||
when :datetime, :timestamp, :time then "{ Time.now }" | ||
when :date then "{ Date.today }" | ||
when :string then '"MyString"' | ||
when :text then '"MyText"' | ||
when :boolean then "false" | ||
when :digest then '"password"' | ||
else | ||
'"Unknown"' | ||
end | ||
end | ||
|
||
def plural_name | ||
name.sub(/_id$/, '').pluralize | ||
end | ||
|
||
def singular_name | ||
name.sub(/_id$/, '').singularize | ||
end | ||
|
||
def human_name | ||
name.humanize | ||
end | ||
|
||
def index_name | ||
@index_name ||= if polymorphic? | ||
%w(id type).map { |t| "#{name}_#{t}" } | ||
else | ||
column_name | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
end | ||
|
||
def column_name | ||
@column_name ||= reference? ? "#{name}_id" : name | ||
end | ||
|
||
def foreign_key? | ||
!!(name =~ /_id$/) | ||
end | ||
|
||
def reference? | ||
self.class.reference?(type) | ||
end | ||
|
||
def polymorphic? | ||
self.attr_options.has_key?(:polymorphic) | ||
end | ||
|
||
def required? | ||
self.attr_options[:required] | ||
end | ||
|
||
def has_index? | ||
@has_index | ||
end | ||
|
||
def has_uniq_index? | ||
@has_uniq_index | ||
end | ||
|
||
def password_digest? | ||
name == 'password' && type == :digest | ||
end | ||
|
||
def inject_options | ||
"".tap { |s| @attr_options.each { |k,v| s << ", #{k}: #{v.inspect}" } } | ||
end | ||
|
||
def inject_index_options | ||
has_uniq_index? ? ", unique: true" : "" | ||
end | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.