module SunSword class ScaffoldGenerator < Rails::Generators::Base source_root File.expand_path('templates_scaffold', __dir__) argument :arg_structure, type: :string, default: '', banner: '' argument :arg_scope, type: :hash, default: '', banner: 'scope:dashboard' def running setup_variables create_root_folder create_controller_file create_view_file create_link_file end private def setup_variables config = YAML.load_file("db/structures/#{arg_structure}_structure.yaml") @structure = Hashie::Mash.new(config) # Mengambil detail konfigurasi model_name = @structure.model resource_name = @structure.resource_name.singularize.underscore.downcase entity = @structure.entity || {} @actor = @structure.actor @resource_owner_id = @structure.resource_owner_id @uploaders = @structure.uploaders || [] @search_able = @structure.search_able || [] @services = @structure.domains || {} @controllers = @structure.controllers || {} @contract_list = @services.action_list.use_case.contract || [] @contract_fetch_by_id = @services.action_fetch_by_id.use_case.contract || [] @contract_create = @services.action_create.use_case.contract || [] @contract_update = @services.action_update.use_case.contract || [] @contract_destroy = @services.action_destroy.use_case.contract || [] @skipped_fields = entity.skipped_fields || [] @custom_fields = entity.custom_fields || [] @variable_subject = model_name.split('::').last.underscore.downcase @scope_path = resource_name.pluralize.underscore.downcase @scope_class = @scope_path.camelize @model_class = model_name.camelize.constantize @subject_class = resource_name.camelize @fields = contract_fields @form_fields = @controllers.form_fields @route_scope_path = arg_scope['scope'].to_s.downcase rescue '' @route_scope_class = @route_scope_path.camelize rescue '' @mapping_fields = { string: :text_field, text: :text_area, integer: :number_field, float: :number_field, decimal: :number_field, boolean: :check_box, date: :date_select, datetime: :datetime_select, timestamp: :datetime_select, time: :time_select, enum: :select, file: :file_field, files: :file_fields } end def generate_form_fields_html form_fields_html = '' @form_fields.each do |field| field_name = field[:name].to_sym field_type = field[:type].to_sym form_helper = @mapping_fields[field_type] || :text_field input_id = "#{@variable_subject}_#{field_name}" label_input_id = case form_helper when :date_select, :datetime_select then "#{input_id}_1i" # Year when :time_select then "#{input_id}_4i" # Hour else input_id end field_html = <<-HTML
<%= form.label :#{field_name}, for: '#{label_input_id}', class: "block text-sm font-medium text-gray-700 sm:pt-1.5" %>
HTML case form_helper when :text_field, :number_field field_html += <<-HTML <%= form.#{form_helper} :#{field_name}, id: '#{input_id}', class: "block w-full rounded-md border-gray-300 py-1.5 text-gray-700 shadow-sm focus:ring-2 focus:ring-gray-300 focus:border-gray-300 sm:max-w-md sm:text-sm" %> HTML when :text_area field_html += <<-HTML <%= form.text_area :#{field_name}, id: '#{input_id}', rows: 3, class: "block w-full max-w-2xl rounded-md border-gray-300 py-1.5 text-gray-700 shadow-sm focus:ring-2 focus:ring-gray-300 focus:border-gray-300 sm:text-sm" %> HTML when :check_box field_html += <<-HTML
<%= form.check_box :#{field_name}, id: '#{input_id}', class: "h-4 w-4 rounded border-gray-300 text-gray-600 focus:ring-gray-300 focus:border-gray-300" %>
<%= form.label :#{field_name}, for: '#{input_id}', class: "font-medium text-gray-700" %>
HTML when :select field_html += <<-HTML <%= form.select :#{field_name}, options_for_select([['Option 1', 1], ['Option 2', 2]]), {}, { id: '#{input_id}', class: "block w-full rounded-md border-gray-300 py-1.5 text-gray-700 shadow-sm focus:ring-2 focus:ring-gray-300 focus:border-gray-300 sm:max-w-xs sm:text-sm" } %> HTML when :datetime_select, :date_select, :time_select field_html += <<-HTML <%= form.#{form_helper} :#{field_name}, { discard_second: true, id_prefix: '#{input_id}' }, { class: "text-gray-700 shadow-sm focus:ring-2 focus:ring-gray-300 focus:border-gray-300 sm:text-sm" } %> HTML when :file_fields field_html += <<-HTML

or drag and drop

PNG, JPG, GIF, DOC etc.

HTML when :file_field field_html += <<-HTML

or drag and drop

PNG, JPG, GIF, DOC etc.

HTML else field_html += <<-HTML <%= form.#{form_helper} :#{field_name}, id: '#{input_id}', class: "block w-full rounded-md border-gray-300 py-1.5 text-gray-700 shadow-sm focus:ring-2 focus:ring-gray-300 focus:border-gray-300 sm:max-w-md sm:text-sm" %> HTML end field_html += <<-HTML
HTML form_fields_html += field_html end form_fields_html end def build_usecase_filename(action, suffix = '') "#{@actor}_#{action}_#{@variable_subject}#{suffix}".camelize end def create_root_folder empty_directory File.join('app/views', @route_scope_path.to_s, @scope_path.to_s) end def create_controller_file template 'controllers/controller.rb.tt', File.join('app/controllers', @route_scope_path.to_s, "#{@scope_path}_controller.rb") end def create_view_file @form_fields_html = generate_form_fields_html template 'views/_form.html.erb.tt', File.join('app/views', @route_scope_path.to_s, @scope_path.to_s, '_form.html.erb') template 'views/edit.html.erb.tt', File.join('app/views', @route_scope_path.to_s, @scope_path.to_s, 'edit.html.erb') template 'views/index.html.erb.tt', File.join('app/views', @route_scope_path.to_s, @scope_path.to_s, 'index.html.erb') template 'views/new.html.erb.tt', File.join('app/views', @route_scope_path.to_s, @scope_path.to_s, 'new.html.erb') template 'views/show.html.erb.tt', File.join('app/views', @route_scope_path.to_s, @scope_path.to_s, 'show.html.erb') end def namespace_exists? routes_file = 'config/routes.rb' scope_pattern = "namespace :#{@route_scope_path} do\n" if File.exist?(routes_file) file_content = File.read(routes_file) file_content.include?(scope_pattern) else false end end def create_link_file template 'views/components/menu/link.html.erb.tt', File.join('app/views/components/menu', "_link_to_#{@scope_path}.html.erb") link_to = "
  • <%= render 'components/menu/#{"link_to_#{@scope_path}"}' %>
  • \n" inject_into_file 'app/views/components/layouts/_sidebar.html.erb', link_to, before: " <%# generate_link %>\n" routes_file = 'config/routes.rb' if !namespace_exists? && @route_scope_path.present? scope_code = <<-RUBY namespace :#{@route_scope_path} do end RUBY insert_into_file routes_file, scope_code, after: "Rails.application.routes.draw do\n" end if @route_scope_path.present? inject_into_file routes_file, " resources :#{@scope_path}\n", after: "namespace :#{@route_scope_path} do\n" else inject_into_file routes_file, " resources :#{@scope_path}\n", after: "Rails.application.routes.draw do\n" end end def contract_fields skip_contract_fields = @skipped_fields.map(&:strip).uniq @model_class.columns.reject { |column| skip_contract_fields.include?(column.name.to_s) }.map(&:name).map(&:to_s) end def strong_params results = '' @controllers.form_fields.each do |field| if field.type.to_s.eql?('files') results << "{ #{field.name}: [] }, " else results << ":#{field.name}, " end end results[0..-2] end end end