require 'rails/generators' # http://guides.rubyonrails.org/generators.html # http://rdoc.info/github/wycats/thor/master/Thor/Actions.html # keep generator idempotent, thanks module FlexibleAdmin class FlexibleAdminGenerator < Rails::Generators::Base namespace "flexible_admin" source_root File.expand_path("../templates", __FILE__) argument :model_name, :type => :string, :required => true, :desc => "Model name for admin section generation" desc "flexible_admin resource generator, rails g flexible_admin Post" def creates_resource_views template "resources/index.html.erb", "app/views/admin/#{resources_name}/index.html.erb" template "resources/new.html.erb", "app/views/admin/#{resources_name}/new.html.erb" template "resources/edit.html.erb", "app/views/admin/#{resources_name}/edit.html.erb" template "resources/form.html.erb", "app/views/admin/#{resources_name}/_form.html.erb" end def remove_any_namespace_admin_comments_in_routes gsub_file 'config/routes.rb', /#\s*(namespace :admin do)/, '' end def make_routes if has_admin_route_namespace? routing_code = " resources :#{resources_name}, :except => :show do member do get 'toggle' end end" sentinel = /namespace :admin do$/ in_root do inject_into_file 'config/routes.rb', "\n #{routing_code}", { :after => sentinel, :verbose => true } end else route_info = " namespace :admin do resources :#{resources_name}, :except => :show do member do get 'toggle' end end end" route(route_info) end end def create_resources_controller template "admin_resources_controller.rb", "app/controllers/admin/resources_controller.rb" template "resources_controller.rb", "app/controllers/admin/#{resources_name}_controller.rb" end def add_to_navigation_menu gsub_file 'app/views/layouts/admin/_navigation.html.erb', "models = %w(", "models = %w(#{resources_name} " end private def model singular_name.classify.constantize end def resources_name model_name.tableize end def singular_name resources_name.singularize end def instance_variable_resource "@#{resources_name.singularize}" end def upper_case_resources_name upper_case_resource_name.pluralize end def upper_case_resource_name resources_name.classify.pluralize end def table_column_headers model_title = ["#{model_title(model)}"] other_columns = table_column_names_for(model).collect{|column_name| "#{column_name.titleize}" } (model_title + other_columns).join("\n ") end def model_title(model) attributes = model.column_names if attributes.include?("title") "Title" elsif attributes.include?("name") "Name" else "#{model.name} ID" end end def table_rows model_title_value = "<%= link_to #{model_title_value(model)}, edit_admin_#{singular_name}_path(#{singular_name}) %>" other_columns = table_columns_for(model).collect do |column| if column.name =~ /_file_name/ column_name = column.name.split("_file_name").first if is_image?(column_name) "<%= image_tag(#{singular_name}.#{column_name}.url, :width => 24, :height => 24) %>" else "<%= link_to #{singular_name}.#{column_name}.original_filename, #{singular_name}.#{column_name}.url %>" end elsif column.type == :datetime "<%= #{singular_name}.#{column.name}.strftime(\"%F %T\") %>" elsif column.type == :boolean "<%= toggle(#{singular_name}, :#{column.name}) %>" else "<%= #{singular_name}.#{column.name} %>" end end ([model_title_value] + other_columns).join("\n ") end def model_title_value(model) attributes = model.column_names if attributes.include?("title") "#{singular_name}.title" elsif attributes.include?("name") "#{singular_name}.name" else "#{singular_name}.id" end end def columns_for(model) rejections = %w( ^id$ _type$ type created_at created_on updated_at updated_on deleted_at reset_password_token reset_password_sent_at sign_in _content_type file_size).join("|") model.columns.reject { |f| f.name.match(rejections) } end def table_columns_for(model) rejections = %w( ^id$ _type$ type password remember ^name$ ^title$ created_on updated_at updated_on deleted_at reset_password_token reset_password_sent_at sign_in _content_type file_size).join("|") desired_columns = model.columns.reject { |f| f.name.match(rejections) } end def table_column_names_for(model) table_columns_for(model).collect { |c| c.name =~ /_file_name/ ? c.name.split("_file_name").first : c.name } end def render_form_fields(model) columns_for(model).collect do |column| if column.type == :string && column.name =~ /_file_name/ column_name = column.name.split("_file_name").first "<%= render 'admin/shared/file_field', :f => f, :what => :#{column_name} %>" elsif column.type == :string && column.name =~ /encrypted_password/ "<%= render 'admin/shared/text_field', :f => f, :what => :password %>" elsif column.type == :string && column.name =~ /email/ "<%= render 'admin/shared/email_field', :f => f, :what => :#{column.name} %>" elsif column.type == :boolean "<%= render 'admin/shared/checkbox_field', :f => f, :what => :#{column.name} %>" elsif column.type == :text if column.name =~ /(body|description)/ "<%= render 'admin/shared/cktext_area_field', :f => f, :what => :#{column.name} %>" else "<%= render 'admin/shared/text_area_field', :f => f, :what => :#{column.name} %>" end else "<%= render 'admin/shared/text_field', :f => f, :what => :#{column.name} %>" end end.join("\n") end def has_admin_route_namespace? File.open(File.join(destination_root, 'config', 'routes.rb')).read.index("namespace :admin do") end def is_image?(text) text =~ /(img|image|avatar|pic|logo)/ end end end