编辑多个记录 - 授予对所有登录用户的访问权限

时间:2009-10-08 11:39:27

标签: ruby-on-rails controller views

据我所知,这是一个视图和控制器问题。

我需要允许用户在我的一个数据库表中编辑多个记录。 Railscast 165处理类似的情况,但对我来说并不是很重要:http://railscasts.com/episodes/165-edit-multiple

我有一套固定的产品,我需要让用户为这些产品添加相关品种。我考虑过更简单的解决方案,要求用户转到产品页面,并一次编辑一个单独的产品,但这对我的应用程序不起作用。相反,我需要为这一项任务提供更多的管理风格功能。

这里的模型关系很简单。产品has_many品种和品种belongs_to产品。在我的用户界面中,我只是让用户从包含网站上所有可用产品的下拉菜单中选择产品,然后用户可以在文本输入中键入各种名称。例如,如果我们谈论苹果,那么用户可以从产品下拉菜单中选择苹果,并且他可以输入“fuji”和各种各样的苹果。我只需要将product_id和品种[name]保存到品种表中。但是,我需要一次为多个记录执行此操作。

目前,我已经通过下拉列表显示了正确的产品选择。问题似乎是变量输入在html中呈现如下:

<label for="nil_class_variety">Variety</label>
<input id="nil_class_name" name="nil_class[name]" size="30" type="text" />  

为了渲染表单的一部分,我遵循Advanced Rails Recipes多模型表单技术(即Ryan Bates方式)。我花了大约10个小时尝试这样做,似乎我现在非常接近,但我不知道这个问题到底是什么。

这是我的设置:

产品控制器

def edit_multiple
  @products = Product.find(:all)
end

 def update_multiple
  params[:product][:existing_variety_attributes] ||= {}

   @products = Product.find(:all)
     if @products.each do |product|
       product.update_attributes!(params[:product].reject { |k,v| v.blank? })
     end
     flash[:notice] = "Updated products!"
     redirect_to edit_user_path(self.current_user)
     else
    render :action => 'edit'
    flash[:error] = "Something went wrong.  Please try again."
  end
end  

Routes.rb#使自定义控制器操作正常工作

map.resources :products, :collection => { :edit_multiple => :get, :update_multiple => :put}    

的观点/产品/ edit_multiple.html.erb

<%= error_messages_for :product %>
<% form_for :product, :url => update_multiple_products_path, :html => { :method => :put } do |f| %>

<div id="varieties">
   <%= render :partial => 'variety' %>
</div>

<p><%= add_variety_link "+ Add another variety" %></p>

<%= f.submit 'Submit Varieties' %>
<%end%>

的观点/产品/ _variety.html.erb

注意:目前,我不会让用户编辑他们提交的品种。所以我从Ryan Bates技术中删除了以下一行,因为它抛出了一个错误而我认为我不需要它,但我可能错了:<%# new_or_existing = variety.new_record? ? 'new' : 'existing' %>

这就是我在这个_variety partial中所拥有的:

<% prefix = "product[new_variety_attributes][]" %>
   <% fields_for @variety do |variety_form| -%>
       <%= collection_select(:product, :product_id, Product.all, :id, :name, {:prompt => true}) %>
       <%= variety_form.label :variety %>
       <%= variety_form.text_field :name %>
<%= link_to_function "- Remove Variety", "$(this).up('.variety').remove()" %>
<%end -%>  

注意:目前您看到的javascript内容正在运行。在edit_multiple视图页面上,我可以动态添加和删除产品/品种输入。正如我所提到的,下拉列表也正常填充。因此,我似乎只需要将各种输入正确渲染并让控制器正确处理它。谢谢你的帮助!

更新

当我从下拉列表中选择一个产品并在品种输入中键入名称时,提交会抛出以下错误并跟踪:

 ActiveRecord::UnknownAttributeError in ProductsController#update_multiple
unknown attribute: product_id

/Library/Ruby/Gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2740:in `attributes='
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2736:in `each'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2736:in `attributes='
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2628:in `update_attributes!'
/Users/michael/dev/fresh/app/controllers/products_controller.rb:74:in `update_multiple'

/Users/michael/dev/fresh/app/controllers/products_controller.rb:73:in each' /Users/michael/dev/fresh/app/controllers/products_controller.rb:73:in update_multiple'

日志显示正确的product_id和我输入的正确名称,但您可以看到它正在调用nil类:

Processing ProductsController#update_multiple (for 127.0.0.1 at 2009-10-08 07:31:05) [PUT]
  Parameters: {"commit"=>"Submit Varieties", "authenticity_token"=>"zzkveSe7qzv2NY8WPrR2cYS376u6DBiz8Vc9iNFLQy8=", "product"=>{"product_id"=>"5"}, "nil_class"=>{"name"=>"yellow"}}

当我尝试输入多个产品/品种记录时,日志除了第一个以外没有识别任何内容。当我输入一个产品/品种记录时,我得到的结果相同。

1 个答案:

答案 0 :(得分:1)

对你的问题的简短回答是@variety在fields_for @variety中未定义。 /app/views/products/_variety.html.erb中该行的正确版本为

<% fields_for :variety do |variety_form| -%>

你的标签行也有一点点挑剔。

<%= variety_form.label :variety %>

应该是

<%= variety_form.label :name, "Variety" %>

我不知道您的目标是一次更新多个产品和品种,还是更新单个产品的品种。假设后者,您应该使用accepts_nested_attributes_for(向下滚动到嵌套属性示例),看起来它可能是一种更简单的方法。另请参阅github Complex-Forms-Example存储库以进行工作演示。

但事实并非如此。在我看来,您的javascript函数正在为产品和品种添加表单/删除值。

这将在控制器中用于添加品种,但需要更多的工作来移除现有品种。但是您链接的railscast提供了将它们组合在一起所需的所有信息。