0

我的目标是能够在从 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 %> 

新闻保存地图控制器

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"=>{"name"=>"我的地图名称", OTHER FIELDS NOT SHOWN ABOVE, "waypoints"=>{"waypointaddress"=>["1600 Pennsylvania Ave NW, Washington, DC 20500" , "350 5th Ave, New York, NY 10118"]}}

4

2 回答 2

0

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

我建议

  1. 看 gem cocoonnested_form
  2. 添加waypoints_attributes到 attr_accessible
  3. 在您的表单中实现来自 gem 的助手(从第 1 点开始)

Rails 的魔法应该做其他的工作

于 2013-09-21T21:44:34.287 回答
0

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

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

在您的情况下,它应该像这样(未经测试!)。该示例基于您在问题中发布的参数。

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
于 2013-09-21T22:45:01.220 回答