Class: InlineFormsAddtoGenerator
- Inherits:
-
Rails::Generators::NamedBase
- Object
- Rails::Generators::NamedBase
- InlineFormsAddtoGenerator
- Defined in:
- lib/generators/inline_forms_addto_generator.rb
Overview
Usage
rails g inline_forms_addto Model attribute:type [attribute:type ...] [options]
Adds fields to an existing inline_forms model. Emits an additive
migration (add_column / add_reference / single :string column for
:image_field/:audio_field) and edits the model file:
- adds
belongs_to/has_many/has_one/has_and_belongs_to_many/has_rich_text/mount_uploaderlines (idempotent) - inserts new rows into the model's
inline_forms_attribute_list
Does NOT touch routes, the controller, or MODEL_TABS (those are
already wired for the existing model). Use rails g inline_forms <Model>
to create new models.
Special generator names
_no_model, _no_migration, _id, _enabled are install-time only and
are rejected. _presentation, _list_order, _list_search are
accepted but only acted on when --replace is passed; otherwise the
generator skips them with a say_status :skipped notice.
Top-level (no InlineForms module wrapper) so Rails resolves
rails g inline_forms_addto Model … to this class without the
inline_forms:inline_forms_addto double-segment trick that Rails only
applies for matching name:name pairs (inline_forms:inline_forms).
Constant Summary collapse
- INSTALL_TIME_ONLY_NAMES =
%w[_no_model _no_migration _id _enabled].freeze
- REPLACE_ONLY_NAMES =
%w[_presentation _list_order _list_search _order].freeze
- VALUE_BEARING_ELEMENTS =
Form elements that render a set of choices and therefore need a values hash as the 3rd element of their attribute_list row. Emitting the bare 2-element row for these raises at show time, so we insert a placeholder hash and warn the user to fill it in. Canonical list lives in InlineForms (shared with the schema GUI/preview).
InlineForms::VALUE_BEARING_FORM_ELEMENTS
- METADATA_ROW_NAMES =
attribute_list rows whose form element (or name) marks the start of the trailing "metadata" block. The smart-default placement inserts new rows above this block instead of at the very end of the list.
%w[created_at updated_at].freeze
Instance Method Summary collapse
- #generate_migration ⇒ Object
-
#remind_to_migrate ⇒ Object
Run last (Thor invokes public methods in definition order).
- #set_some_flags ⇒ Object
- #update_model ⇒ Object
- #validate! ⇒ Object
Instance Method Details
#generate_migration ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/generators/inline_forms_addto_generator.rb', line 107 def generate_migration @migration_lines = String.new attributes.each do |attribute| next if INSTALL_TIME_ONLY_NAMES.include?(attribute.name) next if REPLACE_ONLY_NAMES.include?(attribute.name) next unless attribute.migration? # A :header is a display-only separator in the attribute list; it has # no backing column, so it must not emit a migration line (otherwise # `foo:header` created a pointless `foo` string column). next if attribute.attribute_type == :header if attribute.column_type == :belongs_to @migration_lines << " add_reference :#{table_name}, :#{attribute.name}, foreign_key: true\n" else commenter = attribute.attribute_type == :unknown ? "#" : " " @migration_lines << "#{commenter} add_column :#{table_name}, :#{attribute.name}, :#{attribute.column_type}\n" end end return if @migration_lines.empty? template "add_columns_migration.erb", "db/migrate/#{unique_time_stamp}_#{migration_file_basename}.rb" end |
#remind_to_migrate ⇒ Object
Run last (Thor invokes public methods in definition order). The model row was injected above, but it references a column that does not exist until the generated migration is applied; rendering the model before then raises. Remind the user loudly. No-op when no migration was written (e.g. only has_many/rich_text/habtm additions).
174 175 176 177 178 179 180 181 |
# File 'lib/generators/inline_forms_addto_generator.rb', line 174 def remind_to_migrate return if @migration_lines.nil? || @migration_lines.empty? say "" say " Next step: apply the generated migration before rendering #{model_class_name}:", :yellow say " bundle exec rails db:migrate", :yellow say " (the attribute_list row was added now, but its column only exists after migrating.)", :yellow end |
#set_some_flags ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/generators/inline_forms_addto_generator.rb', line 68 def set_some_flags @unknown_attributes = [] @forbidden_names = [] @skipped_replace_names = [] attributes.each do |attribute| if INSTALL_TIME_ONLY_NAMES.include?(attribute.name) @forbidden_names << attribute.name next end if REPLACE_ONLY_NAMES.include?(attribute.name) && ![:replace] @skipped_replace_names << "#{attribute.name}:#{attribute.type}" next end if !attribute.name.start_with?("_") && ( (attribute.attribute? && attribute.attribute_type == :unknown) || (attribute.migration? && attribute.column_type == :unknown) ) @unknown_attributes << "#{attribute.name}:#{attribute.type}" end end unless @forbidden_names.empty? raise Thor::Error, "Names #{@forbidden_names.uniq.join(', ')} are install-time only " \ "and not supported by inline_forms_addto." end allow_unknown = [:allow_unknown].to_s == "true" if !allow_unknown && !@unknown_attributes.empty? raise Thor::Error, "Unknown field type(s): #{@unknown_attributes.uniq.join(', ')}. " \ "Add a valid form element type or pass --allow-unknown to keep legacy commented output." end @skipped_replace_names.each do |label| say_status :skipped, "#{label} (pass --replace to rewrite the existing scope/method)", :yellow end end |
#update_model ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/generators/inline_forms_addto_generator.rb', line 132 def update_model attributes.each do |attribute| next if INSTALL_TIME_ONLY_NAMES.include?(attribute.name) next if REPLACE_ONLY_NAMES.include?(attribute.name) && ![:replace] if REPLACE_ONLY_NAMES.include?(attribute.name) && [:replace] replace_special!(attribute) next end case attribute.column_type when :belongs_to inject_class_line!(" belongs_to :#{attribute.name}\n") end case attribute.type when :image_field, :audio_field uploader_class = "#{attribute.name}_uploader".camelcase inject_class_line!(" mount_uploader :#{attribute.name}, #{uploader_class}\n") when :has_many inject_class_line!(" has_many :#{attribute.name}\n") when :has_many_destroy inject_class_line!(" has_many :#{attribute.name}, :dependent => :destroy\n") when :has_one inject_class_line!(" has_one :#{attribute.name}\n") when :habtm, :has_and_belongs_to_many, :check_list inject_class_line!(" has_and_belongs_to_many :#{attribute.name}\n") when :rich_text inject_class_line!(" has_rich_text :#{attribute.name}\n") end next unless attribute.attribute? add_attribute_list_row!(attribute) end end |
#validate! ⇒ Object
60 61 62 63 64 65 66 |
# File 'lib/generators/inline_forms_addto_generator.rb', line 60 def validate! unless File.exist?(File.join(destination_root, model_file_path)) raise Thor::Error, "Model #{model_file_path} not found. " \ "Use `rails g inline_forms #{name} ...` for new models." end end |