rails_app_generator 0.2.21 → 0.2.24

Sign up to get free protection for your applications and to get access to all the features.
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>