class HotGlue::ScaffoldGenerator
Attributes
nest_with[RW]
path[RW]
plural[RW]
singular[RW]
singular_class[RW]
Public Class Methods
new(*meta_args)
click to toggle source
def erb_replace_ampersands
if @template_builder.is_a?(HotGlue::ErbTemplate) @output_buffer.gsub!('\%', '%') end
end
Calls superclass method
# File lib/generators/hot_glue/scaffold_generator.rb, line 93 def initialize(*meta_args) super begin @the_object = eval(class_name) rescue StandardError => e message = "*** Oops: It looks like there is no object for #{class_name}. Please define the object + database table first." raise(HotGlue::Error, message) end if @specs_only && @no_specs raise(HotGlue::Error, "*** Oops: You seem to have specified both the --specs-only flag and --no-specs flags. this doesn't make any sense, so I am aborting. sorry.") end if options['markup'] == "erb" @template_builder = HotGlue::ErbTemplate.new elsif options['markup'] == "slim" puts "SLIM IS NOT IMPLEMENTED; please see https://github.com/jasonfb/hot-glue/issues/3" abort @template_builder = HotGlue::SlimTemplate.new elsif options['markup'] == "haml" @template_builder = HotGlue::HamlTemplate.new end @markup = options['markup'] args = meta_args[0] @singular = args.first.tableize.singularize # should be in form hello_world @plural = options['plural'] || @singular + "s" # supply to override; leave blank to use default @auth = options['auth'] || "current_user" @auth_identifier = options['auth_identifier'] || (!@auth.nil? && @auth.gsub("current_", "")) || nil @nest = (!options['nest'].empty? && options['nest']) || nil @namespace = options['namespace'] || nil @singular_class = @singular.titleize.gsub(" ", "") @exclude_fields = [] @exclude_fields += options['exclude'].split(",").collect(&:to_sym) if !options['include'].empty? @include_fields = [] @include_fields += options['include'].split(",").collect(&:to_sym) end @show_only = [] if !options['show_only'].empty? @show_only += options['show_only'].split(",").collect(&:to_sym) end @god = options['god'] || options['gd'] || false @specs_only = options['specs_only'] || false @no_specs = options['no_specs'] || false @no_delete = options['no_delete'] || false @no_create = options['no_create'] || false @no_paginate = options['no_paginate'] || false @big_edit = options['big_edit'] if @god @auth = nil end # when in self auth, the object is the same as the authenticated object if @auth && auth_identifier == @singular @self_auth = true end @nested_args = [] if !@nest.nil? @nested_args = @nest.split("/") @nested_args_plural = {} @nested_args.each do |a| @nested_args_plural[a] = a + "s" end end # the @object_owner will always be object that will 'own' the object # for new and create if @auth && ! @self_auth && @nested_args.none? @object_owner_sym = @auth.gsub("current_", "").to_sym @object_owner_eval = @auth else if @nested_args.any? @object_owner_sym = @nested_args.last.to_sym @object_owner_eval = "@#{@nested_args.last}" else @object_owner_sym = "" @object_owner_eval = "" end end identify_object_owner setup_fields end
Public Instance Methods
all_form_fields()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 594 def all_form_fields @template_builder.all_form_fields( columns: @columns, show_only: @show_only, singular_class: singular_class, singular: singular ) end
all_line_fields()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 603 def all_line_fields @template_builder.all_line_fields( columns: @columns, show_only: @show_only, singular_class: singular_class, singular: singular ) end
all_objects_root()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 470 def all_objects_root if @auth if @self_auth @singular_class + ".where(id: #{@auth}.id)" elsif @nested_args.none? @auth + ".#{plural}" else "@" + @nested_args.last + ".#{plural}" end else @singular_class + ".all" end end
all_objects_variable()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 488 def all_objects_variable all_objects_root + ".page(params[:page])" end
all_views()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 563 def all_views res = %w(index edit _form _line _list _show _errors) unless @no_create res += %w(new _new_form _new_button) end res end
any_nested?()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 484 def any_nested? @nested_args.any? end
auth_identifier()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 393 def auth_identifier @auth_identifier end
auth_object()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 492 def auth_object @auth end
columns_spec_with_sample_data()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 329 def columns_spec_with_sample_data @columns.map { |c| if eval("#{singular_class}.columns_hash['#{c}']").nil? byebug end type = eval("#{singular_class}.columns_hash['#{c}']").type random_data = case type when :integer rand(1...1000) when :string FFaker::AnimalUS.common_name when :text FFaker::AnimalUS.common_name when :datetime Time.now + rand(1..5).days end c.to_s + ": '" + random_data.to_s + "'" }.join(", ") end
controller_class_name()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 378 def controller_class_name res = "" res << @namespace.titleize + "::" if @namespace res << plural.titleize.gsub(" ", "") + "Controller" res end
controller_descends_from()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 612 def controller_descends_from if defined?(@namespace.titlecase + "::BaseController") @namespace.titlecase + "::BaseController" else "ApplicationController" end end
copy_controller_and_spec_files()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 302 def copy_controller_and_spec_files @default_colspan = @columns.size unless @specs_only template "controller.rb.erb", File.join("#{'spec/dummy/' if Rails.env.test?}app/controllers#{namespace_with_dash}", "#{plural}_controller.rb") if @namespace begin eval(controller_descends_from) puts " skipping base controller #{controller_descends_from}" rescue NameError => e template "base_controller.rb.erb", File.join("#{'spec/dummy/' if Rails.env.test?}app/controllers#{namespace_with_dash}", "base_controller.rb") end end end unless @no_specs template "system_spec.rb.erb", File.join("#{'spec/dummy/' if Rails.env.test?}spec/system#{namespace_with_dash}", "#{plural}_behavior_spec.rb") end template "#{@markup}/_errors.#{@markup}", File.join("#{'spec/dummy/' if Rails.env.test?}app/views#{namespace_with_dash}", "_errors.#{@markup}") end
copy_view_files()
click to toggle source
def erb_replace_ampersands!(filename = nil)
return if filename.nil? file = File.open(filename, "r") contents = file.read file.close file = File.open(filename, "w") file.write( contents.gsub('\%', '%')) file.close
end
# File lib/generators/hot_glue/scaffold_generator.rb, line 516 def copy_view_files return if @specs_only all_views.each do |view| formats.each do |format| source_filename = cc_filename_with_extensions("#{@markup}/#{view}", "#{@markup}") dest_filename = cc_filename_with_extensions("#{view}", "#{@markup}") dest_filepath = File.join("#{'spec/dummy/' if Rails.env.test?}app/views#{namespace_with_dash}", controller_file_path, dest_filename) template source_filename, dest_filepath gsub_file dest_filepath, '\%', '%' end end turbo_stream_views.each do |view| formats.each do |format| source_filename = cc_filename_with_extensions( "#{@markup}/#{view}.turbo_stream.#{@markup}") dest_filename = cc_filename_with_extensions("#{view}", "turbo_stream.#{@markup}") dest_filepath = File.join("#{'spec/dummy/' if Rails.env.test?}app/views#{namespace_with_dash}", controller_file_path, dest_filename) template source_filename, dest_filepath gsub_file dest_filepath, '\%', '%' end end end
create_action()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 651 def create_action return false if @self_auth return !@no_create end
destroy_action()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 646 def destroy_action return false if @self_auth return !@no_delete end
display_class()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 622 def display_class me = eval(singular_class) @display_class ||= if me.column_names.include?("name") || me.instance_methods(false).include?(:name) # note that all class object respond_to?(:name) with the name of their own class # this one is unique "name" elsif me.column_names.include?("to_label") || me.instance_methods(false).include?(:to_label) "to_label" elsif me.column_names.include?("full_name") || me.instance_methods(false).include?(:full_name) "full_name" elsif me.column_names.include?("display_name") || me.instance_methods(false).include?(:display_name) "display_name" elsif me.column_names.include?("email") || me.instance_methods(false).include?(:email) "email" elsif me.column_names.include?("number") || me.instance_methods(false).include?(:number) "number" else exit_message = "*** Oops: Can't find any column to use as the display label on #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, 5) email, or 6) number directly on your #{singular_class} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)" raise(HotGlue::Error, exit_message) end end
format()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 298 def format nil end
formats()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 294 def formats [format] end
handler()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 581 def handler :erb end
identify_object_owner()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 195 def identify_object_owner auth_assoc = @auth && @auth.gsub("current_","") if !@object_owner_sym.empty? auth_assoc_field = auth_assoc + "_id" assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})") if assoc @ownership_field = assoc.name.to_s + "_id" elsif !@nest exit_message = "*** Oops: It looks like is no association from current_#{@object_owner_sym} to a class called #{@singular_class}. If your user is called something else, pass with flag auth=current_X where X is the model for your users as lowercase. Also, be sure to implement current_X as a method on your controller. (If you really don't want to implement a current_X on your controller and want me to check some other method for your current user, see the section in the docs for auth_identifier.) To make a controller that can read all records, specify with --god." else if @god exit_message= "*** Oops: god mode could not find the association(?). something is wrong." else @auth_check = "current_user" @nested_args.each do |arg| if !@auth_check.method("#{arg}s") exit_message= "*** Oops: your nesting chain does not have a assocation for #{arg}s on #{@auth_check} something is wrong." end byebug puts "" end end raise(HotGlue::Error, exit_message) end end end
line_path_partial()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 421 def line_path_partial "#{@namespace+"/" if @namespace}#{plural}/line" end
list_column_headings()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 324 def list_column_headings @template_builder.list_column_headings(columns: @columns) end
list_path_partial()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 429 def list_path_partial "#{@namespace+"/" if @namespace}#{plural}/list" end
model_has_strings?()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 585 def model_has_strings? false end
model_search_fields()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 590 def model_search_fields # an array of fields we can search on [] end
namespace_with_dash()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 547 def namespace_with_dash if @namespace "/#{@namespace}" else "" end end
namespace_with_slash()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 656 def namespace_with_slash if @namespace "#{@namespace}/" else "" end end
namespace_with_trailing_dash()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 555 def namespace_with_trailing_dash if @namespace "#{@namespace}/" else "" end end
nested_arity_for_path()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 453 def nested_arity_for_path [@nested_args[0..-1].collect{|a| "@#{a}"}].join(", ") #metaprgramming into arity for the Rails path helper end
nested_assignments()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 437 def nested_assignments @nested_args.map{|a| "#{a}: @#{a}"}.join(", ") #metaprgramming into Ruby hash end
nested_assignments_with_leading_comma()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 441 def nested_assignments_with_leading_comma if @nested_args.any? ", #{nested_assignments}" else "" end end
nested_objects_arity()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 449 def nested_objects_arity @nested_args.map{|a| "@#{a}"}.join(", ") end
new_path_name()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 433 def new_path_name "new_#{@namespace+"_" if @namespace}#{singular}_path" end
no_devise_installed()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 496 def no_devise_installed !Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.group_by{ |g| g.name }['devise'] end
object_parent_mapping_as_argument_for_specs()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 349 def object_parent_mapping_as_argument_for_specs if @nested_args.any? ", " + @nested_args.last + ": " + @nested_args.last elsif @auth ", #{@auth_identifier}: #{@auth}" end end
object_scope()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 457 def object_scope if @auth if @nested_args.none? @auth + ".#{plural}" else "@" + @nested_args.last + ".#{plural}" end else @singular_class end end
objest_nest_factory_setup()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 357 def objest_nest_factory_setup res = "" if @auth last_parent = ", #{@auth_identifier}: #{@auth}" end @nested_args.each do |arg| res << " let(:#{arg}) {create(:#{arg} #{last_parent} )}\n" last_parent = ", #{arg}: #{arg}" end res end
objest_nest_params_by_id_for_specs()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 371 def objest_nest_params_by_id_for_specs @nested_args.map{|arg| "#{arg}_id: #{arg}.id" }.join(",\n ") end
paginate()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 664 def paginate @template_builder.paginate(plural: plural) end
path_arity()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 413 def path_arity res = "" if @nested_args.any? res << nested_objects_arity + ", " end res << "@" + singular end
path_helper_args()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 397 def path_helper_args if @nested_args.any? [(@nested_args).collect{|a| "@#{a}"} , singular].join(",") else singular end end
path_helper_plural()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 409 def path_helper_plural "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{plural}_path" end
path_helper_singular()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 405 def path_helper_singular "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{singular}_path" end
plural_name()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 389 def plural_name plural end
setup_fields()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 229 def setup_fields auth_assoc = @auth && @auth.gsub("current_","") if !@include_fields @exclude_fields.push :id, :created_at, :updated_at, :encrypted_password, :reset_password_token, :reset_password_sent_at, :remember_created_at, :confirmation_token, :confirmed_at, :confirmation_sent_at, :unconfirmed_email @exclude_fields.push( (auth_assoc + "_id").to_sym) if ! auth_assoc.nil? @exclude_fields.push( @ownership_field.to_sym ) if ! @ownership_field.nil? @columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| @exclude_fields.include?(field) } else @columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| !@include_fields.include?(field) } end @columns.each do |col| if col.to_s.starts_with?("_") @show_only << col end if @the_object.columns_hash[col.to_s].type == :integer if col.to_s.ends_with?("_id") # guess the association name label assoc_name = col.to_s.gsub("_id","") assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})") begin eval(assoc.class_name) rescue NameError => e exit_message = "*** Oops: The model #{singular_class} is missing an association for #{assoc_name} or the model doesn't exist. TODO: Please implement a model for #{assoc_name.titlecase}; your model #{singular_class.titlecase} should have_many :#{assoc_name}s. To make a controller that can read all records, specify with --god." raise(HotGlue::Error, exit_message) end if assoc.nil? exit_message= "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'" raise(HotGlue::Error,exit_message) end assoc_class = eval(assoc.class_name) name_list = [:name, :to_label, :full_name, :display_name, :email] if name_list.collect{ |field| assoc_class.column_names.include?(field.to_s) || assoc_class.instance_methods.include?(field) }.any? # do nothing here else exit_message= "*** Oops: Missing a label for #{assoc.class_name.upcase}. Can't find any column to use as the display label for the #{assoc.name.to_s} association on the #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, or 5) email directly on your #{assoc.class_name.upcase} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)" raise(HotGlue::Error,exit_message) end end end end end
show_path_partial()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 425 def show_path_partial "#{@namespace+"/" if @namespace}#{plural}/show" end
singular_name()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 385 def singular_name @singular end
turbo_stream_views()
click to toggle source
# File lib/generators/hot_glue/scaffold_generator.rb, line 573 def turbo_stream_views res = %w(create edit update) unless @no_delete res << 'destroy' end res end