Created
May 20, 2021 12:23
-
-
Save Sylvance/52437e707d6ab0e68e3a0be2d855ec96 to your computer and use it in GitHub Desktop.
MMVCR_Generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%= form_with(model: {ModelSingular}, class: "min-w-max w-full") do |form| %> | |
<% if {ModelSingular}.errors.any? %> | |
<div id="error_explanation"> | |
<h2><%= pluralize({ModelSingular}.errors.count, "error") %> prohibited this {ModelSingular} from being saved:</h2> | |
<ul> | |
<% {ModelSingular}.errors.each do |error| %> | |
<li><%= error.full_message %></li> | |
<% end %> | |
</ul> | |
</div> | |
<% end %> | |
<div> | |
<div class="bg-gray-200 text-gray-600 text-sm leading-normal"> | |
<p class="py-3 px-6 text-left font-bold uppercase">{ModelSingularCamelize} Form</p> | |
</div> | |
</div> | |
<div class="text-gray-600 text-sm font-light"> | |
<div class="border-b border-gray-200"> | |
<div class="flex"> | |
<div class="md:w-1/2 py-3 px-6 text-left whitespace-nowrap"> | |
<%= form.label :{param1}, class: "block uppercase tracking-wide text-grey-darker text-xs font-bold mb-2" %> | |
<%= form.{param1_type} :{param1}, class: "appearance-none border rounded w-full py-2 px-3 text-grey-darker", placeholder: "{param1_titlize}" %> | |
</div> | |
<div class="md:w-1/2 py-3 px-6 text-left whitespace-nowrap"> | |
<%= form.label :{param2}, class: "block uppercase tracking-wide text-grey-darker text-xs font-bold mb-2" %> | |
<%= form.{param2_type} :{param2}, class: "appearance-none border rounded w-full py-2 px-3 text-grey-darker", placeholder: "{param2_titlize}" %> | |
</div> | |
</div> | |
<div class="flex"> | |
<div class="md:w-1/2 py-3 px-6 text-left whitespace-nowrap"> | |
<%= form.label :{param3}, class: "block uppercase tracking-wide text-grey-darker text-xs font-bold mb-2" %> | |
<%= form.{param3_type} :{param3}, class: "appearance-none border rounded w-full py-2 px-3 text-grey-darker", placeholder: "{param3_titlize}" %> | |
</div> | |
<div class="md:w-1/2 py-3 px-6 text-left whitespace-nowrap"> | |
<%= form.label :{param4}, class: "block uppercase tracking-wide text-grey-darker text-xs font-bold mb-2" %> | |
<%= form.{param4_type} :{param4}, class: "appearance-none border rounded w-full py-2 px-3 text-grey-darker", placeholder: "{param4_titlize}" %> | |
</div> | |
</div> | |
<div class="flex"> | |
<div class="md:w-1/2 py-3 px-6 text-left whitespace-nowrap"> | |
<%= form.label :{param5}, class: "block uppercase tracking-wide text-grey-darker text-xs font-bold mb-2" %> | |
<%= form.{param5_type} :{param5}, class: "appearance-none border rounded w-full py-2 px-3 text-grey-darker", placeholder: "{param5_titlize}" %> | |
</div> | |
<div class="md:w-1/2 py-3 px-6 text-left whitespace-nowrap"> | |
<%= form.label :{param6}, class: "block uppercase tracking-wide text-grey-darker text-xs font-bold mb-2" %> | |
<%= form.{param6_type} :{param6}, class: "appearance-none border rounded w-full py-2 px-3 text-grey-darker", placeholder: "{param6_titlize}" %> | |
</div> | |
</div> | |
<div class="flex"> | |
<div class="md:w-1/2 py-3 px-6 text-left whitespace-nowrap"> | |
<%= form.label :{param7}, class: "block uppercase tracking-wide text-grey-darker text-xs font-bold mb-2" %> | |
<%= form.{param7_type} :{param7}, class: "appearance-none border rounded w-full py-2 px-3 text-grey-darker", placeholder: "{param7_titlize}" %> | |
</div> | |
<div class="md:w-1/2 py-3 px-6 text-left whitespace-nowrap"> | |
<%= form.label :{param8}, class: "block uppercase tracking-wide text-grey-darker text-xs font-bold mb-2" %> | |
<%= form.{param8_type} :{param8}, class: "appearance-none border rounded w-full py-2 px-3 text-grey-darker", placeholder: "{param8_titlize}" %> | |
</div> | |
</div> | |
<div class="py-3 px-6 text-left whitespace-nowrap"> | |
<%= form.label :{param9}, class: "block uppercase tracking-wide text-grey-darker text-xs font-bold mb-2" %> | |
<%= form.select :{param9}, {enum_class}, class: "appearance-none border rounded w-full py-2 px-3 text-grey-darker"%> | |
</div> | |
<%= form.submit class: "py-3 px-6 mx-6 my-3 text-white bg-purple-700 rounded-md focus:bg-purple-800 focus:outline-none" %> | |
</div> | |
</div> | |
<% end %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
json.extract! {ModelSingular}, :id, {model_params}, :created_at, :updated_at | |
json.url {ModelSingular}_url({ModelSingular}, format: :json) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Create{ModelPluralCamelize} < ActiveRecord::Migration[6.1] | |
def change | |
create_table :{ModelPlural}, id: :uuid do |t| | |
{ModelFields} | |
t.timestamps | |
end | |
{ModelIndexes} | |
{ModelReferences} | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="flex items-center justify-center font-sans"> | |
<div class="w-full"> | |
<header class="flex items-center justify-between"> | |
<h2 class="text-lg leading-6 font-medium text-purple-600">{plural_name_camelize} / <%= @{ModelSingular}.{ref_name} || 'Edit {ModelSingularCamelize}' %> </h2> | |
<%= link_to {plural_name}_path, class: "group flex items-center rounded-md text-sm font-medium hover:underline hover:text-purple-600 px-4 py-2" do %> | |
<span class="sr-only">Back</span> | |
<!-- Heroicon name: solid/chevron-left --> | |
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> | |
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" /> | |
</svg> | |
Back | |
<% end %> | |
</header> | |
<div class="bg-white shadow-md rounded mt-6"> | |
<%= render 'form', {ModelSingular}: @{ModelSingular} %> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<p id="notice"><%= notice %></p> | |
<%# https://tailwindcomponents.com/component/projects-table %> | |
<div class="flex items-center justify-center font-sans"> | |
<div class="w-full"> | |
<header class="flex items-center justify-between"> | |
<h2 class="text-lg leading-6 font-medium text-purple-600">{plural_name_camelize} <%= "/ Search results" if @search_value.present? %></h2> | |
<%= form_with(url: {plural_name}_path, method: :get, class: 'flex') do |form| %> | |
<%= form.search_field :search, class: "appearance-none border rounded py-2 px-3 text-grey-darker", placeholder: "Search {plural_name_camelize}" %> | |
<%= form.submit "Search", class: "ml-3 py-3 px-6 text-white bg-purple-700 rounded-md focus:bg-purple-800 focus:outline-none" %> | |
<% end %> | |
<%= link_to new_{ModelSingular}_path, class: "group flex items-center rounded-md text-sm font-medium hover:underline hover:text-purple-600 px-4 py-2" do %> | |
<svg class="mr-2" width="12" height="20" fill="currentColor"> | |
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 5a1 1 0 011 1v3h3a1 1 0 110 2H7v3a1 1 0 11-2 0v-3H2a1 1 0 110-2h3V6a1 1 0 011-1z"/> | |
</svg> | |
New {ModelSingularCamelize} | |
<% end %> | |
</header> | |
<div class="bg-white shadow-md rounded mt-6"> | |
<table class="min-w-max w-full table-auto"> | |
<thead> | |
<tr class="bg-gray-200 text-gray-600 uppercase text-sm leading-normal"> | |
<th class="py-3 px-6 text-left">Name</th> | |
<th class="py-3 px-6 text-left">Email</th> | |
<th class="py-3 px-6 text-center">Role</th> | |
<th class="py-3 px-6 text-center">Settings</th> | |
<th class="py-3 px-6 text-center">Actions</th> | |
</tr> | |
</thead> | |
<tbody class="text-gray-600 text-sm font-light"> | |
<% @{plural_name}.each do |{ModelSingular}| %> | |
<tr class="border-b border-gray-200 hover:bg-gray-100"> | |
<td class="py-3 px-6 text-left whitespace-nowrap"> | |
<div class="flex items-center"> | |
<div class="mr-2"> | |
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" | |
width="24" height="24" | |
viewBox="0 0 48 48" | |
style=" fill:#000000;"> | |
<path fill="#80deea" d="M24,34C11.1,34,1,29.6,1,24c0-5.6,10.1-10,23-10c12.9,0,23,4.4,23,10C47,29.6,36.9,34,24,34z M24,16 c-12.6,0-21,4.1-21,8c0,3.9,8.4,8,21,8s21-4.1,21-8C45,20.1,36.6,16,24,16z"></path><path fill="#80deea" d="M15.1,44.6c-1,0-1.8-0.2-2.6-0.7C7.6,41.1,8.9,30.2,15.3,19l0,0c3-5.2,6.7-9.6,10.3-12.4c3.9-3,7.4-3.9,9.8-2.5 c2.5,1.4,3.4,4.9,2.8,9.8c-0.6,4.6-2.6,10-5.6,15.2c-3,5.2-6.7,9.6-10.3,12.4C19.7,43.5,17.2,44.6,15.1,44.6z M32.9,5.4 c-1.6,0-3.7,0.9-6,2.7c-3.4,2.7-6.9,6.9-9.8,11.9l0,0c-6.3,10.9-6.9,20.3-3.6,22.2c1.7,1,4.5,0.1,7.6-2.3c3.4-2.7,6.9-6.9,9.8-11.9 c2.9-5,4.8-10.1,5.4-14.4c0.5-4-0.1-6.8-1.8-7.8C34,5.6,33.5,5.4,32.9,5.4z"></path><path fill="#80deea" d="M33,44.6c-5,0-12.2-6.1-17.6-15.6C8.9,17.8,7.6,6.9,12.5,4.1l0,0C17.4,1.3,26.2,7.8,32.7,19 c3,5.2,5,10.6,5.6,15.2c0.7,4.9-0.3,8.3-2.8,9.8C34.7,44.4,33.9,44.6,33,44.6z M13.5,5.8c-3.3,1.9-2.7,11.3,3.6,22.2 c6.3,10.9,14.1,16.1,17.4,14.2c1.7-1,2.3-3.8,1.8-7.8c-0.6-4.3-2.5-9.4-5.4-14.4C24.6,9.1,16.8,3.9,13.5,5.8L13.5,5.8z"></path><circle cx="24" cy="24" r="4" fill="#80deea"></circle> | |
</svg> | |
</div> | |
<span class="font-medium"><%= {ModelSingular}.name %></span> | |
</div> | |
</td> | |
<td class="py-3 px-6 text-left truncate"> | |
<div class="flex items-center"> | |
<span><%= {ModelSingular}.email %></span> | |
</div> | |
</td> | |
<td class="py-3 px-6 text-center"> | |
<span class="<%= class_roles({ModelSingular}.role) %>"> | |
<%= {ModelSingular}.role %> | |
</span> | |
</td> | |
<td class="py-3 px-6 text-left whitespace-nowrap"> | |
<div class="flex items-center justify-center"> | |
<img class="w-6 h-6 rounded-full border-gray-200 border transform hover:scale-125" src="https://randomuser.me/api/portraits/men/1.jpg"/> | |
<img class="w-6 h-6 rounded-full border-gray-200 border -m-1 transform hover:scale-125" src="https://randomuser.me/api/portraits/women/2.jpg"/> | |
<img class="w-6 h-6 rounded-full border-gray-200 border -m-1 transform hover:scale-125" src="https://randomuser.me/api/portraits/men/3.jpg"/> | |
</div> | |
</td> | |
<td class="py-3 px-6 text-center"> | |
<div class="flex item-center justify-center"> | |
<%= link_to {ModelSingular}, class: "w-4 mr-2 transform hover:text-purple-500 hover:scale-110" do %> | |
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> | |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" /> | |
</svg> | |
<% end %> | |
<%= link_to edit_{ModelSingular}_path({ModelSingular}), class: "w-4 mr-2 transform hover:text-purple-500 hover:scale-110" do %> | |
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" /> | |
</svg> | |
<% end %> | |
<%= link_to {ModelSingular}, method: :delete, data: { confirm: 'Are you sure?' }, class: "w-4 mr-2 transform hover:text-purple-500 hover:scale-110" do %> | |
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | |
</svg> | |
<% end %> | |
</div> | |
</td> | |
</tr> | |
<% end %> | |
</tbody> | |
</table> | |
<div class="bg-white px-4 py-3 flex items-center justify-between border-t border-gray-200 sm:px-6"> | |
<div class="flex-1 flex justify-between sm:hidden"> | |
<a href="#" class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:text-gray-500"> | |
Previous | |
</a> | |
<a href="#" class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:text-gray-500"> | |
Next | |
</a> | |
</div> | |
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between"> | |
<div> | |
<nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination"> | |
<%= link_to {plural_name}_path(page_num: @pagy.prev || @pagy.page, search: @search_value), class: "relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 disabled:opacity-25", disabled: @pagy.prev.nil? do %> | |
<span class="sr-only">Previous</span> | |
<!-- Heroicon name: solid/chevron-left --> | |
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> | |
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" /> | |
</svg> | |
<% end %> | |
<% @pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] -%> | |
<% if item.is_a?(Integer) -%> | |
<%= link_to item.to_s, {plural_name}_path(page_num: item, search: @search_value), class: "relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50" %> | |
<% elsif item.is_a?(String) -%> | |
<%= link_to item, {plural_name}_path(page_num: item.to_i, search: @search_value), class: "relative inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-purple-600 hover:bg-purple-700" %> | |
<% elsif item == :gap -%> | |
<span class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700"> | |
... | |
</span> | |
<% end -%> | |
<% end -%> | |
<%= link_to {plural_name}_path(page_num: @pagy.next || @pagy.page, search: @search_value), class: "relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 disabled:opacity-25", disabled: @pagy.next.nil? do %> | |
<span class="sr-only">Next</span> | |
<!-- Heroicon name: solid/chevron-right --> | |
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> | |
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" /> | |
</svg> | |
<% end %> | |
</nav> | |
</div> | |
</div> | |
<div> | |
<% if @search_value.present? %> | |
<%= link_to {plural_name}_path, class: "group flex items-center rounded-md text-sm font-medium hover:underline hover:text-purple-600 px-4 py-2" do %> | |
<< Back | |
<% end %> | |
<% end %> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
json.array! @{plural_name}, partial: "{plural_name}/{ModelSingular}", as: :{ModelSingular} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MMVCRGenerator < Rails::Generators::NamedBase | |
source_root File.expand_path('templates', __dir__) | |
class_option :search_fields, type: :string, default: 'name, id' | |
def create_model_file | |
timestamp = Time.now.strftime("%Y%m%d%H%M%S") | |
built_model = build_model_from_json | |
copy_file "models/model.rb", "app/models/#{plural_name.singularize}.rb" | |
gsub_file "app/models/#{plural_name.singularize}.rb", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
end | |
def create_migration_file | |
timestamp = Time.now.strftime("%Y%m%d%H%M%S") | |
built_model = build_model_from_json | |
copy_file "migrations/create_models.rb", "db/migrate/#{timestamp}_create_#{plural_name}.rb" | |
gsub_file "db/migrate/#{timestamp}_create_#{plural_name}.rb", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
gsub_file "db/migrate/#{timestamp}_create_#{plural_name}.rb", "{ModelPlural}", "#{plural_name}" | |
gsub_file "db/migrate/#{timestamp}_create_#{plural_name}.rb", "{ModelFields}", "#{built_model[0].join("\n")}" | |
gsub_file "db/migrate/#{timestamp}_create_#{plural_name}.rb", "{ModelIndexes}", "#{built_model[1].join("\n")}" | |
gsub_file "db/migrate/#{timestamp}_create_#{plural_name}.rb", "{ModelReferences}", "#{built_model[2].join("\n")}" | |
end | |
def create_peparizer_search_file | |
copy_file "services/search/models.rb", "app/services/search/#{file_name}.rb" | |
gsub_file "app/services/search/#{file_name}.rb", "{ModelPlural}", "#{plural_name.camelize}" | |
gsub_file "app/services/search/#{file_name}.rb", "{ModelSingular}", "#{plural_name.camelize.singularize}" | |
gsub_file "app/services/search/#{file_name}.rb", "{value1}", "#{options['search_fields'].split(',').first}" | |
gsub_file "app/services/search/#{file_name}.rb", "{value2}", "#{options['search_fields'].split(',').second}" | |
end | |
def create_peparizer_controller_file | |
copy_file "controllers/models_controller.rb", "app/controllers/#{file_name}_controller.rb" | |
gsub_file "app/controllers/#{file_name}_controller.rb", "{ModelPlural}", "#{plural_name}" | |
gsub_file "app/controllers/#{file_name}_controller.rb", "{ModelSingular}", "#{plural_name.singularize}" | |
gsub_file "app/controllers/#{file_name}_controller.rb", "{ModelSingularCamelize}", "#{plural_name.camelize.singularize}" | |
gsub_file "app/controllers/#{file_name}_controller.rb", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
gsub_file "app/controllers/#{file_name}_controller.rb", "{ModelParams}", "#{options['params']}" | |
end | |
def create_views_files | |
copy_file "views/models/_form.html.erb", "app/views/#{file_name}/_form.html.erb" | |
copy_file "views/models/_user.json.jbuilder", "app/views/#{file_name}/_#{file_name.singularize}.json.jbuilder" | |
copy_file "views/models/edit.html.erb", "app/views/#{file_name}/edit.html.erb" | |
copy_file "views/models/index.html.erb", "app/views/#{file_name}/index.html.erb" | |
copy_file "views/models/index.json.jbuilder", "app/views/#{file_name}/index.json.jbuilder" | |
copy_file "views/models/new.html.erb", "app/views/#{file_name}/new.html.erb" | |
copy_file "views/models/show.html.erb", "app/views/#{file_name}/show.html.erb" | |
copy_file "views/models/show.json.jbuilder", "app/views/#{file_name}/show.json.jbuilder" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{ModelPlural}", "#{plural_name}" | |
gsub_file "app/views/#{file_name}/_#{file_name.singularize}.json.jbuilder", "{ModelPlural}", "#{plural_name}" | |
gsub_file "app/views/#{file_name}/edit.html.erb", "{ModelPlural}", "#{plural_name}" | |
gsub_file "app/views/#{file_name}/index.html.erb", "{ModelPlural}", "#{plural_name}" | |
gsub_file "app/views/#{file_name}/index.json.jbuilder", "{ModelPlural}", "#{plural_name}" | |
gsub_file "app/views/#{file_name}/new.html.erb", "{ModelPlural}", "#{plural_name}" | |
gsub_file "app/views/#{file_name}/show.html.erb", "{ModelPlural}", "#{plural_name}" | |
gsub_file "app/views/#{file_name}/show.json.jbuilder", "{ModelPlural}", "#{plural_name}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
gsub_file "app/views/#{file_name}/_#{file_name.singularize}.json.jbuilder", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
gsub_file "app/views/#{file_name}/edit.html.erb", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
gsub_file "app/views/#{file_name}/index.html.erb", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
gsub_file "app/views/#{file_name}/index.json.jbuilder", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
gsub_file "app/views/#{file_name}/new.html.erb", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
gsub_file "app/views/#{file_name}/show.html.erb", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
gsub_file "app/views/#{file_name}/show.json.jbuilder", "{ModelPluralCamelize}", "#{plural_name.camelize}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{ModelSingular}", "#{plural_name.singularize}" | |
gsub_file "app/views/#{file_name}/_#{file_name.singularize}.json.jbuilder", "{ModelSingular}", "#{plural_name.singularize}" | |
gsub_file "app/views/#{file_name}/edit.html.erb", "{ModelSingular}", "#{plural_name.singularize}" | |
gsub_file "app/views/#{file_name}/index.html.erb", "{ModelSingular}", "#{plural_name.singularize}" | |
gsub_file "app/views/#{file_name}/index.json.jbuilder", "{ModelSingular}", "#{plural_name.singularize}" | |
gsub_file "app/views/#{file_name}/new.html.erb", "{ModelSingular}", "#{plural_name.singularize}" | |
gsub_file "app/views/#{file_name}/show.html.erb", "{ModelSingular}", "#{plural_name.singularize}" | |
gsub_file "app/views/#{file_name}/show.json.jbuilder", "{ModelSingular}", "#{plural_name.singularize}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{ModelSingularCamelize}", "#{plural_name.singularize.camelize}" | |
gsub_file "app/views/#{file_name}/_#{file_name.singularize}.json.jbuilder", "{ModelSingularCamelize}", "#{plural_name.singularize.camelize}" | |
gsub_file "app/views/#{file_name}/edit.html.erb", "{ModelSingularCamelize}", "#{plural_name.singularize.camelize}" | |
gsub_file "app/views/#{file_name}/index.html.erb", "{ModelSingularCamelize}", "#{plural_name.singularize.camelize}" | |
gsub_file "app/views/#{file_name}/index.json.jbuilder", "{ModelSingularCamelize}", "#{plural_name.singularize.camelize}" | |
gsub_file "app/views/#{file_name}/new.html.erb", "{ModelSingularCamelize}", "#{plural_name.singularize.camelize}" | |
gsub_file "app/views/#{file_name}/show.html.erb", "{ModelSingularCamelize}", "#{plural_name.singularize.camelize}" | |
gsub_file "app/views/#{file_name}/show.json.jbuilder", "{ModelSingularCamelize}", "#{plural_name.singularize.camelize}" | |
end | |
def create_form_file_params | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param1}", "#{form_params[0][:param]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param2}", "#{form_params[1][:param]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param3}", "#{form_params[2][:param]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param4}", "#{form_params[3][:param]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param5}", "#{form_params[4][:param]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param6}", "#{form_params[5][:param]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param7}", "#{form_params[6][:param]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param8}", "#{form_params[7][:param]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param9}", "#{form_params[8][:param]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param1_type}", "#{form_params[0][:param_type]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param2_type}", "#{form_params[1][:param_type]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param3_type}", "#{form_params[2][:param_type]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param4_type}", "#{form_params[3][:param_type]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param5_type}", "#{form_params[4][:param_type]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param6_type}", "#{form_params[5][:param_type]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param7_type}", "#{form_params[6][:param_type]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param8_type}", "#{form_params[7][:param_type]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param1_titlize}", "#{form_params[0][:param_titlize]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param2_titlize}", "#{form_params[1][:param_titlize]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param3_titlize}", "#{form_params[2][:param_titlize]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param4_titlize}", "#{form_params[3][:param_titlize]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param5_titlize}", "#{form_params[4][:param_titlize]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param6_titlize}", "#{form_params[5][:param_titlize]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param7_titlize}", "#{form_params[6][:param_titlize]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{param8_titlize}", "#{form_params[7][:param_titlize]}" | |
gsub_file "app/views/#{file_name}/_form.html.erb", "{enum_class}", "#{enum_class}" | |
end | |
private | |
def build_model_from_json | |
fields = [] | |
idxs = [] | |
refs = [] | |
model_name = plural_name.singularize | |
hash.each do |key, value| | |
next if key == :_refs || key == :_idxs | |
fields.append("t.#{value[:type]} :#{key}, #{aux_field(value.except(:type))}") | |
end | |
hash[:_idxs].each do |idxs_hash| | |
idxs.append("add_index :#{plural_name}, :#{idxs_hash[:field]}, #{aux_field(idxs_hash.except(:field))}") | |
end | |
hash[:_refs].each do |refs_hash| | |
refs.append("add_reference :#{plural_name}, :#{refs_hash[:field]}, #{aux_field(refs_hash.except(:field))}") | |
end | |
return [fields, idxs, refs] | |
end | |
def aux_field(field) | |
field_str = field.map do |key, value| | |
"#{key}:#{value}" unless value.nil? | |
end | |
return field_str.join(', ')[0...-2] if field_str.size > 1 | |
field_str | |
end | |
def enum_class | |
User::ROLES.keys | |
end | |
def form_params | |
[ | |
{ | |
key: 1, | |
param: 'name', | |
param_type: 'text_field', | |
param_titlize: 'Name' | |
}, | |
{ | |
key: 2, | |
param: 'first_name', | |
param_type: 'text_field', | |
param_titlize: 'First Name' | |
}, | |
{ | |
key: 3, | |
param: 'last_name', | |
param_type: 'text_field', | |
param_titlize: 'Last Name' | |
}, | |
{ | |
key: 4, | |
param: 'email', | |
param_type: 'email_field', | |
param_titlize: 'Name' | |
}, | |
{ | |
key: 5, | |
param: 'password', | |
param_type: 'password_field', | |
param_titlize: 'Password' | |
}, | |
{ | |
key: 6, | |
param: 'password_confirmation', | |
param_type: 'password_field', | |
param_titlize: 'Password confirmation' | |
}, | |
{ | |
key: 7, | |
param: 'phone_number', | |
param_type: 'telephone_field', | |
param_titlize: 'Phone number' | |
}, | |
{ | |
key: 8, | |
param: 'address', | |
param_type: 'text_area', | |
param_titlize: 'Address' | |
}, | |
{ | |
key: 9, | |
param: 'role' | |
} | |
] | |
end | |
def hash | |
{ | |
name: { | |
type: 'string', | |
null: false | |
}, | |
first_name: { | |
type: 'string', | |
null: false | |
}, | |
last_name: { | |
type: 'string', | |
null: false | |
}, | |
email: { | |
type: 'string', | |
null: false | |
}, | |
password: { | |
type: 'string', | |
null: false | |
}, | |
password_confirmation: { | |
type: 'string', | |
null: false | |
}, | |
phone_number: { | |
type: 'string', | |
null: false | |
}, | |
address: { | |
type: 'text', | |
null: false | |
}, | |
role: { | |
type: 'integer', | |
null: false, | |
default: 0 | |
}, | |
settings: { | |
type: 'hstore', | |
null: false, | |
default: {} | |
}, | |
_idxs: [ | |
{ | |
field: 'name', | |
unique: true | |
}, | |
{ | |
field: 'email', | |
unique: true | |
} | |
], | |
_refs: [] | |
} | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class {ModelPluralCamelize}Controller < ApplicationController | |
before_action :set_{ModelSingular}, only: %i[ show edit update destroy ] | |
# GET /{ModelPlural} or /{ModelPlural}.json | |
def index | |
{ModelPlural} ||= Search::{ModelPluralCamelize}.new(params).find | |
@search_value = params[:search] if params.has_key?(:search) | |
@pagy, @{ModelPlural} = pagy({ModelPlural}, items: 10) | |
end | |
# GET /{ModelPlural}/1 or /{ModelPlural}/1.json | |
def show | |
end | |
# GET /{ModelPlural}/new | |
def new | |
@{ModelSingular} = {ModelSingularCamelize}.new | |
end | |
# GET /{ModelPlural}/1/edit | |
def edit | |
end | |
# POST /{ModelPlural} or /{ModelPlural}.json | |
def create | |
@{ModelSingular} = {ModelSingularCamelize}.new({ModelSingular}_params) | |
respond_to do |format| | |
if @{ModelSingular}.save | |
format.html { redirect_to @{ModelSingular}, notice: "{ModelSingularCamelize} was successfully created." } | |
format.json { render :show, status: :created, location: @{ModelSingular} } | |
else | |
format.html { render :new, status: :unprocessable_entity } | |
format.json { render json: @{ModelSingular}.errors, status: :unprocessable_entity } | |
end | |
end | |
end | |
# PATCH/PUT /{ModelPlural}/1 or /{ModelPlural}/1.json | |
def update | |
respond_to do |format| | |
if @{ModelSingular}.update({ModelSingular}_params) | |
format.html { redirect_to @{ModelSingular}, notice: "{ModelSingularCamelize} was successfully updated." } | |
format.json { render :show, status: :ok, location: @{ModelSingular} } | |
else | |
format.html { render :edit, status: :unprocessable_entity } | |
format.json { render json: @{ModelSingular}.errors, status: :unprocessable_entity } | |
end | |
end | |
end | |
# DELETE /{ModelPlural}/1 or /{ModelPlural}/1.json | |
def destroy | |
@{ModelSingular}.destroy | |
respond_to do |format| | |
format.html { redirect_to {ModelPlural}_url, notice: "{ModelSingularCamelize} was successfully destroyed." } | |
format.json { head :no_content } | |
end | |
end | |
private | |
# Use callbacks to share common setup or constraints between actions. | |
def set_{ModelSingular} | |
@{ModelSingular} = {ModelSingularCamelize}.find(params[:id]) | |
end | |
# Only allow a list of trusted parameters through. | |
def {ModelSingular}_params | |
params.require(:{ModelSingular}).permit({ModelParams}) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="flex items-center justify-center font-sans"> | |
<div class="w-full"> | |
<header class="flex items-center justify-between"> | |
<h2 class="text-lg leading-6 font-medium text-purple-600">{plural_name_camelize} / <%= @{ModelSingular}.{ref_name_1} || 'New {ModelSingularCamelize}' %> </h2> | |
<%= link_to {plural_name}_path, class: "group flex items-center rounded-md text-sm font-medium hover:underline hover:text-purple-600 px-4 py-2" do %> | |
<span class="sr-only">Back</span> | |
<!-- Heroicon name: solid/chevron-left --> | |
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> | |
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" /> | |
</svg> | |
Back | |
<% end %> | |
</header> | |
<div class="bg-white shadow-md rounded mt-6"> | |
<%= render 'form', {ModelSingular}: @{ModelSingular} %> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Search | |
class {ModelPlural} | |
def initialize(params) | |
@params = params | |
@{value1} = {ModelSingular}.arel_table[:{value1}] | |
@{value2} = {ModelSingular}.arel_table[:{value2}] | |
end | |
def find | |
if(@params.has_key?(:search)) | |
{ModelSingular}.where(@{value2}.matches("%#{@params[:search]}%")) | |
.or({ModelSingular}.where(@{value1}.matches("%#{@params[:search]}%"))) | |
else | |
{ModelSingular}.all | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<p id="notice"><%= notice %></p> | |
<div class="flex items-center justify-center font-sans"> | |
<div class="w-full"> | |
<header class="flex items-center justify-between"> | |
<h2 class="text-lg leading-6 font-medium text-purple-600">{plural_name_camelize} / <%= @{ModelSingular}.name %></h2> | |
<div class="flex"> | |
<%= link_to edit_{ModelSingular}_path(@{ModelSingular}), class: "group flex items-center rounded-md text-sm font-medium hover:underline hover:text-purple-600 px-4 py-2" do %> | |
Edit {ModelSingular} | |
<% end %> | |
<%= link_to {plural_name}_path, class: "group flex items-center rounded-md text-sm font-medium hover:underline hover:text-purple-600 px-4 py-2" do %> | |
Back to all {plural_name} | |
<% end %> | |
</div> | |
</header> | |
<div class="bg-white shadow-md rounded mt-6"> | |
<div class="min-w-max w-full table-auto"> | |
<div> | |
<div class="bg-gray-200 text-gray-600 uppercase text-sm leading-normal"> | |
<div class="py-3 px-6 text-left"><%= @{ModelSingular}.name %></div> | |
</div> | |
</div> | |
<div class="text-gray-600 text-sm font-light"> | |
<div class="border-b border-gray-200"> | |
<div class="flex p-1"> | |
<div class="flex-none w-44 relative"> | |
<%= image_tag("undraw_unicorn_dp2f.svg", alt: "", class: "absolute inset-0 w-full h-full object-cover") %> | |
</div> | |
<form class="flex-auto py-7 px-8"> | |
<div class="flex flex-wrap items-baseline"> | |
<h1 class="w-full flex-none text-3xl text-black mb-1.5"> | |
<%= @{ModelSingular}.{ref_name_1} %> | |
</h1> | |
<div class="text-lg leading-6 text-black"> | |
<%= @{ModelSingular}.{ref_name_2} %> | |
</div> | |
<div class="text-sm text-gray-500 ml-3"> | |
<%= @{ModelSingular}.{ref_name_3} %> | |
</div> | |
</div> | |
<div class="flex space-x-3 mt-3 mb-3 text-sm font-semibold uppercase"> | |
<div class="flex-auto flex space-x-3"> | |
<button class="w-1/2 flex items-center justify-center bg-purple-700 text-white" type="submit">Buy now</button> | |
<button class="w-1/2 flex items-center justify-center border border-purple-200" type="button">Add to bag</button> | |
</div> | |
<button class="flex-none flex items-center justify-center w-12 h-12 text-purple-900 border border-purple-200" type="button" aria-label="like"> | |
<svg width="20" height="20" fill="currentColor"> | |
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.172 5.172a4 4 0 015.656 0L10 6.343l1.172-1.171a4 4 0 115.656 5.656L10 17.657l-6.828-6.829a4 4 0 010-5.656z" /> | |
</svg> | |
</button> | |
</div> | |
<p class="text-sm text-purple-500"> | |
{ModelSingularCamelize} can create children. | |
</p> | |
</form> | |
</div> | |
</div> | |
<section class="px-4 sm:px-6 lg:px-4 xl:px-6 pt-4 pb-4 sm:pb-6 lg:pb-4 xl:pb-6 space-y-4"> | |
<header class="flex items-center justify-between"> | |
<h2 class="text-lg leading-6 font-medium text-black">{child_name_pluralize_camelize}</h2> | |
<%= link_to new_{child_name}_path({{ModelSingular}_id: @{ModelSingular}.id}), class: "hover:bg-purple-200 hover:text-purple-800 group flex items-center rounded-md bg-purple-100 text-purple-600 text-sm font-medium px-4 py-2" do %> | |
<svg class="group-hover:text-purple-600 text-purple-500 mr-2" width="12" height="20" fill="currentColor"> | |
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 5a1 1 0 011 1v3h3a1 1 0 110 2H7v3a1 1 0 11-2 0v-3H2a1 1 0 110-2h3V6a1 1 0 011-1z"/> | |
</svg> | |
Create New {child_name_camelize} | |
<% end %> | |
</header> | |
<ul class="flex"> | |
<% @{ModelSingular}.{child_name}.each do |{child_name}| %> | |
<%= link_to {child_name} do %> | |
<li class="ml-2 hover:bg-purple-500 hover:border-transparent hover:shadow-lg hover:text-white group rounded-lg p-4 border border-gray-200 cursor-pointer"> | |
<p class="group-hover:text-white leading-6 font-medium text-black"><%= {child_name}.{child_ref_name_1} %></p> | |
<p class="text-sm font-medium sm:mb-4 lg:mb-0 xl:mb-4"><%= {child_name}.{child_ref_name_2} %></p> | |
<li> | |
<% end %> | |
<% end %> | |
</ul> | |
</section> | |
</div> | |
</div> | |
<div class="bg-white px-4 py-3 flex items-center justify-between border-t border-gray-200 sm:px-6"> | |
<div> | |
<%= link_to 'Settings', @{ModelSingular}, class: "group flex items-center rounded-md text-sm font-medium hover:underline hover:text-purple-600 px-4 py-2" %> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
json.partial! "{plural_name}/{ModelSingular}", {ModelSingular}: @{ModelSingular} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Description: | |
Generator for Model, Migration, View, Controller and Relationships. | |
Example: | |
bin/rails generate peparizer some_model_in_plural [options] | |
--search_fields ':field1, :field2' # only two fields | |
This will create: | |
search service | |
controller | |
model | |
views |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment