rails_app_generator 0.2.21 → 0.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.builders/generators/project-plan.rb +16 -2
  3. data/CHANGELOG.md +24 -0
  4. data/after_templates/addons/avo/_.rb +54 -0
  5. data/after_templates/addons/avo/app/controllers/home_controller.rb +4 -0
  6. data/after_templates/addons/avo/app/views/home/index.html.erb +3 -0
  7. data/after_templates/addons/avo/app/views/layouts/_footer.html.erb +3 -0
  8. data/after_templates/addons/avo/app/views/layouts/_navbar.html.erb +8 -0
  9. data/after_templates/addons/avo/app/views/layouts/application.html.erb +23 -0
  10. data/after_templates/addons/avo/db/seeds.rb +132 -0
  11. data/after_templates/addons/devise/_.rb +70 -0
  12. data/after_templates/addons/devise/app/controllers/home_controller.rb +4 -0
  13. data/after_templates/addons/devise/app/controllers/posts_controller.rb +81 -0
  14. data/after_templates/addons/devise/app/models/post.rb +11 -0
  15. data/after_templates/addons/devise/app/models/user.rb +17 -0
  16. data/after_templates/addons/devise/app/views/home/index.html.erb +40 -0
  17. data/after_templates/addons/devise/app/views/layouts/_footer.html.erb +1 -0
  18. data/after_templates/addons/devise/app/views/layouts/_navbar.html.erb +10 -0
  19. data/after_templates/addons/devise/app/views/layouts/application.html.erb +38 -0
  20. data/after_templates/addons/devise/app/views/posts/_form.html.erb +27 -0
  21. data/after_templates/addons/devise/app/views/posts/_post.html.erb +14 -0
  22. data/after_templates/addons/devise/app/views/posts/index.html.erb +12 -0
  23. data/after_templates/addons/devise/app/views/posts/show.html.erb +8 -0
  24. data/after_templates/addons/devise/db/seeds.rb +11 -0
  25. data/after_templates/addons/minimal_css/_.rb +62 -0
  26. data/after_templates/addons/minimal_css/app/controllers/home_controller.rb +4 -0
  27. data/after_templates/addons/minimal_css/app/views/home/index.html.erb +140 -0
  28. data/after_templates/addons/minimal_css/app/views/layouts/_footer.html.erb +1 -0
  29. data/after_templates/addons/minimal_css/app/views/layouts/_navbar.html.erb +3 -0
  30. data/after_templates/addons/minimal_css/app/views/layouts/application.html.erb +29 -0
  31. data/after_templates/addons/minimal_css/db/seeds.rb +5 -0
  32. data/after_templates/rag/devise/_.rb +14 -17
  33. data/after_templates/rag/devise/app/controllers/home_controller.rb +4 -0
  34. data/after_templates/rag/devise/{post → app/controllers}/posts_controller.rb +0 -0
  35. data/after_templates/rag/devise/{post → app/models}/post.rb +0 -0
  36. data/after_templates/rag/devise/app/views/home/index.html.erb +3 -0
  37. data/after_templates/rag/devise/app/views/layouts/_footer.html.erb +3 -0
  38. data/after_templates/rag/devise/app/views/layouts/_navbar.html.erb +8 -0
  39. data/after_templates/rag/devise/app/views/layouts/application.html.erb +24 -0
  40. data/after_templates/rag/devise/{post → app/views/post}/_post.html.erb +0 -0
  41. data/after_templates/rag/test/_.rb +64 -0
  42. data/after_templates/rag/test/app/controllers/home_controller.rb +4 -0
  43. data/after_templates/rag/test/app/views/home/index.html.erb +3 -0
  44. data/after_templates/rag/test/app/views/layouts/_footer.html.erb +1 -0
  45. data/after_templates/rag/test/app/views/layouts/_navbar.html.erb +5 -0
  46. data/after_templates/rag/test/app/views/layouts/application.html.erb +29 -0
  47. data/after_templates/rag/test/db/seeds.rb +7 -0
  48. data/after_templates/rag/testy/_.rb +64 -0
  49. data/after_templates/rag/testy/app/controllers/home_controller.rb +4 -0
  50. data/after_templates/rag/testy/app/views/home/index.html.erb +3 -0
  51. data/after_templates/rag/testy/app/views/layouts/_footer.html.erb +1 -0
  52. data/after_templates/rag/testy/app/views/layouts/_navbar.html.erb +5 -0
  53. data/after_templates/rag/testy/app/views/layouts/application.html.erb +29 -0
  54. data/after_templates/rag/testy/db/seeds.rb +7 -0
  55. data/docs/last_run/app_generator_class.json +58 -34
  56. data/docs/last_run/app_generator_data.json +13 -10
  57. data/docs/last_run/rails_options_class.json +48 -24
  58. data/docs/last_run/rails_options_data.json +13 -10
  59. data/docs/project-plan/project.drawio +65 -59
  60. data/docs/project-plan/project_done.svg +1 -1
  61. data/lib/rails_app_generator/addon.rb +20 -2
  62. data/lib/rails_app_generator/addons/avo.rb +27 -0
  63. data/lib/rails_app_generator/addons/devise.rb +78 -28
  64. data/lib/rails_app_generator/addons/devise_old.rb +22 -0
  65. data/lib/rails_app_generator/addons/minimal_css.rb +70 -0
  66. data/lib/rails_app_generator/app_generator.rb +39 -20
  67. data/lib/rails_app_generator/gem_query.rb +34 -0
  68. data/lib/rails_app_generator/rag_initializer.rb +24 -8
  69. data/lib/rails_app_generator/version.rb +1 -1
  70. data/lib/rails_app_generator.rb +1 -0
  71. data/package-lock.json +2 -2
  72. data/package.json +1 -1
  73. data/profiles/addons/avo.json +16 -0
  74. data/profiles/addons/devise.json +16 -0
  75. data/profiles/addons/minimal_css.json +15 -0
  76. data/profiles/rag/testy.json +12 -0
  77. data/tasks/addon.thor +7 -3
  78. data/tasks/profile.thor +3 -3
  79. data/templates/Gemfile.erb +1 -0
  80. data/{after_templates/rag/devise/turbo_controller.rb → templates/addons/devise/app/controllers/turbo_devise_controller.rb} +4 -10
  81. data/templates/addons/devise/app/controllers/users/registrations_controller.rb +62 -0
  82. data/templates/addons/devise/app/views/devise/registrations/edit.html.erb +40 -54
  83. data/templates/addons/devise/app/views/devise/registrations/new.html.erb +32 -43
  84. data/templates/addons/devise/app/views/layouts/_alerts.html.erb +2 -0
  85. data/{after_templates/rag → templates/addons}/devise/config/initializers/devise_turbo.rb +1 -1
  86. data/templates/thor_task/profile/after_template.rb +1 -1
  87. data/templates/thor_task/profile/app/views/layouts/_footer.html.erb.tt +1 -3
  88. data/templates/thor_task/profile/app/views/layouts/_navbar.html.erb +5 -8
  89. data/templates/thor_task/profile/app/views/layouts/application.html.erb.tt +8 -2
  90. data/templates/thor_task/profile/db/seeds.rb +2 -11
  91. metadata +64 -17
  92. data/after_templates/rag/devise/application.html.erb +0 -20
  93. data/tasks/gem_info.rb +0 -47
  94. data/templates/addons/devise/app/views/devise/confirmations/new.html.erb +0 -24
  95. data/templates/addons/devise/app/views/devise/passwords/edit.html.erb +0 -34
  96. data/templates/addons/devise/app/views/devise/passwords/new.html.erb +0 -23
  97. data/templates/addons/devise/app/views/devise/sessions/new.html.erb +0 -33
  98. data/templates/addons/devise/app/views/devise/shared/_error_messages.html.erb +0 -15
  99. data/templates/addons/devise/app/views/devise/shared/_form_wrap.html.erb +0 -5
  100. data/templates/addons/devise/app/views/devise/shared/_links.html.erb +0 -25
  101. data/templates/addons/devise/app/views/devise/unlocks/new.html.erb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5040f4476242b440975bacea04755a6f5b2a3734b42bef7ff9af2716f5663477
4
- data.tar.gz: d772aadc218e55633caa058345424bab72f0fc118be94bf175f0ea99523ce8a4
3
+ metadata.gz: f3b2288ae71fcb62d6d27a0c112af620c7ccebf29dad7f7a3ccf0b6b763960bd
4
+ data.tar.gz: 66acd6ef9f7663d0f71605564fa793e88e2f7c4c10427da39b21259cf9cb8ee4
5
5
  SHA512:
6
- metadata.gz: 572437e5b7c05918ba39071fa9d3328aaf477924f9e738325d9c60b49563a76995245016b9af70824dc3a1c2934025d69419a68e47c274beaed7e570bb3ed27d
7
- data.tar.gz: e56b65373ec558e9b854b8c39101e4f89e878b6d12a498f998b56db31b253c5dd3b99a513081546869d471c44366089ca52ea1cc3af7fd075b6563084e7d663a
6
+ metadata.gz: f58098fef783d509ff3005a5687c5d576c02b827ecb252b90e15f0150a73301d268dc4bd37412618b53bf4d82f21e60b02b9c46ae84ee0351ae9ddc85cc335bc
7
+ data.tar.gz: 02e741081aeec1eca92b1ae4260831cd0b556a243c98b3147c76b446b793d9fa1bee52949819bf02255dc00c0d9257192224fe8516834354f9d02fdf71a1017b
@@ -41,20 +41,34 @@ KManager.action :project_plan do
41
41
 
42
42
  todo(title: 'add addon - acts_as_list')
43
43
  todo(title: 'add addon - administrate')
44
+ todo(title: 'add addon - annotate')
44
45
  todo(title: 'add addon - bcrypt')
45
46
  todo(title: 'add addon - browser')
46
47
  todo(title: 'add addon - chartkick')
48
+ # continuous_integration
49
+ # devise
50
+ # docker_compose
51
+ # docker
47
52
  todo(title: 'add addon - dotenv')
53
+ # factory_bot
48
54
  todo(title: 'add addon - faker')
55
+ # generators
56
+ todo(title: 'add addon - groupdate')
49
57
  todo(title: 'add addon - hexapdf')
50
- todo(title: 'add addon - honeybadger')
51
58
  todo(title: 'add addon - httparty')
59
+ # high_voltage
60
+ todo(title: 'add addon - honeybadger')
52
61
  todo(title: 'add addon - lograge')
53
62
  todo(title: 'add addon - mini_magick')
54
63
  todo(title: 'add addon - motor_magick')
55
- todo(title: 'add addon - phony_rails')
56
64
  todo(title: 'add addon - public_suffix')
65
+ todo(title: 'add addon - phony_rails')
66
+ # pundit
57
67
  todo(title: 'add addon - rails_html_sanitizer')
68
+ # rails_app_generator
69
+ # services
70
+ # shoulda
71
+ # sidekiq
58
72
  todo(title: 'add addon - redcarpet')
59
73
  todo(title: 'add addon - groupdate')
60
74
  todo(title: 'add addon - rubocop')
