[Ruby on Rails] Asynchronous communication of posting function, ajax

Target

ajax.gif

Development environment

ruby 2.5.7 Rails 5.2.4.3 OS: macOS Catalina

Premise

-Build login environment with devise -Posting function that only logged-in users can do -Post editing function (update, delete)

flow

1 Introduced gem'jquery-rails' 2 Partial template for the part you want to use asynchronous communication 3 remote: Describe true 4 Create js.erb file 5 Delete controller redirect destination

If it doesn't work, ActionView :: Template :: Error is often displayed in the terminal, I think that most people forget to define variables. After that, if you do not make a mistake in the id name and render description, it should work.

Introduced gem'jquery-rails'

Gemfile


gem 'jquery-rails'

Terminal


$ bundle install

app/assets/javascript/sapplication.js


//= require rails-ujs
//= require activestorage
//= require jquery      <--add to
//= require turbolinks
//= require_tree .

Partial template, remote: add true

This time we will perform asynchronous communication on the new posting screen,

erb:app/views/posts/new.html.erb


<h1>Posts#new</h1>
<span>Currently logged in user:<%= current_user.name %></span>

<--- form_for to form_Change to with, data: {remote: true}Describe--->
<%= form_for(@post, url: posts_path) do |f| %>
<--- --->

	<div>
		<%= f.label :title%><br>
		<%= f.text_field :title, autofocus: true %> <--Add id
	</div>
	<div>
		<%= f.label :contents%><br>
		<%= f.text_area :body %>
	</div>
	<div><%= f.submit "Post" %></div>
<% end %>
<table>
	<thead>
		<tr>
			<th>Posted by name</th>
			<th>title</th>
			<th>Text</th>
			<th></th>
			<th></th>
			<th></th>
		</tr>
	</thead>
	<tbody>  <--Add id

<---from here--->
		<% @posts.each do |post| %>
			<tr>
				<td><%= post.user.name %></td>
				<td><%= post.title %></td>
				<td><%= post.body %></td>
				<td><%= link_to "Details", post_path(post) %></td>
				<td><%= link_to "Edit", edit_post_path(post) %></td>
				<td><%= link_to "Delete", post_path(post), method: :delete %></td>
			</tr>
		<% end %>
<---Partial template up to here--->

	</tbody>
</table>

The modified description is as follows.

erb:app/views/posts/new.html.erb


<h1>Posts#new</h1>
<span>Currently logged in user:<%= current_user.name %></span>
<%= form_with model:[@post], data: {remote: true} do |f| %>
	<div>
		<%= f.label :title%><br>
		<%= f.text_field :title, autofocus: true, id: "text" %>
	</div>
	<div>
		<%= f.label :contents%><br>
		<%= f.text_area :body %>
	</div>
	<div><%= f.submit "Post" %></div>
<% end %>
<table>
	<thead>
		<tr>
			<th>Posted by name</th>
			<th>title</th>
			<th>Text</th>
			<th></th>
			<th></th>
			<th></th>
		</tr>
	</thead>
	<tbody id="post">
		<%= render 'posts/new', posts: @posts %>
	</tbody>
</table>
Supplement render'posts / new', posts: @posts Load the partial template of app / views / posts / _new.html.erb. Then assign @posts to the posts changed to a local variable. * At that time, it is necessary to define @posts in create and destroy. This will be described later.

For the partial template, create the following file and change @posts to a local variable. Write remote: true in the delete button as well.

erb:app/views/posts/_new.html.erb


<% posts.each do |post| %>
	<tr>
		<td><%= post.user.name %></td>
		<td><%= post.title %></td>
		<td><%= post.body %></td>
		<td><%= link_to "Details", post_path(post) %></td>
		<td><%= link_to "Edit", edit_post_path(post) %></td>
		<td><%= link_to "Delete", post_path(post), method: :delete, remote: true %></td>
	</tr>
<% end %>

Create js.erb file

js:app/views/create.js.erb


$('#post').html("<%= j(render 'posts/new', posts: @posts) %>");
$("text_area").val("");
$("#text").val("");

js:app/views/destroy.js.erb


$('#post').html("<%= j(render 'posts/new', posts: @posts) %>");
Supplement $ ('#post'). html ("<% = j (render'posts / new', posts: @posts)%>"); It means to update the html of the render part. $ ("text_area"). val (""); leaves text_area of form_with blank $ ("# Text"). Val (""); leaves text_fild (specified by id) of form_with blank It is recommended because you can use append etc. in addition to html
# Remove controllers redirect destination

app/controllers/posts_controller.rb


  def create
    @posts = Post.all  <---add to
    @post = Post.new(post_params)
    @post.user_id = current_user.id
    if @post.save
      redirect_to new_post_path  <---Delete
    else
      render :new
    end
  end

  def destroy
    @posts = Post.all  <---add to
    @post = Post.find(params[:id])
    @post.destroy
    redirect_to request.referer  <---Delete
  end

Revised.

app/controllers/posts_controller.rb


  def create
    @posts = Post.all
    @post = Post.new(post_params)
    @post.user_id = current_user.id
    if @post.save
    else
      render :new
    end
  end

  def destroy
    @posts = Post.all
    @post = Post.find(params[:id])
    @post.destroy
  end

Recommended Posts