如何在Rails中删除使用collection_select保存的记录?

时间:2013-09-21 20:38:40

标签: mysql ruby-on-rails rails-activerecord

我的目标是能够在从collection_select中取消选择项目时更新已保存的记录(然后重新提交该记录。)在此先感谢您的帮助!

详情

我有一张Newsavedmaps的表格。 Newsavedmaps可以有很多航点。用户可以在collection_select中选择航点,当他们保存Newsavedmap时,这些航点将保存到他们自己的数据库表中。

问题:当用户打开他们保存的Newsavedmap时,我希望他们能够取消选择一个航点。当他们再次保存Newsavedmap时,我希望删除取消选择的航点。

这是我正在维护的Rails 2.3X应用程序,这就是为什么collection_select在下面使用不同的格式。

模型

class Newsavedmap < ActiveRecord::Base
  belongs_to :itinerary
  has_many :waypoints, :dependent => :destroy
  accepts_nested_attributes_for :waypoints, :reject_if => lambda { |a| a[:waypointaddress].blank? }, :allow_destroy => true
end

查看

    <% form_for @newsavedmap, :html => { :id => 'createaMap' } do |f| %>
      <%= f.error_messages %>               
      <%= f.text_field :name, {:id=>"savemap_name", :size=>30 }%></p>

      <%= collection_select :waypoints, :waypointaddress, @newsavedmap.waypoints, :waypointaddress, :waypointaddress, {}, { :multiple => true, :class => "mobile-waypoints-remove", :id =>"waypoints" } %>

    <% end %> 

Newsavedmaps控制器

def create
  @newsavedmap = Newsavedmap.new(params[:newsavedmap])
  waypoint = @newsavedmap.waypoints.build

  respond_to do |format|
    if @newsavedmap.save
      flash[:notice] = 'The new map was successfully created.'
      format.html { redirect_to "MYURL"}
      format.xml  { render :xml => @newsavedmap, :status => :created, :location => @newsavedmap }
    else
      format.html { render :action => "new" }
      format.xml  { render :xml => @newsavedmap.errors, :status => :unprocessable_entity }
    end
  end
end


def update
  @newsavedmap = Newsavedmap.find(params[:id])

  if @newsavedmap.itinerary.user_id == current_user.id
    respond_to do |format|
      if @newsavedmap.update_attributes(params[:newsavedmap])
        flash[:notice] = 'Newsavedmap was successfully updated.'
        format.html { redirect_to "MYURL" }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @newsavedmap.errors, :status => :unprocessable_entity }
      end
    end
  else
    redirect_to '/'
  end
end

创建新记录时的参数

参数:{“newsavedmap”=&gt; {“name”=&gt;“我的地图名称”,其他字段未显示在上面,“waypoints”=&gt; {“waypointaddress”=&gt; [“1600 Pennsylvania Ave NW,Washington,DC 20500“,”350 5th Ave,New York,NY 10118“]}}

2 个答案:

答案 0 :(得分:0)

我认为你的问题是正确构建的形式(以及来自它的参数)。

我建议

  1. 查看gem cocoonnested_form
  2. waypoints_attributes添加到a​​ttr_accessible
  3. 在表格
  4. 中实施来自gem(来自第1点)的助手

    Rails魔术应该做其他工作

答案 1 :(得分:0)

另一种变体(不使用宝石)(我觉得要困难得多!

您可以删除accept_nested_attributes并直接使用params。但在这种情况下,您应该手动管理所有进程:正确插入记录,正确销毁它们。

在你的情况下它应该像这样(它没有经过测试!)。该示例基于您在问题中发布的params。

def create
  # delete params 'waypoints' it will be manage manually
  waypoints = params[:newsavedmap].delete(:waypoints)
  @newsavedmap = Newsavedmap.new(params[:newsavedmap])
  waypoints.each do |waypoint|
    @newsavedmap.waypoints.build(:waypointaddress => waypoint)
  end
  if @newsavedmap.save
    ...
  end
end

主要问题在于方法update

def update
  # delete params 'waypoints' it will be manage manually
  waypoints = params[:newsavedmap].delete(:waypoints)

  # find and setup attributes
  @newsavedmap = Newsavedmap.find(params[:id])
  @newsavedmap.attributes = params[:newsavedmap]

  # TROUBLES start here
  # destroy not checked (but existed in DB) waypoints
  existed_waypoints = @newsavedmap.waypoints
  existed_waypoint_addresses = existed_waypoints.map(&:waypointaddress)
  new_waypoints = []
  waypoints.each do |waypoint|
    if existed_waypoint_addresses.include?(waypoint)
      # existed waypoint was selected on the form
      # find it and add to new_waypoints
      new_waypoints << @newsavedmap.waypoints.find_by_waypointaddress(waypoint)
    else
      # new waypoint was selected on the form
      # build it and add to new_waypoints
      new_waypoints << @newsavedmap.waypoints.build(:waypointaddress => waypoint)
    end
  end
  # setup new records for waypoints
  @newsavedmap.waypoints = new_waypoints

  if @newsavedmap.save
    # destroy existed but not selected waypoints
    (existed_waypoints - new_waypoints).map(&:destroy)
    ...
  end
end