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.
- checksums.yaml +4 -4
- data/.builders/generators/project-plan.rb +16 -2
- data/CHANGELOG.md +24 -0
- data/after_templates/addons/avo/_.rb +54 -0
- data/after_templates/addons/avo/app/controllers/home_controller.rb +4 -0
- data/after_templates/addons/avo/app/views/home/index.html.erb +3 -0
- data/after_templates/addons/avo/app/views/layouts/_footer.html.erb +3 -0
- data/after_templates/addons/avo/app/views/layouts/_navbar.html.erb +8 -0
- data/after_templates/addons/avo/app/views/layouts/application.html.erb +23 -0
- data/after_templates/addons/avo/db/seeds.rb +132 -0
- data/after_templates/addons/devise/_.rb +70 -0
- data/after_templates/addons/devise/app/controllers/home_controller.rb +4 -0
- data/after_templates/addons/devise/app/controllers/posts_controller.rb +81 -0
- data/after_templates/addons/devise/app/models/post.rb +11 -0
- data/after_templates/addons/devise/app/models/user.rb +17 -0
- data/after_templates/addons/devise/app/views/home/index.html.erb +40 -0
- data/after_templates/addons/devise/app/views/layouts/_footer.html.erb +1 -0
- data/after_templates/addons/devise/app/views/layouts/_navbar.html.erb +10 -0
- data/after_templates/addons/devise/app/views/layouts/application.html.erb +38 -0
- data/after_templates/addons/devise/app/views/posts/_form.html.erb +27 -0
- data/after_templates/addons/devise/app/views/posts/_post.html.erb +14 -0
- data/after_templates/addons/devise/app/views/posts/index.html.erb +12 -0
- data/after_templates/addons/devise/app/views/posts/show.html.erb +8 -0
- data/after_templates/addons/devise/db/seeds.rb +11 -0
- data/after_templates/addons/minimal_css/_.rb +62 -0
- data/after_templates/addons/minimal_css/app/controllers/home_controller.rb +4 -0
- data/after_templates/addons/minimal_css/app/views/home/index.html.erb +140 -0
- data/after_templates/addons/minimal_css/app/views/layouts/_footer.html.erb +1 -0
- data/after_templates/addons/minimal_css/app/views/layouts/_navbar.html.erb +3 -0
- data/after_templates/addons/minimal_css/app/views/layouts/application.html.erb +29 -0
- data/after_templates/addons/minimal_css/db/seeds.rb +5 -0
- data/after_templates/rag/devise/_.rb +14 -17
- data/after_templates/rag/devise/app/controllers/home_controller.rb +4 -0
- data/after_templates/rag/devise/{post → app/controllers}/posts_controller.rb +0 -0
- data/after_templates/rag/devise/{post → app/models}/post.rb +0 -0
- data/after_templates/rag/devise/app/views/home/index.html.erb +3 -0
- data/after_templates/rag/devise/app/views/layouts/_footer.html.erb +3 -0
- data/after_templates/rag/devise/app/views/layouts/_navbar.html.erb +8 -0
- data/after_templates/rag/devise/app/views/layouts/application.html.erb +24 -0
- data/after_templates/rag/devise/{post → app/views/post}/_post.html.erb +0 -0
- data/after_templates/rag/test/_.rb +64 -0
- data/after_templates/rag/test/app/controllers/home_controller.rb +4 -0
- data/after_templates/rag/test/app/views/home/index.html.erb +3 -0
- data/after_templates/rag/test/app/views/layouts/_footer.html.erb +1 -0
- data/after_templates/rag/test/app/views/layouts/_navbar.html.erb +5 -0
- data/after_templates/rag/test/app/views/layouts/application.html.erb +29 -0
- data/after_templates/rag/test/db/seeds.rb +7 -0
- data/after_templates/rag/testy/_.rb +64 -0
- data/after_templates/rag/testy/app/controllers/home_controller.rb +4 -0
- data/after_templates/rag/testy/app/views/home/index.html.erb +3 -0
- data/after_templates/rag/testy/app/views/layouts/_footer.html.erb +1 -0
- data/after_templates/rag/testy/app/views/layouts/_navbar.html.erb +5 -0
- data/after_templates/rag/testy/app/views/layouts/application.html.erb +29 -0
- data/after_templates/rag/testy/db/seeds.rb +7 -0
- data/docs/last_run/app_generator_class.json +58 -34
- data/docs/last_run/app_generator_data.json +13 -10
- data/docs/last_run/rails_options_class.json +48 -24
- data/docs/last_run/rails_options_data.json +13 -10
- data/docs/project-plan/project.drawio +65 -59
- data/docs/project-plan/project_done.svg +1 -1
- data/lib/rails_app_generator/addon.rb +20 -2
- data/lib/rails_app_generator/addons/avo.rb +27 -0
- data/lib/rails_app_generator/addons/devise.rb +78 -28
- data/lib/rails_app_generator/addons/devise_old.rb +22 -0
- data/lib/rails_app_generator/addons/minimal_css.rb +70 -0
- data/lib/rails_app_generator/app_generator.rb +39 -20
- data/lib/rails_app_generator/gem_query.rb +34 -0
- data/lib/rails_app_generator/rag_initializer.rb +24 -8
- data/lib/rails_app_generator/version.rb +1 -1
- data/lib/rails_app_generator.rb +1 -0
- data/package-lock.json +2 -2
- data/package.json +1 -1
- data/profiles/addons/avo.json +16 -0
- data/profiles/addons/devise.json +16 -0
- data/profiles/addons/minimal_css.json +15 -0
- data/profiles/rag/testy.json +12 -0
- data/tasks/addon.thor +7 -3
- data/tasks/profile.thor +3 -3
- data/templates/Gemfile.erb +1 -0
- data/{after_templates/rag/devise/turbo_controller.rb → templates/addons/devise/app/controllers/turbo_devise_controller.rb} +4 -10
- data/templates/addons/devise/app/controllers/users/registrations_controller.rb +62 -0
- data/templates/addons/devise/app/views/devise/registrations/edit.html.erb +40 -54
- data/templates/addons/devise/app/views/devise/registrations/new.html.erb +32 -43
- data/templates/addons/devise/app/views/layouts/_alerts.html.erb +2 -0
- data/{after_templates/rag → templates/addons}/devise/config/initializers/devise_turbo.rb +1 -1
- data/templates/thor_task/profile/after_template.rb +1 -1
- data/templates/thor_task/profile/app/views/layouts/_footer.html.erb.tt +1 -3
- data/templates/thor_task/profile/app/views/layouts/_navbar.html.erb +5 -8
- data/templates/thor_task/profile/app/views/layouts/application.html.erb.tt +8 -2
- data/templates/thor_task/profile/db/seeds.rb +2 -11
- metadata +64 -17
- data/after_templates/rag/devise/application.html.erb +0 -20
- data/tasks/gem_info.rb +0 -47
- data/templates/addons/devise/app/views/devise/confirmations/new.html.erb +0 -24
- data/templates/addons/devise/app/views/devise/passwords/edit.html.erb +0 -34
- data/templates/addons/devise/app/views/devise/passwords/new.html.erb +0 -23
- data/templates/addons/devise/app/views/devise/sessions/new.html.erb +0 -33
- data/templates/addons/devise/app/views/devise/shared/_error_messages.html.erb +0 -15
- data/templates/addons/devise/app/views/devise/shared/_form_wrap.html.erb +0 -5
- data/templates/addons/devise/app/views/devise/shared/_links.html.erb +0 -25
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3b2288ae71fcb62d6d27a0c112af620c7ccebf29dad7f7a3ccf0b6b763960bd
|
4
|
+
data.tar.gz: 66acd6ef9f7663d0f71605564fa793e88e2f7c4c10427da39b21259cf9cb8ee4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,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,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,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 @@
|
|
1
|
+
<hr />
|
@@ -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>
|