Rails Blog In VS Code-Using Stimulus
How To Create A Blog in VS Code — Part VII— RailsSeries#Episode 09
Let’s proceed with the previous example and add the ability to post a new review (adding a button Edit
comments).
In this post:
You will:
Learn How to Use Stimulus;
Learn about Hotwire Turbo Family;
Set up Turbo JavaScript to review a comment;
Learn how to pass data from your Front-End View
into your Front-End JS;
Welcome!
This is how it’s going to look.
Index:
Here are the modified files:
app/views/comments/_comment.html.erb — Steps #1, #3, #5 & #7
app/controllers/comments_controller.rb — Step #4
app/javascript/controllers/comments_controller.js — Step #6
app/views/posts/show.html.erb — Step #8
app/views/comments/_form.html.erb — Step #9
Let’s Get Started!
Note: if you get stuck, please see my repo.
0#step — Download the last version (v6) post here and prepare your vscode
environment.
Let’s open a new Feature Branch: git checkout -b add_turbo
.
1#Step — Rails automatically gets set to the current date and time whenever the record is created or updated.
Let’s use it in our favor:
GoTo and paste in place <span>Posted…
this chunk of if condition code:
app/views/comments/_comment.html.erb
...
<% if (comment.updated_at - comment.created_at ) > 1 %>
<span>Edited <%= time_ago_in_words(comment.updated_at) %> ago</span>
<% else %>
<span>Posted <%= time_ago_in_words(comment.created_at) %> ago</span>
<% end %>
...
This code generates HTML output that informs users about the timing of a comment in relation to its creation and last update. It’s designed to provide context about when a comment was made or last posted/edited in a user-friendly format such as Posted X minutes ago
or Edited X days ago.
2#Step — To Test it Go To the Terminal and type rails c
and inside:
Comment.last.update(body:"This was changed in the console")
exit
Now rails s
, browse http://127.0.0.1:3000/
and refresh the page, find the last commented post:
3#Step — Imagine that we want to update one of our comments. This is where things start to get intriguing.
From this point forward, we’ll make use of Stimulus to accomplish our task!
Before we proceed, let’s establish some context.
Hotwire is a tech that aims to improve the UX and performance by reducing the need for full-page reloads.
The Turbo family of tech is led by:
Hotwire:
Turbo Stream — small snippets of HTML;
Turbo Frames — isolated client-side rendering;
Turbo Drive — transform standard link -> AJAX;
Stimulus — lightweight JavaScript framework.
Turbo is a modern, interactive, and performant web app without MANUAL SETUP.
It gives us:
Real time updates;
Interactive Forms;
Smooth Navigation;
Leading more efficient/responsive UX.
To Add Stimulus code create an EDIT
button:
GoTo:
app/views/comments/_comment.html.erb,
paste in place entire <div>...Delete
this chunk of style code:
...
<div class="button-group float-end" style="display: inline-block;">
<%= link_to "Edit", nil, remote: true, class: "btn btn-warning" %>
</div>
<div class="button-group float-end" style="display: inline-block;">
<%= button_to "Delete", [post, comment], class:"btn btn-danger", method: :delete %>
</div>
...
Let’s break down the different parts of this code:
<%= link_to "Edit", ... %>
: This is a Rails helper method that generates a hyperlink with the labelEdit
. The first argument within thelink_to
method is the text that will be displayed as the link text.nil
: This argument represents the URL to which the link should point. In this case,nil
is provided as the URL, which means the link will not lead to a specific URL. This is intentional because we're planning to handle the link's behavior through JavaScript.remote: true
: This option indicates that the link should trigger an Ajax request when clicked. The link's behavior will be handled asynchronously, allowing you to update parts of the page without a full page reload. This option is commonly used in Rails for implementing "remote actions.class: "btn btn-warning"
: This option adds CSS classes to the link, styling it as a button with a "warning" appearance. The"btn btn-warning"
classes are part of a front-end Bootstrap framework and will style the link as a yellow warning button.
In summary, this code generates a link labeled Edit
that, when clicked, triggers an Ajax request (remote: true
). The link has styling applied to it to make it look like a warning button, likely from a CSS framework such as Bootstrap. The actual destination of the link is unspecified (nil
), which suggests that the behavior and destination of the link might be handled through JavaScript code.
4#Step — Now let’s implement the update method:
We need something like this:
def update
if @comment.update(comment_params)
# Redirect or render as needed
else
# Handle unsuccessful comment update
end
end
GoTo and add below create():
app/controllers/comments_controller.rb
def update
@comment = @post.comments.find(params[:id])
respond_to do |format|
if @comment.update(comment_params)
format.html { redirect_to post_url(@post), notice: 'Comment has been updated!' }
else
format.html { redirect_to post_url(@post), alert: 'Comment was not updated!' }
end
end
end
This action is responsible for updating a comment’s content and then responding to the update operation based on the format of the request. It provides feedback to the user based on whether the update was successful or not.
It uses the respond_to
block to handle different response formats, such as HTML, JSON, XML, etc.
If the comment update is not successful, it redirects to the post’s show page with an alert message indicating that the update didn’t occur.
5#Step — Currently, when we click on the Edit
button, there is no response.
To enable editing, we need to instruct Rails to display an edit form.
But how can we achieve this?
Answer: add Stimulus Logic to Edit
button.
Let’s enhance our commenting system by introducing a new feature for editing existing comments. We’ll achieve this by adding another form right below the existing comment. This approach will display two identical comment forms. Utilizing JavaScript, we’ll hide the original comment form and replace it with the one intended for editing. When the edited form is submitted, we’ll toggle the views accordingly, providing a seamless editing experience.
First, let us render the edit form.
GoTo:
app/views/comments/_comment.html.erb
Below <div…> <%= link_to “Edit”%> </div>
include these two <div>
;
Type:
...
<div id="edit-form-<%= comment.id %>" class="d-none" >
<%= render 'comments/form', post: @post, comment: comment, submit_label: "Update" %>
</div>
...
...
<div id="comment-body-<%= comment.id %>">
<%= comment.body %>
</div>
Let me explain the purpose of this code:
<div id="edit-form-<%= comment.id %>" class="d-none">
: This<div>
element has anid
attribute that's unique to each comment. It is used to encapsulate the edit form for the comment. Theclass="d-none"
indicates that by default, the edit form is hidden. By removing theclass="d-none"
you can locate the position of the editing forms.<%= render 'comments/form', post: @post, comment: comment, submit_label: "Update" %>
: This line renders a partial called_form.html.erb
located in theapp/views/comments
directory. This partial is used for both creating and editing comments. It's passing several local variables to the partial:post
,comment
, andUpdate string
.<% end %>
: This seems to be the end of a loop or iteration through comments. It's not completely clear from the provided code. To gain a comprehensive understanding, kindly access my GitHub [TODO: LINK GOES HERE] repository.<hr />
: This<hr>
(horizontal rule) element is used to visually separate different comments in the layout.<div id="comment-body-<%= comment.id %>">
: This<div>
element displays the body content of the comment. Theid
attribute is unique for each comment and could potentially be used for JavaScript-based interactions.
When working with JavaScript, use id
for elements or classes. This is because we'll be utilizing the classList
method in JavaScript to access the object passed by our frontend view.
In summary, this code handles the display and editing of comments in a user interface. The edit form is initially hidden; JavaScript will be used to toggle its visibility when a Edit
button is clicked. The partial _form.html.erb
handle the form creation/editing logic, and each comment's content is displayed within its own unique <div>
.
6#Step — Now create this JavaScript file, GoTo:
app/javascript/controllers/comments_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
initialize() {}
connect() {}
toggleForm(event) {
console.log("I clicked Edit Button!");
event.preventDefault();
event.stopPropagation();
const formID = event.params["form"];
const commentBodyID = event.params["body"];
const form = document.getElementById(formID);
form.classList.toggle("d-none");
form.classList.toggle("mt-5");
const commentBody = document.getElementById(commentBodyID);
commentBody.classList.toggle("d-none");
}
}
Here’s a brief breakdown of what the code does:
import { Controller } from "@hotwired/stimulus"
: This imports theController
class from Stimulus, which you'll be extending.export default class extends Controller { ... }
: This defines your Stimulus controller class.initialize() {}
andconnect() {}
: These are lifecycle methods in Stimulus. If you need to perform specific actions when the controller is initialized or connected to an element in the DOM, you can define those actions within these methods.toggleForm(event) { ... }
: This method handles the toggle action when theEdit
button is clicked.console.log("I clicked Edit Button!");
: This line logs a message to the console, indicating that the button has been clicked. This is helpful for debugging purposes.event.preventDefault(); event.stopPropagation();
: These lines prevent the default behavior of the button click event and stop its propagation. This can prevent the browser from navigating to a new page or performing unintended actions; in this scenario, clickingEdit
won’t unexpectedly scroll us back to the top of the page.const formID = event.params["form"];
: This retrieves theform
parameter from the event. It's assumed that this parameter contains the ID of the form to be toggled.const commentBodyID = event.params["body"];
: This retrieves thebody
parameter from the event. It's assumed that this parameter contains the ID of the comment body element to be toggled.const form = document.getElementById(formID);
: This line retrieves the DOM element using the provided ID, and indeed, it accomplishes that task.form.classList.toggle("d-none"); form.classList.toggle("mt-5");
: This toggles the visibility of the form by toggling thed-none
class (initially hidden by default, it will become visible) and themt-5
class (for adding margin).- Similarly
commentBody.classList.toggle(“d-none”)
the code toggles the visibility of the comment body element (initially visible by default, it will become hidden).
Overall, the code is designed to smoothly toggle the visibility of form and comment elements when a Edit
button is clicked, providing a more interactive User eXperience (UX).
7#Step — Now let’s handle the behavior of Edit
button:
GoTo:
app/views/comments/_comment.html.erb
And type the data attributes in the Edit
button:
<%= link_to "Edit", nil, remote: true, class: "btn btn-warning",
data: {
controller: "comments",
action: "comments#toggleForm",
comments_form_param: "edit-form-#{comment.id}",
comments_body_param: "comment-body-#{comment.id}", } %>
Here’s an explanation of the different parts of the code:
data: { ... }
: This option provides data attributes to the link that will be used by JavaScript (Stimulus) to handle the toggling behavior. Let's break down the data attributes:
controller: "comments"
: This specifies that the controller that will handle this link's behavior is theCommentsController.js
(step#6).action: "comments#toggleForm"
: This indicates that thetoggleForm
action within theCommentsController.js
(controller#action) will handle the behavior.comments_form_param: "edit-form-#{comment.id}"
: This data attribute holds the ID of the form related to the comment. The comment's ID is interpolated into the string to make it unique — edit-form-5, for example.comments_body_param: "comment-body-#{comment.id}"
: This data attribute holds the ID of the comment's body element. The comment's ID is again interpolated to ensure uniqueness — comment-body-5, for example.
Please observe a recurring pattern: comments_body_param
(controller_dom_param) to be interpreted by Stimulus and stored in an array. This will be accessed in JavaScript as follows: const dom = event.params["dom"]
.
In summary, this code creates a button link labeled Edit
that, when clicked, triggers a remote request and provides data attributes for JavaScript (Stimulus) to handle. The JavaScript is expected to toggle the visibility of a comment form and comment body based on the provided IDs.
Here is the whole file for your convenience:
<div class="comment-<%= comment.id %> container"
style="border: 1px solid black; padding: 1em; margin: 1em;">
<%= comment.user.email %><br />
<% if (comment.updated_at - comment.created_at ) > 1 %>
<span>Edited <%= time_ago_in_words(comment.updated_at) %> ago</span>
<% else %>
<span>Posted <%= time_ago_in_words(comment.created_at) %> ago</span>
<% end %>
<% if current_user == comment.user %>
<div class="btn-group float-end">
<%= link_to "Edit", nil, remote: true, class: "btn btn-warning",
data: {
controller: "comments",
action: "comments#toggleForm",
comments_form_param: "edit-form-#{comment.id}",
comments_body_param: "comment-body-#{comment.id}", } %>
<%= button_to "Delete", [post, comment], class:"btn btn-danger", method: :delete %>
</div>
<div id="edit-form-<%= comment.id %>" class="d-none" >
<%= render 'comments/form', post: @post, comment: comment, submit_label: "Update" %>
</div>
<% end %>
<hr />
<div id="comment-body-<%= comment.id %>">
<%= comment.body %>
</div>
</div>
8#Step — Now GoTo:
app/views/posts/show.html.erb
And transform this line:
<%= render 'comments/form', post: @post%>
Into:
<%= render 'comments/form', post: @post, comment: @post.comments.build , submit_label: "Reply" %>
The code <%= render 'comments/form', post: @post, comment: @post.comments.build , submit_label: "Reply" %>
in a Rails view is used to render a partial named _form.html.erb
for creating a new comment associated with a post.
Let’s break down what each part of the code does:
<%= render 'comments/form', ... %>
: This line uses therender
helper to render a partial named_form.html.erb
from theapp/views/comments
directory. Partials are reusable pieces of view code that can be included in other views.post: @post
: This is passing the@post
instance variable to the partial. The variable will be available within the_form.html.erb
partial.comment: @post.comments.build
: This is passing a new comment object associated with the@post
object. It's using thebuild
method to create a new comment instance that's related to the post. This is utilized to generate a new comment on the post, providing an opportunity to seamlessly link the forms together (one withid="edit-form"
and another withid="comment-body"
).submit_label: "Reply"
: This is passing the label "Reply" to the partial. It's used to customize the label on the submit button of the comment form.
In summary, this code renders a partial named _form.html.erb
for creating a new comment. The partial receives the @post
instance variable and a new comment object associated with that post. It also allows customizing the label of the submit button. The actual content of the _form.html.erb
partial will likely contain the HTML structure and form elements needed for creating a new comment, including the comment's content and any other relevant information.
9#Step — Now modify 2 lines in:
app/views/comments/_form.html.erb
Line1:
<%= form_with(model: [post, post.comments.build]) do |f| %>
Into:
<%= form_with(model: [post, comment]) do |f| %>
Both of the lines we provided are related to form creation in Rails using the form_with
helper. However, they have a subtle difference in terms of the comment object being built and used within the form.
<%= form_with(model: [post, post.comments.build]) do |f| %>
In this line, a form is being created using the form_with
helper. The model
option is set to an array containing [post, post.comments.build]
. This means that the form will be associated with both the post
object and a new comment object built within the context of that post.
The post.comments.build
part indicates that a new comment is being constructed within the context of the post
. This is often used when you want to create a new comment associated with a specific post.
<%= form_with(model: [post, comment]) do |f| %>
In this line, again a form is being created using the form_with
helper. The model
option is set to an array containing [post, comment]
. Here, comment
seems to refer to an existing comment object.
This implies that you’re creating a form that is associated with both the post
and an already existing comment
object. This might be used, for instance, if you want to edit or update an existing comment associated with a specific post. And that is precisely our intention here. We’ve moved the creation process to the show page, as outlined in step #8.
In summary, the difference between the two lines lies in how the comment object is being used within the form. The first line builds a new comment associated with the post, while the second line assumes that you have an existing comment
object and associates it with the post within the form.
Line2:
Transform this:
<%= f.submit "Reply", class: "btn btn-primary mt-1" %>
Into this:
<%= f.submit submit_label, class: "btn btn-primary mt-1" %>
Both of the lines you provided are related to generating submit buttons within a form using the form_with
helper in Rails. The difference between these two lines is in how the submit button's label is determined:
<%= f.submit "Reply", class: "btn btn-primary mt-1" %>
In this line, the submit button is given a fixed label of “Reply”. This label is directly specified in the line of code. The class
option is also used to apply CSS classes to the button, styling it as a primary button with a top margin.
<%= f.submit submit_label, class: "btn btn-primary mt-1" %>
In this line, the submit button’s label is determined by the submit_label
variable, which presumably holds a value that will be used as the label. This provides flexibility, as the label can be set dynamically based on the context in which the form is used.
Both lines of code generate a submit button styled as a primary button with a top margin. The difference is in how the label for the button is determined: one has a fixed label (“Reply”), while the other uses a variable (submit_label
) to dynamically set the label. The choice between these two lines would depend on the desired behavior and context of your application.
For your convenience, here is the whole file:
app/views/posts/show.html.erb
<%= render @post %>
<div>
<%= link_to "Edit this post", edit_post_path(@post) %> |
<%= link_to "Back to posts", posts_path %>
<%= button_to "Destroy this post", @post, method: :delete %>
</div>
<div class="container">
<%= render 'comments/form', post: @post, comment: @post.comments.build , submit_label: "Reply" %>
<% @comments.each do |comment| %>
<%= render 'comments/comment', post: @post, comment: comment%>
<% end %>
</div>
That’s All, Folks!
See you in the next episode about Noticed v1👋️👋️👋️!
Error:
When running ActiveStorage methods on rails 7 locally occurs:
LoadError (Could not open library vips.so.42
: vips.so.42: cannot open shared object file: No such file or directory. Could not open library libvips.so.42
: cannot open shared object file: No such file or directory):
Solution:
sudo apt-get install -y libvips
What is the purpose of form_with()
method?
The form_with
method is a helper provided by Ruby on Rails that generates HTML forms for creating, updating, or interacting with model objects. It's a versatile tool for generating forms with proper RESTful conventions and built-in support for handling various scenarios, including data submission, AJAX requests, and more. The main purpose of form_with
is to simplify and standardize the process of creating HTML forms within Rails applications.
Here are some key features and purposes of the form_with
method:
- RESTful Conventions:
form_with
helps maintain RESTful conventions by generating appropriate form attributes and HTTP methods (like POST, PUT, PATCH, or DELETE) based on the action and model object. This is crucial for maintaining clean and predictable URLs and routing. - Automatic CSRF Protection: It automatically generates a hidden field containing an authenticity token to protect against Cross-Site Request Forgery (CSRF) attacks.
- Model Binding: It binds the form to a specific model object, simplifying form generation and data handling. This means you don’t need to manually populate the fields or retrieve values when submitting the form.
- Route Helpers: The
form_with
method generates the appropriateaction
attribute for the form, based on the RESTful route helper methods. This ensures that the form is submitted to the correct URL for creating or updating the object. - Resource Nesting: It supports nested resources and automatically handles the routing for nested forms.
- Ajax Support:
form_with
provides built-in support for handling form submissions via AJAX, which can enhance the user experience by allowing data to be sent and received without a full page reload. - Customization: While providing sensible defaults,
form_with
allows you to customize form behavior through various options and configurations. - Unobtrusive JavaScript (UJS): It generates HTML attributes that are compatible with Rails’ UJS library, making it easy to add JavaScript interactions to forms without writing a lot of custom code.
In summary, the form_with
method in Ruby on Rails is designed to streamline the process of generating HTML forms that are tightly integrated with your application's models, routes, and conventions. It simplifies the generation of forms, helps prevent common security issues, and supports various features like AJAX submissions while encouraging adherence to RESTful practices.
git checkout -b add_turbo
rails c
rails s
rails app:update
rails s
clear
bundle exec rails active_storage:install
bundle exec rails db:migrate
rails db:migrate
rails s
sudo apt-get install -y libvips
rails s
References:
Hotwire created by 37signals to power HEY
Get Started with Hotwire in Your Ruby on Rails App by blog.appsignal.com
Active Storage Overview by rubyonrails.org
Related Posts:
00# Episode — RailsSeries — Installing Ruby on Rails Using ASDF — Why ASDF is Better Than RBENV for Rails Bootstrap App?
01# Episode — RailsSeries — How To Send Email In Rails 7? — User Registration and Onboarding.
02# Episode — RailsSeries — 14 Ruby Extensions 4 Vs Code — Based On This Deanin’s video.
03# Episode — RailsSeries — A Rails Blog In VS Code — Quick Start — How To Create A Blog in VS Code — Part I
04# Episode — RailsSeries — A Rails Blog In VS Code — Styling — How To Create A Blog in VS Code — Part II
05# Episode — RailsSeries — A Rails Blog In VS Code — Create Posts — How To Create A Blog in VS Code — Part III
06# Episode — RailsSeries — A Rails Blog In VS Code — Posts Tips&Tricks — How To Create A Blog in VS Code — Part IV
07# Episode — RailsSeries — A Rails Blog In VS Code — Devise — How To Create A Blog in VS Code — Part V
08# Episode — RailsSeries — A Rails Blog In VS Code — Add Comments to Post — How To Create A Blog in VS Code — Part VI
09# Episode — RailsSeries — Rails Blog In VS Code — Using Stimulus — How To Create A Blog in VS Code — Part VII (this one)
10# Episode — RailsSeries — Rails Blog In VS Code — Noticed V1 — Notifications for your Ruby on Rails app — Part VIII
11# Episode — RailsSeries — Rails Blog In VS Code — Noticed V2 — Notifications for your Ruby on Rails app — Part IX
For v7 let’s Tag it all!
git tag -a rails_blog_v7 -m "Blog in Rails 7 - v1.0: Go to https://j3-rails-blog-demo-5a0a55d44e12.herokuapp.com/" -m "0- Learn How to Use Stimulus;" -m "1- Learn about Hotwire Turbo Family;" -m "2- Set up Turbo JavaScript to review a comment;" -m "3- Learn how to pass data from your Front-End V
iew into your Front-End JS" -m "Thank you for downloading this project 😘️👌️👋️😍️"
git push origin rails_blog_v7
j3@JAYTHREE:~/Documents/rails_projects/rails-blog-demo$ git status
On branch add_turbo
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: app/controllers/comments_controller.rb
modified: app/views/comments/_comment.html.erb
modified: app/views/comments/_form.html.erb
modified: app/views/posts/show.html.erb
modified: db/schema.rb
modified: db/seeds.rb
Untracked files:
(use "git add <file>..." to include in what will be committed)
app/javascript/controllers/comments_controller.js
config/initializers/new_framework_defaults_7_0.rb
db/migrate/20230815221100_add_service_name_to_active_storage_blobs.active_storage.rb
db/migrate/20230815221101_create_active_storage_variant_records.active_storage.rb
db/migrate/20230815221102_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb
history.txt
no changes added to commit (use "git add" and/or "git commit -a")
j3@JAYTHREE:~/Documents/rails_projects/rails-blog-demo$ git add -A
j3@JAYTHREE:~/Documents/rails_projects/rails-blog-demo$ git commit -m ":lipstick:feat:add Turbo"
[add_turbo c5283b7] :lipstick:feat:add Turbo
12 files changed, 691 insertions(+), 11 deletions(-)
create mode 100644 app/javascript/controllers/comments_controller.js
create mode 100644 config/initializers/new_framework_defaults_7_0.rb
create mode 100644 db/migrate/20230815221100_add_service_name_to_active_storage_blobs.active_storage.rb
create mode 100644 db/migrate/20230815221101_create_active_storage_variant_records.active_storage.rb
create mode 100644 db/migrate/20230815221102_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb
create mode 100644 history.txt
j3@JAYTHREE:~/Documents/rails_projects/rails-blog-demo$ git push --set-upstream origin add_turbo
Enumerating objects: 43, done.
Counting objects: 100% (43/43), done.
Delta compression using up to 12 threads
Compressing objects: 100% (25/25), done.
Writing objects: 100% (25/25), 10.16 KiB | 3.39 MiB/s, done.
Total 25 (delta 13), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (13/13), completed with 13 local objects.
remote:
remote: Create a pull request for 'add_turbo' on GitHub by visiting:
remote: https://github.com/giljr/rails_blog_demo/pull/new/add_turbo
remote:
To github.com:giljr/rails_blog_demo.git
* [new branch] add_turbo -> add_turbo
branch 'add_turbo' set up to track 'origin/add_turbo'.
j3@JAYTHREE:~/Documents/rails_projects/rails-blog-demo$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
j3@JAYTHREE:~/Documents/rails_projects/rails-blog-demo$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
j3@JAYTHREE:~/Documents/rails_projects/rails-blog-demo$ git fetch
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), 637 bytes | 637.00 KiB/s, done.
From github.com:giljr/rails_blog_demo
b5fb89f..2b184ad master -> origin/master
j3@JAYTHREE:~/Documents/rails_projects/rails-blog-demo$ git pull
Updating b5fb89f..2b184ad
Fast-forward
app/controllers/comments_controller.rb | 12 +++
app/javascript/controllers/comments_controller.js | 22 ++++
app/views/comments/_comment.html.erb | 21 +++-
app/views/comments/_form.html.erb | 4 +-
app/views/posts/show.html.erb | 4 +-
config/initializers/new_framework_defaults_7_0.rb | 148 +++++++++++++++++++++++++++
db/migrate/20230815221100_add_service_name_to_active_storage_blobs.active_storage.rb | 22 ++++
db/migrate/20230815221101_create_active_storage_variant_records.active_storage.rb | 27 +++++
db/migrate/20230815221102_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb | 8 ++
db/schema.rb | 4 +-
db/seeds.rb | 4 +-
history.txt | 426 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 files changed, 691 insertions(+), 11 deletions(-)
create mode 100644 app/javascript/controllers/comments_controller.js
create mode 100644 config/initializers/new_framework_defaults_7_0.rb
create mode 100644 db/migrate/20230815221100_add_service_name_to_active_storage_blobs.active_storage.rb
create mode 100644 db/migrate/20230815221101_create_active_storage_variant_records.active_storage.rb
create mode 100644 db/migrate/20230815221102_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb
create mode 100644 history.txt
j3@JAYTHREE:~/Documents/rails_projects/rails-blog-demo$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
Essence of thought:
1)METHOD CONTROLLER(comments_controller.rb): -> udpate() ;
2)MARK FOR JS(_comment.html.erb): -> 2 <div>: edit_form & comment_boby;
3)JS(create JavaScript file):->app/javascript/controllers/comments_controller.js;
4)LINK FRONT TO BACKEND(EDIT BUTTON): -> _comments.html.erb -> data{...};
5)SEND VARIABLES TO BE RENDERED(posts/show.html.erb): comment & submit_label;
6)DO NOT BUILD, RENDER VARIABLE DIRECTLY(comment): -> show()