使用Turbo Frames (不使用像Best_In_Place这样的gem,因为它需要jQuery,并且在Rails 7中不能很好地工作) 创建原地编辑 *-模型的单个属性**。
为了实现这一点,我遵循这个教程:https://nts.strzibny.name/single-attribute-in-place-editing-turbo/(编写于2022年1月)
本教程与Ruby 3.2.0、Rails 7.0.4并不完全匹配,需要在显示页面上进行一个变量调整才能正常工作。
遗憾的是,本教程方法中目前没有验证反馈,因为所实现的turbo_frame表单没有包含它。
问题:如何正确添加验证反馈和错误路由?(最好是仅turbo_frames解决方案)
教程摘要:
- 创建新应用并搭建一个模型:用户名:字符串
- 对UsersController的更改(控制器上编辑单个属性的新操作,和将edit_name添加到before_action列表)
before_action :set_user, only: %i[ show edit edit_name update destroy ]
# GET /users/1/edit_name
def edit_name
end
- 添加到routes.rb*(用于编辑单个特定属性的新路由)*
resources :users do
member do
get 'edit_name'
end
end
- 创建视图/users/edit_name.html.erb*(支持编辑特定属性(此处为名称)的新视图页面)。*
<%= turbo_frame_tag "name_#{user.id}" do %>
<%= form_with model: @user, url: user_path(@user) do |form| %>
<%= form.text_field :name %>
<%= form.submit "Save" %>
<% end %>
<% end %>
_user.html.erb文件 * 上的附加内容(链接到创建的turbo帧表格edit_name.html.erb)
<%= turbo_frame_tag "name_#{user.id}" do %>
Name: <%= link_to @user.name, edit_name_user_path(@user) %>
<% end %>
在启动应用服务器时,我收到关于@user为nil:Class的错误。
为了让教程工作,我必须更改_user.html.erb文件,以便在链接中使用user的局部变量。
- 再次编辑**_user.html.erb***(将示例变量@user更改为局部变量user)*
<%= turbo_frame_tag "name_#{user.id}" do %>
Name: <%= link_to user.name, edit_name_user_path(user) %>
<% end %>
有了这一更改,教程可以正常工作,允许通过turbo帧进行单个属性原地编辑!但没有实现模型验证反馈。
下面,我将尝试处理验证,首先将验证添加到models/user.rb
class User < ApplicationRecord
validates :name, presence: true
validates :name, comparison: { other_than: "Jason" }
end
建议解决方案:
为弹出的编辑错误创建一个新的turbo_stream文件*(其目标turbo_frame标签中有一个错误,它需要能够以启动单个属性编辑的任何父turbo frame为目标)*
<%= turbo_stream.replace"name_#{@user.id}" do %>
<%= form_with model: @user, url: user_path(@user) do |form| %>
<% if @user.errors.any? %>
<div style="color: red">
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% @user.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<% if @user.errors[:name].any? %>
<%= form.label :name, style: "display: block" %> <%= form.text_field :name %>
<% end %>
<% if @user.errors[:active].any? %>
<%= form.label :active, style: "display: block" %> <%= form.check_box :active %>
<% end %>
<%= form.submit "Save" %>
<% end %>
<% end %>
并编辑UsersController.rb更新方法以处理turbo流错误
# PATCH/PUT /users/1 or /users/1.json
def update
respond_to do |format|
if @user.update(user_params)
format.html { redirect_to user_url(@user), notice: "User was successfully updated." }
format.json { render :show, status: :ok, location: @user }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @user.errors, status: :unprocessable_entity }
format.turbo_stream do
if @user.errors[:name].any?
@user.name = nil #so that it does not repopulate the form with the bad data
if @user.errors[:active].any?
@user.active = nil
end
render :edit_errors, status: :unprocessable_entity
end
end
end
end
除了在无效条目后生成的表单上输入一个成功的编辑后,这一切都可以工作,它只呈现该条目的显示,而不是所有条目。
完成所有这些操作的“更干燥"的方法是什么?(以及我如何针对仅更新turbo流中的一个帧,以便在验证成功后仅更新一个场)?
从哲学上讲,与仅仅使用jQuery和Gem Best_In_Place相比,这一切是否值得???似乎修改的数量正在堆积,如果跨多个属性支持这样的功能,代码将变得丑陋?
1条答案
按热度按时间k97glaaz1#
既然最初的问题已经解决了,我将添加一些其他的方法来实现这一点。你自己完成这一点需要做更多的工作,而且你也不会拥有一些gem可以给你的所有功能。另一方面,它的代码要少得多,而且你可以完全控制一切。此外,如果你只需要有一个字段是可编辑的,安装gem和jquery的开销太大。
设置:
Turbo帧
作为一个简单的例子,我将只修改默认表单,而不涉及控制器:
一个二个一个一个
就是这样,每个属性都被呈现,可编辑,电子邮件显示验证错误。另外,因为所有
turbo_frame_tag
都有唯一的id
,所以索引页面上的所有内容都可以与多个用户一起使用。涡轮流
您也可以使用
turbo_stream
来获得更大的灵活性,使其更具动态性,但它更像是一个设置。此外,添加在适当位置编辑全名的功能,将 * first_name * 和 * last_name * 字段放在一起: