我有一个 Rails 应用程序,它试图在 User 表中一次更新多个用户。我尝试给出多个用","分隔的 id,但失败并出现"没有路由匹配"之类的错误,我创建了一个自定义方法"分配",将路由指定为 ,
"assign/:id" => "users#assign" , :via => [:put]
我正在尝试通过邮递员REST客户端进行更新。
我的 PUT 请求,
http://localhost:3000/assign/6,7,8 --- PUT
数据:
{
"users":[
{
"trainerid":4
},
{
"trainerid":5
},
{
"trainerid":6
}
]
}
牟控制器
def assign
@ids = params[:id].split(",")
@users = params[:users]
@ids.each_with_index do |i|
@user = User.find(i)
@user.updateattributes(@users[index])
end
render :json => { :status => :ok, :message => "User Updated Successfully"}.to_json
end
在这里,我正在尝试使用id: 4 ,5 ,6
更新用户表中的trainerid
是否可以以其他方式更新。
任何帮助不胜感激.....
为什么要把ID放在URL中?拆分字符串感觉不对。为什么不有一个更简单的路由,只给用户/分配?然后在您的 JSON 中,您可以拥有:
{ "users":[
{ "id":6, "trainer_id":4 },
{ "id":7, "trainer_id":5 },
{ "id":8, "trainer_id":6 }
]}
并这样处理它:
def assign
params[:users].each do |hash|
User.find(hash['id']).update_attributes hash
end
end
显然它需要错误处理等,但这是基本方法。请注意,update_attributes只会更新标记为attr_accessible的属性,因此您不必担心哈希中是否存在 ID。
我已经测试了您的路由,它没有给我路由错误。这是我所拥有的:
match "assign/:id" => "users#assign" , :via => [:put]
使用此路由,正确assign/1,2,3
的请求将路由到控制器的assign
操作。此时,您需要拆分params[:id]
(就像您所做的那样)。
但是,您不需要使用实例变量,也不需要each_with_index
:
def assign
ids = params[:id].split(",")
users = params[:users]
ids.each do |i|
user = User.find(i)
user.update_attributes(users[index])
end
render :json => { :status => :ok, :message => "User Updated Successfully"}.to_json
end
但是,我发布此答案只是为了说这是可以做到的。老实说,我同意@micapam的观点,你真的不需要像这样拆分id。
路线
"assign/:id" => "users#assign" , :via => [:put]
一次只能获取一个 ID。您不能为此路由传递多个 ID。
更新路由以使用edit_multiple和update_multiple操作:
resources :users do
get edit_multiple, :on => :collection
post update_multiple, :on => :collection
end
现在创建edit_multiple操作,该操作使用要更新的用户数据设置@users实例变量:
def edit_multiple
@users = User.all #get the users with specified criteria.
end
在您的edit_multiple.html.erb中:
<%= form_tag :action => "update_multiple" do %>
<% @users.each_with_index do |user, index| %>
<%= fields_for "user[#{index}]", user do |f| %>
<%= f.hidden_field :id, :value => user.id %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :dob %><br />
<%= f.date_select :dob %>
</div>
<% end %>
<%end%>
<div class="actions">
<%= submit_tag "submit" %>
</div>
<% end %>
在控制器中:
def update_multiple
@users = {}
error_count = 0
params[:users].values.each do |user_params|
user = User.find(user_params[:id])
unless user.update_attributes(user_params)
error_count += 1 #increment error count if fails to update
end
@users << user #add user to @users array to render the edit if fails
end
if error_count == 0
redirect_to users_path, :notice => 'Users saved successfully'
else
render :edit_multiple #@users will play its role here
end
end
这可能不是最好的方法。希望这会有所帮助。您也可以使用 JSON 响应。