data/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ ## [0.2.23](https://github.com/klueless-io/rails_app_generator/compare/v0.2.22...v0.2.23) (2022-08-16)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add devise profile ([a665767](https://github.com/klueless-io/rails_app_generator/commit/a6657670b1fce4eb802a56ace36368505ede3c2e))
7
+ * fix invalid gem ([377e547](https://github.com/klueless-io/rails_app_generator/commit/377e5479c4debbd0df9e1362694d1847cf7d58e0))
8
+ * update addon to work with non gems ([f9b0b14](https://github.com/klueless-io/rails_app_generator/commit/f9b0b147859760abbb921a236cd1e7f6a97eb3f0))
9
+
10
+ ## [0.2.22](https://github.com/klueless-io/rails_app_generator/compare/v0.2.21...v0.2.22) (2022-08-14)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * update avo profile ([79a3f36](https://github.com/klueless-io/rails_app_generator/commit/79a3f366f9f95e29a5f003a815c1fc963d796179))
16
+ * update avo profile ([2830ddf](https://github.com/klueless-io/rails_app_generator/commit/2830ddff3fd327d2c162ef1e0128dc525b3a493c))
17
+
18
+ ## [0.2.21](https://github.com/klueless-io/rails_app_generator/compare/v0.2.20...v0.2.21) (2022-08-12)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * add annotate profile ([1794612](https://github.com/klueless-io/rails_app_generator/commit/17946124c5600881a4d015c3283fc9e2e3278634))
24
+
1
25
  ## [0.2.20](https://github.com/klueless-io/rails_app_generator/compare/v0.2.19...v0.2.20) (2022-08-12)
2
26
 
3
27
 
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Avo abstracts away the common parts of building apps, letting your engineers work on your app's essential components. The result is a full-featured admin panel that works out of the box, ready to give to your end-users.
4
+ #
5
+ # exe/rag addons/avo
6
+ #
7
+ # based on: https://www.youtube.com/watch?v=WgNK-oINFww
8
+
9
+ self.local_template_path = File.dirname(__FILE__)
10
+
11
+ gac 'base rails 7 image created'
12
+
13
+ prepare_environment
14
+
15
+ add_controller('home', 'index')
16
+
17
+ route("root 'home#index'")
18
+
19
+ force_copy
20
+
21
+ directory "app/controllers"
22
+ directory "app/views/home"
23
+ directory "app/views/layouts"
24
+ template 'app/views/layouts/application.html.erb' , 'app/views/layouts/application.html.erb'
25
+
26
+ template 'db/seeds.rb' , 'db/seeds.rb'
27
+
28
+ after_bundle do
29
+ setup_db
30
+ setup_avo
31
+ end
32
+
33
+ def setup_db
34
+ add_scaffold('author', 'name:string', 'email:string', 'bio:text')
35
+ add_scaffold('category', 'title:string', 'description:text')
36
+ add_scaffold('post', 'title:string content:text', 'published:boolean', 'author:references', 'category:references')
37
+ add_scaffold('product', 'name', 'quantity:integer', 'price:decimal', 'author:references')
38
+
39
+ db_migrate
40
+ db_seed
41
+ end
42
+
43
+ def setup_avo
44
+ generate('avo:install')
45
+ generate('avo:resource Product')
46
+ generate('avo:resource Post')
47
+ generate('avo:resource Author')
48
+ generate('avo:resource Category')
49
+ generate('avo:resource User')
50
+ generate('avo:dashboard Dashboard')
51
+
52
+ # add devise support
53
+ gsub_file 'config/initializers/avo.rb', %(# config.current_user_method = {}), 'config.current_user_method = :current_user'
54
+ end
@@ -0,0 +1,4 @@
1
+ class HomeController < ApplicationController
2
+ def index
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ <h1>Avo</h1>
2
+
3
+ <p>Avo abstracts away the common parts of building apps, letting your engineers work on your app's essential components. The result is a full-featured admin panel that works out of the box, ready to give to your end-users.</p>
@@ -0,0 +1,3 @@
1
+ <footer>
2
+ <hr />
3
+ </footer>
@@ -0,0 +1,8 @@
1
+ <header>
2
+ <%= link_to 'Home', root_path %> |
3
+ <%= link_to 'Authors', authors_path %> |
4
+ <%= link_to 'Posts', posts_path %> |
5
+ <%= link_to 'Products', products_path %> |
6
+ <%= link_to 'ADMIN', avo_path %>
7
+ <hr />
8
+ </header>
@@ -0,0 +1,23 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= camelized %></title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <%%= csrf_meta_tags %>
7
+ <%%= csp_meta_tag %>
8
+
9
+ <%- if options[:skip_hotwire] || options[:skip_javascript] -%>
10
+ <%%= stylesheet_link_tag "application" %>
11
+ <%- else -%>
12
+ <%%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
13
+ <%- end -%>
14
+ </head>
15
+
16
+ <body>
17
+ <%%= render 'layouts/navbar' %>
18
+ <main>
19
+ <%%= yield %>
20
+ </main>
21
+ <%%= render 'layouts/footer' %>
22
+ </body>
23
+ </html>
@@ -0,0 +1,132 @@
1
+ def fake_category
2
+ [
3
+ 'Action',
4
+ 'Adventure',
5
+ 'Biography',
6
+ 'Comedy',
7
+ 'Crime',
8
+ 'Drama',
9
+ 'Fantasy',
10
+ ]
11
+ end
12
+
13
+ def fake_title
14
+ [
15
+ 'Fundamentals of Wavelets',
16
+ 'Data Smart',
17
+ 'God Created the Integers',
18
+ 'Superfreakonomics',
19
+ 'Orientalism',
20
+ 'Nature of Statistical Learning Theory',
21
+ 'Integration of the Indian States',
22
+ 'Image Processing & Mathematical Morphology',
23
+ 'How to Think Like Sherlock Holmes',
24
+ 'Data Scientists at Work',
25
+ 'Slaughterhouse Five',
26
+ 'Birth of a Theorem',
27
+ 'Structure & Interpretation of Computer Programs',
28
+ 'Age of Wrath',
29
+ 'Trial',
30
+ 'Data Mining Handbook',
31
+ 'New Machiavelli',
32
+ 'Physics & Philosophy',
33
+ 'Making Software',
34
+ 'Analysis',
35
+ 'Machine Learning for Hackers',
36
+ 'Signal and the Noise',
37
+ 'Python for Data Analysis',
38
+ 'Introduction to Algorithms',
39
+ 'Beautiful and the Damned',
40
+ 'Outsider',
41
+ 'Complete Sherlock Holmes',
42
+ 'Complete Sherlock Holmes',
43
+ 'Wealth of Nations',
44
+ 'Pillars of the Earth',
45
+ 'Mein Kampf',
46
+ 'Tao of Physics',
47
+ 'Farewell to Arms',
48
+ 'Veteran',
49
+ 'False Impressions',
50
+ 'Last Lecture',
51
+ 'Return of the Primitive',
52
+ 'Jurassic Park',
53
+ 'Russian Journal',
54
+ 'Tales of Mystery and Imagination',
55
+ 'Freakonomics',
56
+ 'Hidden Connections',
57
+ 'Story of Philosophy',
58
+ 'Asami Asami',
59
+ 'Journal of a Novel',
60
+ 'Once There Was a War',
61
+ 'Moon is Down',
62
+ 'Brethren',
63
+ 'In a Free State',
64
+ 'Catch 22',
65
+ 'Complete Mastermind',
66
+ 'Dylan on Dylan',
67
+ 'Soft Computing & Intelligent Systems',
68
+ 'Textbook of Economic Theory',
69
+ 'Econometric Analysis',
70
+ 'Learning OpenCV',
71
+ 'Data Structures Using C & C++',
72
+ 'Computer Vision',
73
+ 'Principles of Communication Systems',
74
+ 'Let Us C',
75
+ 'Amulet of Samarkand',
76
+ 'Crime and Punishment',
77
+ 'Angels & Demons',
78
+ 'Argumentative Indian',
79
+ 'Sea of Poppies',
80
+ 'Idea of Justice',
81
+ 'Raisin in the Sun',
82
+ 'Prisoner of Birth',
83
+ 'Scoop!',
84
+ 'Ahe Manohar Tari',
85
+ 'Last Mughal',
86
+ 'Social Choice & Welfare',
87
+ 'Radiowaril Bhashane & Shrutika',
88
+ 'Gun Gayin Awadi',
89
+ 'Aghal Paghal',
90
+ 'Beyond Degrees',
91
+ 'Manasa',
92
+ 'India from Midnight to Milennium',
93
+ 'Great Indian Novel',
94
+ 'O Jerusalem!',
95
+ 'City of Joy',
96
+ 'Freedom at Midnight',
97
+ 'Winter of Our Discontent',
98
+ 'On Education',
99
+ 'Free Will',
100
+ 'Bookless in Baghdad',
101
+ 'Case of the Lame Canary',
102
+ 'Theory of Everything',
103
+ 'New Markets & Other Essays',
104
+ 'Electric Universe',
105
+ 'Hunchback of Notre Dame',
106
+ 'Burning Bright',
107
+ 'Age of Discontuinity'
108
+ ].sample
109
+ end
110
+
111
+ 60.times do
112
+ Author.create!(name: Faker::Name.name, bio: Faker::Lorem.words(number: 5).join(' '), email: Faker::Internet.email)
113
+ end
114
+
115
+ fake_category.each do |category|
116
+ Category.create!(title: category, description: Faker::Lorem.sentence)
117
+ end
118
+
119
+ 100.times do |i|
120
+ Post.create!(title: fake_title,
121
+ content: "This is the body of post #{i}",
122
+ published: Faker::Boolean.boolean(true_ratio: 0.6),
123
+ author: Author.all.sample)
124
+ end
125
+
126
+ 200.times do
127
+ Product.create!(
128
+ name: Faker::Name.name,
129
+ quantity: Faker::Number.number(digits: 2),
130
+ price: Faker::Number.decimal(l_digits: 4)
131
+ )
132
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Based on guidance from:
4
+ # Rails 7 - Intro to Devise
5
+ # https://www.youtube.com/watch?v=m3uhldUGVes
6
+ #
7
+ # exe/rag addons/devise
8
+
9
+ self.local_template_path = File.dirname(__FILE__)
10
+
11
+ gac 'base rails 7 image created'
12
+
13
+ prepare_environment
14
+
15
+ after_bundle do
16
+ scaffolds
17
+ setup_customizations
18
+ setup_db
19
+ end
20
+
21
+ def scaffolds
22
+ add_scaffold('post', 'title', 'body:text', 'views:integer', 'user:references')
23
+ end
24
+
25
+ def setup_db
26
+ template 'db/seeds.rb' , 'db/seeds.rb'
27
+
28
+ db_migrate
29
+ db_seed
30
+ end
31
+
32
+ def setup_customizations
33
+ route("root 'home#index'")
34
+
35
+ force_copy
36
+
37
+ add_controller('home', 'index')
38
+
39
+ directory "app/controllers"
40
+ directory "app/models"
41
+ directory "app/views"
42
+ template 'app/views/layouts/application.html.erb' , 'app/views/layouts/application.html.erb'
43
+ end
44
+
45
+ # Other template command examples
46
+ # prepare_environment
47
+ # bundle_install
48
+ # css_install('tailwind')
49
+ # rails_command('db:migrate')
50
+ # rails_command('db:migrate')
51
+ # bundle_add('hotwire-rails')
52
+ # rails_command('hotwire:install')
53
+ # run('bin/importmap pin sortablejs')
54
+ # run('npm install daisyui')
55
+ # rubocop
56
+ #
57
+ # directory 'app/assets/images'
58
+ # create_file 'app/assets/stylesheets/custom-bootstrap-import.scss' , read_template('custom-bootstrap-import.scss')
59
+ # append_to_file 'app/assets/config/manifest.js' , read_template('manifest.js')
60
+ # insert_into_file 'app/views/layouts/application.html.erb', read_template('application.html.erb'),
61
+ # before: %( <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>)
62
+ # gsub_file 'app/views/layouts/application.html.erb', %(container mx-auto mt-28 px-5 flex), 'container mx-auto px-5'
63
+ # template 'home.css', 'app/assets/stylesheets/home.css'
64
+ #
65
+ # add_controller('page', 'benefits', 'faq', 'terms', 'privacy', '--skip-routes')
66
+ # route(<<-'RUBY')
67
+ # PageController.action_methods.each do |action|
68
+ # get "/#{action}", to: "page##{action}", as: "page_#{action}"
69
+ # end
70
+ # RUBY
@@ -0,0 +1,4 @@
1
+ class HomeController < ApplicationController
2
+ def index
3
+ end
4
+ end
@@ -0,0 +1,81 @@
1
+ class PostsController < ApplicationController
2
+ before_action :authenticate_user!, except: %i[show index]
3
+ before_action :set_post, only: %i[show edit update destroy]
4
+ before_action :require_permission, only: %i[edit destroy]
5
+
6
+ def index
7
+ @posts = Post.all.order(updated_at: :desc)
8
+ end
9
+
10
+ def show
11
+ @post.update(views: @post.views + 1)
12
+ end
13
+
14
+ def new
15
+ @post = Post.new
16
+ end
17
+
18
+ def edit
19
+ end
20
+
21
+ def create
22
+ @post = Post.new(post_params)
23
+ @post.user = current_user
24
+
25
+ respond_to do |format|
26
+ if @post.save
27
+ format.html { redirect_to post_url(@post), notice: "Post was successfully created." }
28
+ format.json { render :show, status: :created, location: @post }
29
+ else
30
+ format.html { render :new, status: :unprocessable_entity }
31
+ format.json { render json: @post.errors, status: :unprocessable_entity }
32
+ end
33
+ end
34
+ end
35
+
36
+ def update
37
+ respond_to do |format|
38
+ if @post.update(post_params)
39
+ format.html { redirect_to post_url(@post), notice: "Post was successfully updated." }
40
+ format.json { render :show, status: :ok, location: @post }
41
+ else
42
+ format.html { render :edit, status: :unprocessable_entity }
43
+ format.json { render json: @post.errors, status: :unprocessable_entity }
44
+ end
45
+ end
46
+ end
47
+
48
+ def destroy
49
+ @post.destroy
50
+
51
+ respond_to do |format|
52
+ format.html { redirect_to posts_url, notice: "Post was successfully destroyed." }
53
+ format.json { head :no_content }
54
+ end
55
+ end
56
+
57
+ private
58
+ def set_post
59
+ @post = Post.find(params[:id])
60
+ end
61
+
62
+ def post_params
63
+ params.require(:post).permit(:title, :body, :views, :user_id)
64
+ end
65
+
66
+ def require_permission
67
+ current_user_name = current_user.name.capitalize
68
+ post_user_name = @post.user.name.capitalize
69
+ post_user_name_plural = "#{post_user_name}#{post_user_name.ends_with?('s') ? "'" : "s"}"
70
+
71
+ flash.notice = "#{current_user_name} is trying to #{action_name} #{post_user_name_plural} post."
72
+
73
+ return if current_user.admin? # Administrators can do anything
74
+ return if current_user.moderator? && action_name == "edit" # Moderators can edit any post (but not delete)
75
+ return if current_user.user? && @post.user == current_user # Users can edit or delete their own posts
76
+
77
+ flash.alert = "You do not have permission to #{action_name} #{post_user_name_plural} post."
78
+
79
+ redirect_back(fallback_location: root_path)
80
+ end
81
+ end
@@ -0,0 +1,11 @@
1
+ class Post < ApplicationRecord
2
+ after_initialize :set_views, if: :new_record?
3
+
4
+ belongs_to :user
5
+
6
+ private
7
+
8
+ def set_views
9
+ self.views ||= 0
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ class User < ApplicationRecord
2
+ after_initialize :set_default_role, if: :new_record?
3
+
4
+ # Include default devise modules. Others available are:
5
+ # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
6
+ devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable
7
+
8
+ has_many :posts
9
+
10
+ enum role: { user: 0, moderator: 1, admin: 9 }
11
+
12
+ private
13
+
14
+ def set_default_role
15
+ self.role ||= :user
16
+ end
17
+ end
@@ -0,0 +1,40 @@
1
+ <h1>Devise</h1>
2
+
3
+ <h4>Using a simple Enum based Role for permissions</h4>
4
+
5
+ <ul>
6
+ <li>Anyone can view posts</li>
7
+ <li>Only signed in users can create, update or delete a post</li>
8
+ <li>If role <b>user</b>, you can update and delete your own posts only</li>
9
+ <li>If role <b>moderator</b>, you can update any post, but only delete your own posts</li>
10
+ <li>If role <b>admin</b>, you can update or delete any post</li>
11
+ </ul>
12
+
13
+ <h3>Sample users and passwords</h3>
14
+
15
+ <style>
16
+ table {
17
+ border-collapse: collapse;
18
+ }
19
+ th, td {
20
+ border: 1px solid #ccc;
21
+ padding: 5px;
22
+ }
23
+ </style>
24
+
25
+ <table style='width: 600px;'>
26
+ <tr>
27
+ <th>Name</th>
28
+ <th>Email</th>
29
+ <th>Role</th>
30
+ <th>Password</th>
31
+ </tr>
32
+ <% User.all.each do |user| %>
33
+ <tr>
34
+ <td><%= user.name %></td>
35
+ <td><%= user.email %></td>
36
+ <td><%= user.role %></td>
37
+ <td>password</td>
38
+ </tr>
39
+ <% end %>
40
+ </table>
@@ -0,0 +1,10 @@
1
+ <%= link_to 'Home', root_path %>
2
+ | <%= link_to 'Posts', posts_path %>
3
+ <% if current_user %>
4
+ <%= current_user.name || current_user.email %>
5
+ | <%= link_to 'Edit', edit_user_registration_path %>
6
+ | <%= link_to 'Sign Out', destroy_user_session_path, data: { turbo_method: :delete } %>
7
+ <% else %>
8
+ | <%= link_to 'Sign Up', new_user_registration_path %>
9
+ | <%= link_to 'Sign In', new_user_session_path %>
10
+ <% end%>
@@ -0,0 +1,38 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= camelized %></title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <%%= csrf_meta_tags %>
7
+ <%%= csp_meta_tag %>
8
+
9
+ <%- if options[:skip_hotwire] || options[:skip_javascript] -%>
10
+ <%%= stylesheet_link_tag "application" %>
11
+ <%- else -%>
12
+ <%%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
13
+ <%- end -%>
14
+ <%%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
15
+ <style>
16
+ .notice {
17
+ color: green;
18
+ }
19
+ .alert {
20
+ color: red;
21
+ }
22
+ </style>
23
+ </head>
24
+
25
+ <body>
26
+ <header>
27
+ <%%= render 'layouts/navbar' %>
28
+ <hr />
29
+ <%%= render 'layouts/alerts' %>
30
+ </header>
31
+ <main>
32
+ <%%= yield %>
33
+ </main>
34
+ <footer>
35
+ <%%= render 'layouts/footer' %>
36
+ </footer>
37
+ </body>
38
+ </html>
@@ -0,0 +1,27 @@
1
+ <%= form_with(model: post) do |form| %>
2
+ <% if post.errors.any? %>
3
+ <div style="color: red">
4
+ <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>
5
+
6
+ <ul>
7
+ <% post.errors.each do |error| %>
8
+ <li><%= error.full_message %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div>
15
+ <%= form.label :title, style: "display: block" %>
16
+ <%= form.text_field :title %>
17
+ </div>
18
+
19
+ <div>
20
+ <%= form.label :body, style: "display: block" %>
21
+ <%= form.text_area :body %>
22
+ </div>
23
+
24
+ <div>
25
+ <%= form.submit %>
26
+ </div>
27
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <div id="<%= dom_id post %>">
2
+ <h3>posted by <%= post.user.name || post.user.email %></h4>
3
+ <h4><%= pluralize(post.views, 'view') %></h4>
4
+
5
+ <p>
6
+ <strong>Title:</strong>
7
+ <%= post.title %>
8
+ </p>
9
+
10
+ <p>
11
+ <strong>Body:</strong>
12
+ <%= post.body %>
13
+ </p>
14
+ </div>
@@ -0,0 +1,12 @@
1
+ <h1>Posts</h1>
2
+
3
+ <div id="posts">
4
+ <% @posts.each do |post| %>
5
+ <%= render post %>
6
+ <p>
7
+ <%= link_to "Show this post", post %>
8
+ </p>
9
+ <% end %>
10
+ </div>
11
+
12
+ <%= link_to "New post", new_post_path %>
@@ -0,0 +1,8 @@
1
+ <%= render @post %>
2
+
3
+ <div>
4
+ <%= link_to "Edit this post", edit_post_path(@post) %> |
5
+ <%= link_to "Back to posts", posts_path %>
6
+
7
+ <%= button_to "Destroy this post", @post, method: :delete %>
8
+ </div>