require 'rails/generators/migration' class Spud::ModuleGenerator < ::Rails::Generators::Base desc 'Creates a new model, dashboard module, and frontend route' argument :module_name, type: :string argument :attributes, type: :array, default: [], banner: 'field[:type][:index] field[:type][:index]' source_root File.expand_path('../templates', __FILE__) def create_module install_templates install_assets inject_code create_routes create_specs if defined?(RSpec) create_model_scopes() if self.behavior == :invoke end private def install_templates template 'admin_controller.rb.erb', "app/controllers/admin/#{module_name_formatted}_controller.rb" template 'controller.rb.erb', "app/controllers/#{module_name_formatted}_controller.rb" template 'assets/module.js.erb', "app/assets/javascripts/#{module_name_formatted}.js" template 'assets/admin/module.js.erb', "app/assets/javascripts/admin/#{module_name_formatted}.js" template 'views/admin/index.html.erb', "app/views/admin/#{module_name_formatted}/index.html.erb" template 'views/admin/show.html.erb', "app/views/admin/#{module_name_formatted}/show.html.erb" template 'views/admin/new.html.erb', "app/views/admin/#{module_name_formatted}/new.html.erb" template 'views/admin/edit.html.erb', "app/views/admin/#{module_name_formatted}/edit.html.erb" template 'views/admin/_form.html.erb', "app/views/admin/#{module_name_formatted}/_form.html.erb" template 'views/frontend/index.html.erb', "app/views/#{module_name_formatted}/index.html.erb" template 'views/frontend/show.html.erb', "app/views/#{module_name_formatted}/show.html.erb" end def install_assets create_file "app/assets/stylesheets/admin/#{module_name_formatted}.scss", "// Place #{module_name} admin styles here\n\n" create_file "app/assets/stylesheets/#{module_name_formatted}.scss", "// Place #{module_name} styles here\n\n" end def inject_code environment( "Spud::Core.config.admin_applications += [{name: '#{module_name_formatted.humanize.titlecase}', thumbnail: \"admin/module_icon.png\", url: \"/admin/#{module_name_formatted}\"}]" ) Rails::Generators.invoke 'model', [module_name_formatted.singularize] + attributes, behavior: behavior Rails::Generators.invoke 'helper', [module_name], behavior: behavior Rails::Generators.invoke 'helper', ["Admin/#{module_name}"], behavior: behavior end def module_name_formatted module_name.pluralize.underscore end def create_routes route < [:index, :show] EOF end def create_specs string_attribute = find_first_string_attr() Rails::Generators.invoke 'spud:controller_spec', ["#{module_name_formatted}", string_attribute, 0], behavior: behavior Rails::Generators.invoke 'spud:controller_spec', ["Admin/#{module_name_formatted}", string_attribute, 1], behavior: behavior end def field_for_attribute(type, name) case type when 'integer' "<%= f.tb_number_field :#{name} %>" when 'text' "<%= f.tb_text_area :#{name}, rows: 4 %>" when 'boolean' "<%= f.tb_check_box :#{name} %>" when 'date' "<%= f.tb_date_select :#{name} %>" else "<%= f.tb_text_field :#{name} %>" end end def application_name Rails.application.class.name.split('::').first.underscore end def attribute_names attributes.collect{ |att| att.split(':')[0] } end def create_model_scopes sort_field = ask('What field would you like to sort by?', default: 'created_at') search_field = ask('What field would you like to search by?', default: attributes.first.split(':').first) inject_into_file "app/models/#{module_name.singularize.underscore}.rb", after: "ApplicationRecord\n" do <<-RUBY scope :ordered, -> { order(#{sort_field}: :desc) } scope :search, ->(term) { where('#{search_field} LIKE ?', "%\#{term}%") } RUBY end end # NOT CURRENTLY USED # # Call this method from the create_module generator to automatically build length validators for string columns. # The idea here is to protect against database exceptions when long strings are entered by a user. # # Assumes 255 as the default limit # # def add_string_maximums string_attrs = attributes.select{ |att| att.split(':')[1] == 'string' }.collect{ |att| att.split(':')[0] } if string_attrs.any? string_attrs_as_symbols = string_attrs.collect{ |att| ":#{att.to_s}" }.join(', ') inject_into_file "app/models/#{module_name.singularize.underscore}.rb", before: 'end' do <<-RUBY validates #{string_attrs_as_symbols}, :length => {:maximum => 255} RUBY end end end def find_first_string_attr found = attributes.find{ |att| att.split(':')[1] == 'string' } if found return found.split(':')[0] else return 'string_not_found' end end end