{"id":15463547,"url":"https://github.com/ntamvl/rails_custom_view_scaffold_example","last_synced_at":"2025-10-07T03:31:32.846Z","repository":{"id":83971111,"uuid":"329217971","full_name":"ntamvl/rails_custom_view_scaffold_example","owner":"ntamvl","description":"Customize view scaffolding template in Rails 6 using Bootstrap 5","archived":false,"fork":false,"pushed_at":"2021-01-15T08:47:29.000Z","size":529,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-12T22:33:53.685Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ntamvl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-13T06:44:42.000Z","updated_at":"2024-02-21T10:48:01.000Z","dependencies_parsed_at":"2023-04-10T08:46:47.775Z","dependency_job_id":null,"html_url":"https://github.com/ntamvl/rails_custom_view_scaffold_example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntamvl%2Frails_custom_view_scaffold_example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntamvl%2Frails_custom_view_scaffold_example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntamvl%2Frails_custom_view_scaffold_example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntamvl%2Frails_custom_view_scaffold_example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ntamvl","download_url":"https://codeload.github.com/ntamvl/rails_custom_view_scaffold_example/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235575694,"owners_count":19012157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-02T00:21:52.901Z","updated_at":"2025-10-07T03:31:27.474Z","avatar_url":"https://github.com/ntamvl.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rails Custom View Scaffold Example\nCustomize view scaffolding template using Bootstrap 5\n\nWe will do in this example:\n- Create new new the Ruby on Rails project using version 6.1.1\n- Locate Railties path\n- Customize the scaffold template\n- Add Boostrap version 5.0.0-beta1\n- Generate scaffold for category and article \n- Run project and see the result\n\n![Rails Custom View Scaffold Example](https://raw.githubusercontent.com/ntamvl/rails_custom_view_scaffold_example/master/screenshot.png)\n\n## Create new project\n```\ncd\nrails _6.1.1_ new rails_custom_view_scaffold_example\n```\n\n## Locate the existing template\n\nThe existing scaffolding templates are under the railties directory, located in:\n\n```bash\n[railties directory path]/lib/rails/generators/erb/scaffold/templates\n```\n\nRun this command to show where railties is located\n\n```bash\nbundle info railties\n\nOR\n\nbundle show railties\n```\n\n**Example in my pc:**\n\n```bash\nbundle info railties\n  * railties (6.1.1)\n  Summary: Tools for creating, working with, and running Rails applications.\n  Homepage: https://rubyonrails.org\n  Documentation: https://api.rubyonrails.org/v6.1.1/\n  Source Code: https://github.com/rails/rails/tree/v6.1.1/railties\n  Changelog: https://github.com/rails/rails/blob/v6.1.1/railties/CHANGELOG.md\n  Bug Tracker: https://github.com/rails/rails/issues\n  Mailing List: https://discuss.rubyonrails.org/c/rubyonrails-talk\n  Path: /Users/tamnguyen/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/railties-6.1.1\n```\n\nWe found railties path is: \n```\n/Users/tamnguyen/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/railties-6.1.1\n```\n\nThen we get the scaffolding templates path:\n\n```bash\n/Users/tamnguyen/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/railties-6.1.1/lib/rails/generators/erb/scaffold/templates\n```\n\n**List folder in the existing scaffold template:**\n```bash\nls -l /Users/tamnguyen/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/railties-6.1.1/lib/rails/generators/erb/scaffold/templates\ntotal 40\ndrwxr-xr-x  7 tamnguyen  staff   224 Jan  8 10:01 .\ndrwxr-xr-x  4 tamnguyen  staff   128 Jan  8 10:01 ..\n-rw-rw-r--  1 tamnguyen  staff  1195 Jan  8 10:01 _form.html.erb.tt\n-rw-rw-r--  1 tamnguyen  staff   237 Jan  8 10:01 edit.html.erb.tt\n-rw-rw-r--  1 tamnguyen  staff   974 Jan  8 10:01 index.html.erb.tt\n-rw-rw-r--  1 tamnguyen  staff   179 Jan  8 10:01 new.html.erb.tt\n-rw-rw-r--  1 tamnguyen  staff   903 Jan  8 10:01 show.html.erb.tt\n```\n\n## Copy and customize the scaffold template\nWe should copy the existing scaffold template to path `lib/templates/erb/scaffold` in the project folder\nWe should have the lib folder in the project:\n```\nlib/templates/erb/scaffold/_form.html.erb.tt\nlib/templates/erb/scaffold/edit.html.erb.tt\nlib/templates/erb/scaffold/index.html.erb.tt\nlib/templates/erb/scaffold/new.html.erb.tt\nlib/templates/erb/scaffold/show.html.erb.tt\n```\n\n**Following these commands to get this:**\n```\nmkdir -p lib/templates/erb/scaffold\ncp /Users/tamnguyen/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/railties-6.1.1/lib/rails/generators/erb/scaffold/templates/*.* lib/templates/erb/scaffold\n```\n\n*Then we open files `*.erb.tt` to customize base on Bootstrap 5*\n\n**File _form.html.erb.tt**\n```erb\n\u003c%%= form_with(model: \u003c%= model_resource_name %\u003e) do |form| %\u003e\n  \u003c%% if \u003c%= singular_table_name %\u003e.errors.any? %\u003e\n    \u003cdiv id=\"error_explanation\"\u003e\n      \u003ch2\u003e\u003c%%= pluralize(\u003c%= singular_table_name %\u003e.errors.count, \"error\") %\u003e prohibited this \u003c%= singular_table_name %\u003e from being saved:\u003c/h2\u003e\n\n      \u003cul\u003e\n        \u003c%% \u003c%= singular_table_name %\u003e.errors.each do |error| %\u003e\n          \u003cli\u003e\u003c%%= error.full_message %\u003e\u003c/li\u003e\n        \u003c%% end %\u003e\n      \u003c/ul\u003e\n    \u003c/div\u003e\n  \u003c%% end %\u003e\n\n\u003c% attributes.each do |attribute| -%\u003e\n  \u003cdiv class=\"form-group mb-3\"\u003e\n\u003c% if attribute.password_digest? -%\u003e\n    \u003c%%= form.label :password, class: \"form-label\" %\u003e\n    \u003c%%= form.password_field :password, class:\"form-control\" %\u003e\n  \u003c/div\u003e\n\n  \u003cdiv class=\"form-group mb-3\"\u003e\n    \u003c%%= form.label :password_confirmation, class: \"form-label\" %\u003e\n    \u003c%%= form.password_field :password_confirmation, class:\"form-control\" %\u003e\n\u003c% elsif attribute.attachments? -%\u003e\n    \u003c%%= form.label :\u003c%= attribute.column_name %\u003e, class: \"form-label\" %\u003e\n    \u003c%%= form.\u003c%= attribute.field_type %\u003e :\u003c%= attribute.column_name %\u003e, multiple: true %\u003e\n\u003c% elsif attribute.type == :boolean -%\u003e\n    \u003c%%= form.label :\u003c%= attribute.column_name %\u003e, class: \"form-check-label\" %\u003e\n    \u003c%%= form.\u003c%= attribute.field_type %\u003e :\u003c%= attribute.column_name %\u003e, class:\"form-check-input\" %\u003e\n\u003c% elsif attribute.reference? -%\u003e\n    \u003c%%= form.label :\u003c%= attribute.column_name %\u003e %\u003e\n    \u003c%%= form.collection_select :\u003c%= attribute.column_name %\u003e, \u003c%= attribute.name.camelize %\u003e.all, :id, :name, { prompt: true }, { class: \"form-select\" }  %\u003e\n\u003c% else -%\u003e\n    \u003c%%= form.label :\u003c%= attribute.column_name %\u003e, class: \"form-label\" %\u003e\n    \u003c%%= form.\u003c%= attribute.field_type %\u003e :\u003c%= attribute.column_name %\u003e, class:\"form-control\" %\u003e\n\u003c% end -%\u003e\n  \u003c/div\u003e\n\n\u003c% end -%\u003e\n  \u003cdiv class=\"form-group mb-3\"\u003e\n    \u003c%%= form.submit class: 'btn btn-primary' %\u003e\n  \u003c/div\u003e\n\u003c%% end %\u003e\n\n```\n\n**File edit.html.erb.tt**\n```erb\n\u003cdiv class=\"container-fluid\"\u003e\n  \u003ch1\u003eEditing \u003c%= singular_table_name.titleize %\u003e\u003c/h1\u003e\n\n  \u003c%%= render 'form', \u003c%= singular_table_name %\u003e: @\u003c%= singular_table_name %\u003e %\u003e\n\n  \u003c%%= link_to 'Show', @\u003c%= singular_table_name %\u003e, class: \"btn btn-primary\" %\u003e |\n  \u003c%%= link_to 'Back', \u003c%= index_helper %\u003e_path, class: \"btn btn-secondary\" %\u003e\n\u003c/div\u003e\n\n```\n\n**File index.html.erb.tt**\n```erb\n\u003cdiv class=\"container-fluid\"\u003e\n  \u003cp id=\"notice\"\u003e\u003c%%= notice %\u003e\u003c/p\u003e\n\n  \u003ch1\u003e\u003c%= plural_table_name.titleize %\u003e\u003c/h1\u003e\n\n  \u003ctable class=\"table\"\u003e\n    \u003cthead\u003e\n      \u003ctr\u003e\n  \u003c% attributes.reject(\u0026:password_digest?).each do |attribute| -%\u003e\n        \u003cth\u003e\u003c%= attribute.human_name %\u003e\u003c/th\u003e\n  \u003c% end -%\u003e\n        \u003cth colspan=\"3\"\u003e\u003c/th\u003e\n      \u003c/tr\u003e\n    \u003c/thead\u003e\n\n    \u003ctbody\u003e\n      \u003c%% @\u003c%= plural_table_name %\u003e.each do |\u003c%= singular_table_name %\u003e| %\u003e\n        \u003ctr\u003e\n  \u003c% attributes.reject(\u0026:password_digest?).each do |attribute| -%\u003e\n          \u003ctd\u003e\u003c%%= \u003c%= singular_table_name %\u003e.\u003c%= attribute.column_name %\u003e %\u003e\u003c/td\u003e\n  \u003c% end -%\u003e\n          \u003ctd\u003e\u003c%%= link_to 'Show', \u003c%= model_resource_name %\u003e %\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003c%%= link_to 'Edit', edit_\u003c%= singular_route_name %\u003e_path(\u003c%= singular_table_name %\u003e) %\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003c%%= link_to 'Destroy', \u003c%= model_resource_name %\u003e, method: :delete, data: { confirm: 'Are you sure?' } %\u003e\u003c/td\u003e\n        \u003c/tr\u003e\n      \u003c%% end %\u003e\n    \u003c/tbody\u003e\n  \u003c/table\u003e\n\n  \u003cbr\u003e\n\n  \u003c%%= link_to 'New \u003c%= singular_table_name.titleize %\u003e', new_\u003c%= singular_route_name %\u003e_path, class: \"btn btn-primary\" %\u003e\n\n\u003c/div\u003e\n\n```\n\n**File new.html.erb.tt**\n```erb\n\u003cdiv class=\"container-fluid\"\u003e\n  \u003ch1\u003eNew \u003c%= singular_table_name.titleize %\u003e\u003c/h1\u003e\n\n  \u003c%%= render 'form', \u003c%= singular_table_name %\u003e: @\u003c%= singular_table_name %\u003e %\u003e\n\n  \u003c%%= link_to 'Back', \u003c%= index_helper %\u003e_path, class: \"btn btn-primary\" %\u003e\n\u003c/div\u003e\n\n```\n\n**File show.html.erb.tt**\n```erb\n\u003cdiv class=\"container-fluid\"\u003e\n  \u003cp id=\"notice\"\u003e\u003c%%= notice %\u003e\u003c/p\u003e\n\n  \u003c% attributes.reject(\u0026:password_digest?).each do |attribute| -%\u003e\n  \u003c% if attribute.attachment? -%\u003e\n  \u003cdiv class=\"form-group mb-3\"\u003e\n    \u003cp\u003e\u003cstrong\u003e\u003c%= attribute.human_name %\u003e:\u003c/strong\u003e\u003c/p\u003e\n    \u003c%%= link_to @\u003c%= singular_table_name %\u003e.\u003c%= attribute.column_name %\u003e.filename, @\u003c%= singular_table_name %\u003e.\u003c%= attribute.column_name %\u003e if @\u003c%= singular_table_name %\u003e.\u003c%= attribute.column_name %\u003e.attached? %\u003e\n  \u003c/div\u003e\n  \u003c% elsif attribute.attachments? -%\u003e\n  \u003cdiv class=\"form-group mb-3\"\u003e\n    \u003cp\u003e\u003cstrong\u003e\u003c%= attribute.human_name %\u003e:\u003c/strong\u003e\u003c/p\u003e\n    \u003c%% @\u003c%= singular_table_name %\u003e.\u003c%= attribute.column_name %\u003e.each do |\u003c%= attribute.singular_name %\u003e| %\u003e\n      \u003cdiv\u003e\u003c%%= link_to \u003c%= attribute.singular_name %\u003e.filename, \u003c%= attribute.singular_name %\u003e %\u003e\u003c/div\u003e\n    \u003c%% end %\u003e\n  \u003c/div\u003e\n  \u003c% else -%\u003e\n  \u003cdiv class=\"form-group mb-3\"\u003e\n    \u003cp\u003e\u003cstrong\u003e\u003c%= attribute.human_name %\u003e:\u003c/strong\u003e\u003c/p\u003e\n    \u003cdiv\u003e\n      \u003c%%= @\u003c%= singular_table_name %\u003e.\u003c%= attribute.column_name %\u003e %\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n  \u003c% end -%\u003e\n\n  \u003c% end -%\u003e\n\n  \u003c%%= link_to 'Edit', edit_\u003c%= singular_table_name %\u003e_path(@\u003c%= singular_table_name %\u003e), class: \"btn btn-primary\" %\u003e\n  \u003c%%= link_to 'Back', \u003c%= index_helper %\u003e_path, class: \"btn btn-secondary\" %\u003e\n\u003c/div\u003e\n\n```\n\n## Add Bootstrap 5 to the project\n\nRun this command to add bootstrap\n```\nyarn add bootstrap@5.0.0-beta1 @popperjs/core@@2.6.0\n```\n\nEdit `app/javascript/packs/application.js`:\n```js\nimport Rails from \"@rails/ujs\"\nimport Turbolinks from \"turbolinks\"\nimport * as ActiveStorage from \"@rails/activestorage\"\nimport \"channels\"\n\nRails.start()\nTurbolinks.start()\nActiveStorage.start()\n\n// Add these lines\nimport \"bootstrap\"\nimport \"bootstrap/scss/bootstrap.scss\"\n```\n\n## Generate scaffold for Category and Article\nGenerate new views for the restaurant model overriding the original ones.\n\n```\nrails g scaffold Category name description:text\nrails g scaffold Article title content:text category:references active:boolean\n\n```\n\n**Then run migration command**\n\n```\nbundle exec rails db:create db:migrate\nbundle exec rails s\n```\n\nopen other terminal and run:\n\n```\n./bin/webpack-dev-server\n```\n\nand see the result at the address\n```\nhttp://localhost:3000/categories\nhttp://localhost:3000/articles\n```\n\n## If you want to run this example quickly\n\n```\ncd \ngit clone https://github.com/ntamvl/rails_custom_view_scaffold_example \ncd rails_custom_view_scaffold_example\nbundle install \u0026\u0026 yarn install \nrails db:create db:migrate \nrails s\n```\n\nopen other terminal and run:\n```\n./bin/webpack-dev-server\n```\n\nEnjoy :D :) \u003c3\n\n---\nCheers, and happy coding!\n\nI also published this example at my blog [https://ntam.me/customize-view-scaffolding-template-using-bootstrap-5/](https://ntam.me/customize-view-scaffolding-template-using-bootstrap-5/)\n\nIf you have questions or comments about this blog post, you can get in touch with me on Twitter [@nguyentamvn](https://twitter.com/nguyentamvn)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fntamvl%2Frails_custom_view_scaffold_example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fntamvl%2Frails_custom_view_scaffold_example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fntamvl%2Frails_custom_view_scaffold_example/lists"}