form_with
in Rails 5.1.3 & Ruby 2.3.0我发现的最好的文档就在这里
# The parameters in the forms are accessible in controllers according to
# their name nesting. So inputs named +title+ and <tt>post[title]</tt> are
# accessible as <tt>params[:title]</tt> and <tt>params[:post][:title]</tt>
# respectively.
# friendships_controller.rb
...
private
def friendship_params
params.require(:friendship).permit(:user_id, :id)
end
# Works
def destroy
Friendship.remove_friend(current_user.id, params[:id].to_i)
end
# Doesn't work
def destroy
Friendship.remove_friend(friendship_params[:user_id].to_i, friendship_params[:id].to_i)
end
# form_with
<%= form_with model: Friendship,
url: user_friendship_path(
user_id: current_user.id
id: other_user.id,
), method: :delete do |f| %>
<button class='button'></button>
<% end %>
我知道命名有点令人困惑,我仍然没有想出如何让form_with
正确映射到我需要的路线。 friendships#destroy
位于/users/:user_id/friendships/:id(.:format)
路
resources :users do
resources :friendships
end
Started DELETE "/users/1/friendships/8" for 127.0.0.1 at 2018-01-02 03:21:40 +0700
Processing by FriendshipsController#destroy as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"fWnYwpNDItctgg3q/TYIXy5VRO55nwQRINCCykMsDPAFBfwJKjMZ1dneNbg 5yFNHaQP+lXR4ViTje6mK+dCmVg==", "user_id"=>"1", "id"=>"8"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.2ms) BEGIN
(0.1ms) COMMIT
Friendship Load (1.0ms) SELECT "friendships".* FROM "friendships" WHERE "friendships"."friend_id" = $1 AND "friendships"."user_id" = $2 ORDER BY "friendships"."id" ASC LIMIT $3 [["friend_id", 1], ["user_id", 8], ["LIMIT", 1]]
SQL (1.2ms) DELETE FROM "friendships" WHERE "friendships"."id" = $1 [["id", 499]]
Friendship Load (0.5ms) SELECT "friendships".* FROM "friendships" WHERE "friendships"."friend_id" = $1 AND "friendships"."user_id" = $2 ORDER BY "friendships"."id" ASC LIMIT $3 [["friend_id", 8], ["user_id", 1], ["LIMIT", 1]]
SQL (0.9ms) DELETE FROM "friendships" WHERE "friendships"."id" = $1 [["id", 498]]
Completed 400 Bad Request in 13ms (ActiveRecord: 4.2ms)
ActionController::ParameterMissing (param is missing or the value is empty: friendship):
app/controllers/friendships_controller.rb:40:in `friendship_params'
app/controllers/friendships_controller.rb:22:in `destroy'
也许我不应该说它不起作用,无论是否有friendship_params
,行为都是我的期望。但是,返回400 Bad Request
的服务器日志对我来说是一个红旗。
该路由是嵌套资源,因此您应该为该路径提供两个参数。你还需要提供范围,以便在params中给它“友谊”键。
<%= form_with scope: :friendship, url: user_friendship_path(current_user, other_user), method: :delete do |f| %>
<button class='button'></button>
<% end %>
这段代码有点令人困惑,我建议简单的方法就像改变你的路线一样
resources :users do
resources :friendships
end
改成
resources :users
resources :friendships
并在视图上
<%= link_to "Remove Friend", friendship_path(friend_id), method: :delete, data: {confirm: "Are you sure"}, class: "btn btn-xs btn-danger" %>
最后是控制器
def destroy
@friendship = current_user.friendships.where(friend_id: params[:id]).first
@friendship.destroy
flash[:notice] = "Friend was removed"
redirect_to(my_friends_path)
end
希望能有所帮助
答案是form_with
的参数没有将实际参数传递给密钥Friendship
,我们必须在表单体内手动传递它们。
<%= form_with model: Friendship, url:
user_friendship_path(
current_user, other_user
), method: :delete do |f| %>
<%= f.hidden_field :id, value: other_user.id %>
<button class='button'></button>
<% end %>