Rails has_many 通过带有附加属性的表单

2024-05-26

我正在尝试创建一个表单,允许用户向活动添加/编辑/删除位置。我目前找到的所有例子要么是HABTM表单(不允许编辑存在于表单中的附加属性)has_many through配置)或仅列出现有关系。

下面的图片显示了我想要完成的任务。

该列表将显示每个可用位置。通过campaign_locations模型有关系的位置将被检查,并且其campaign_location特定属性可编辑。未检查的位置应该能够被检查,输入campaign_location特定数据,并在提交时创建新的关系。

下面是我目前已经实现的代码。我尝试过利用collection_check_boxes,这非常接近我所需要的,只是它不允许我编辑 Campaign_location 属性。

我已经能够成功编辑/删除现有的campaign_locations,但我不知道如何将其合并以显示所有可用位置(如附图)。


Models

活动.rb

class Campaign < ActiveRecord::Base
  has_many :campaign_locations
  has_many :campaign_products
  has_many :products,  through: :campaign_products
  has_many :locations, through: :campaign_locations

  accepts_nested_attributes_for :campaign_locations, allow_destroy: true
end

活动地点.rb

class CampaignLocation < ActiveRecord::Base
  belongs_to :campaign
  belongs_to :location
end

位置.rb

class Location < ActiveRecord::Base
  has_many :campaign_locations
  has_many :campaigns, through: :campaign_locations
end

View

活动/_form.html.haml

= form_for @campaign do |campaign_form|

  # this properly shows existing campaign_locations, and properly allows me
  # to edit the campaign_location attributes as well as destroy the relationship
  = campaign_form.fields_for :campaign_locations do |cl_f|
    = cl_f.check_box :_destroy, {:checked => cl_f.object.persisted?}, false, true
    = cl_f.label cl_f.object.location.title
    = cl_f.datetime_field :pickup_time_start
    = cl_f.datetime_field :pickup_time_end
    = cl_f.text_field :pickup_timezone

  # this properly lists all available locations as well as checks the ones
  # which have a current relationship to the campaign via campaign_locations
  = campaign_form.collection_check_boxes :location_ids, Location.all, :id, :title

表单 HTML 的一部分

 <input name="campaign[campaign_locations_attributes][0][_destroy]" type="hidden" value="true" /><input id="campaign_campaign_locations_attributes_0__destroy" name="campaign[campaign_locations_attributes][0][_destroy]" type="checkbox" value="false" />
 <label for="campaign_campaign_locations_attributes_0_LOCATION 1">Location 1</label>
 <label for="campaign_campaign_locations_attributes_0_pickup_time_start">Pickup time start</label>
 <input id="campaign_campaign_locations_attributes_0_pickup_time_start" name="campaign[campaign_locations_attributes][0][pickup_time_start]" type="datetime" />
 <label for="campaign_campaign_locations_attributes_0_pickup_time_end">Pickup time end</label>
 <input id="campaign_campaign_locations_attributes_0_pickup_time_end" name="campaign[campaign_locations_attributes][0][pickup_time_end]" type="datetime" />
 <input id="campaign_campaign_locations_attributes_0_location_id" name="campaign[campaign_locations_attributes][0][location_id]" type="hidden" value="1" />
 <input id="campaign_campaign_locations_attributes_0_pickup_timezone" name="campaign[campaign_locations_attributes][0][pickup_timezone]" type="hidden" value="EST" />

 <input name="campaign[campaign_locations_attributes][1][_destroy]" type="hidden" value="true" /><input id="campaign_campaign_locations_attributes_1__destroy" name="campaign[campaign_locations_attributes][1][_destroy]" type="checkbox" value="false" />
 <label for="campaign_campaign_locations_attributes_1_LOCATION 2">Location 2</label>
 <label for="campaign_campaign_locations_attributes_1_pickup_time_start">Pickup time start</label>
 <input id="campaign_campaign_locations_attributes_1_pickup_time_start" name="campaign[campaign_locations_attributes][1][pickup_time_start]" type="datetime" />
 <label for="campaign_campaign_locations_attributes_1_pickup_time_end">Pickup time end</label>
 <input id="campaign_campaign_locations_attributes_1_pickup_time_end" name="campaign[campaign_locations_attributes][1][pickup_time_end]" type="datetime" />
 <input id="campaign_campaign_locations_attributes_1_location_id" name="campaign[campaign_locations_attributes][1][location_id]" type="hidden" value="2" />
 <input id="campaign_campaign_locations_attributes_1_pickup_timezone" name="campaign[campaign_locations_attributes][1][pickup_timezone]" type="hidden" value="EST" />

 <input name="campaign[campaign_locations_attributes][2][_destroy]" type="hidden" value="true" /><input id="campaign_campaign_locations_attributes_2__destroy" name="campaign[campaign_locations_attributes][2][_destroy]" type="checkbox" value="false" />
 <label for="campaign_campaign_locations_attributes_2_LOCATION 3">Location 3</label>
 <label for="campaign_campaign_locations_attributes_2_pickup_time_start">Pickup time start</label>
 <input id="campaign_campaign_locations_attributes_2_pickup_time_start" name="campaign[campaign_locations_attributes][2][pickup_time_start]" type="datetime" />
 <label for="campaign_campaign_locations_attributes_2_pickup_time_end">Pickup time end</label>
 <input id="campaign_campaign_locations_attributes_2_pickup_time_end" name="campaign[campaign_locations_attributes][2][pickup_time_end]" type="datetime" />
 <input id="campaign_campaign_locations_attributes_2_location_id" name="campaign[campaign_locations_attributes][2][location_id]" type="hidden" value="3" />
 <input id="campaign_campaign_locations_attributes_2_pickup_timezone" name="campaign[campaign_locations_attributes][2][pickup_timezone]" type="hidden" value="EST" />

您遇到的问题是空白位置尚未实例化,因此您的视图无法为其构建表单元素。要解决此问题,您需要在控制器中构建空白位置new and edit行动。

class CampaignController < ApplicationController
  def new
    empty_locations = Location.where.not(id: @campaign.locations.pluck(:id))
    empty_locations.each { |l| @campaign.campaign_locations.build(location: l) }
  end

  def edit
    # do same thing as new
  end
end

然后,在你的edit and update操作中,您需要删除所有留空的位置params用户提交表单时的哈希值。

class CampaignController < ApplicationController
  def create
    params[:campaign][:campaign_locations].reject! do |cl|
     cl[:pickup_time_start].blank? && cl[:pickup_time_end].blank? && cl[:pickup_timezone].blank?
    end
  end

  def update
    # do same thing as create
  end
end

另外,我认为你需要一个隐藏字段location_id.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rails has_many 通过带有附加属性的表单 的相关文章

随机推荐

  • 在 CGridView 中显示另一个模型的属性

    在 Yii 中 我正在做多模型 我的数据库是这样的 Group id name Member id group id firstname lastname membersince 在组控制器中 我想显示成员的属性 一切工作正常 但是当我使用
  • Zuul不转发请求到其他微服务

    我正在使用 Spring Boot 微服务 我已经配置了 eureka zuul 代理和另一个微服务 帐户 如果我直接从帐户拨打电话 则工作正常 帐户和 zuul 服务器都显示在 eureka 上 当我尝试使用 zuul 代理进行访问时 它
  • CTRL + 单击 Sublime Text 2 中的绑定

    我多年来使用 IDE 的一个长期习惯是 CTRL 或命令 单击选择一个完整的单词 这相当于双击当前 ST2 中的单词 我希望能够在ST2中恢复这个能力 我会用按键绑定还是插件来解决这个问题 如果您创建一个sublime text 2 Pac
  • 如何用 C# 发送原始以太网数据包? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 有没有办法通过 C 将原始数据包以太网发送到其他主机 在 Windows 7 中 如果有区别的话 根据 Saint pl 的建议 我找
  • 在浏览器中下载视频,而不是在新选项卡中播放 [CORS]

    I have a 并在其内部href属性 当我点击该属性时 我从第 3 方 api 获得了一个视频 URL a 浏览器打开一个新选项卡并播放视频而不是下载视频 PROBLEM 我需要实现的是点击后直接下载视频 a 而不是在新标签中播放并强制
  • 算法:找到圆中的峰值

    Given n排列成圆圈的整数显示了一种可以找到一个峰值的有效算法 峰值是不小于它旁边的两个数字的数字 一种方法是遍历所有整数并检查每个整数以查看它是否是峰值 这产生O n 时间 似乎应该有某种方法来分而治之 以提高效率 EDIT 好吧 基
  • c#.net MS Access 数据库,未安装 Access [重复]

    这个问题在这里已经有答案了 是否可以 我尝试过谷歌 但我一定是搜索了错误的关键词并且没有得到答案 我有一个仅由 2 3 人使用的小型应用程序 我想将其数据存储在数据库中 我无法安装任何 SQL 服务器 因此我认为访问将是最好的选择 将使用它
  • numba.prange 性能不佳

    我试图整理一个简单的例子来说明使用的好处numba prange对于我自己和一些同事来说 但我无法获得像样的加速 我编写了一个简单的一维扩散求解器 它本质上是在一个长数组上循环 组合元素i 1 i and i 1 并将结果写入element
  • IntelliJ Git 集成 - git --version 空输出

    我目前正在尝试使用 IntelliJ 2016 2 的 Git 集成 但每当我将其指向可执行文件时 我都会遇到以下问题 这在技术上并不会阻止集成工作 但它确实会导致更新索引等问题 我正在运行 Windows 7 完全全新安装 但我在以前的
  • 将图像添加到从 altchunk 创建的 openxml 文档中

    我需要一个从 xhtml 源创建 docx 文件的自动化过程 xhtml 文件包含图像 img 元素 其 src 属性指向外部引用 但是docx文件需要在没有网络连接的情况下可读 所以我需要找到一种方法将图像直接嵌入到docx包中 即在 m
  • 创建新实例,同时仍然使用依赖注入

    环境的快速描述 我有一个代表聊天室并依赖于记录器的类 它与具有横切关注点的系统范围记录器不同 而是与特定聊天室绑定的记录器 它将该聊天室中的所有活动记录到其唯一的日志文件中 当聊天室创建时 我想打开日志文件 当聊天室被销毁时 我想关闭日志文
  • Rails:如何在 Rails 5 中禁用 Turbolink?

    在处理 websocket 时 这是一个持续令人头痛的问题 除了添加错误之外 它还会降低我的性能 由于 ActionCable 是我升级的全部原因 我非常想完全摆脱它 以下内容复制自here http blog steveklabnik c
  • 如何延迟关闭并在窗口服务中运行进程

    我必须在 Windows 关闭时运行一个进程 即应用程序 有什么方法可以延迟 Windows 关闭并在 Windows 服务中运行该应用程序 protected override void OnShutdown Add your save
  • 我想使用 javascript 和按钮更改标签的 src 属性
  • pandas 时间序列的 interp1d

    我想在 pandas 时间序列中的时间之间进行插值 我想使用 scipy interpolate interp1d 或类似的 这pandas interpolate函数是不可取的 因为它需要插入nan值 然后使用插值替换它们 从而修改数据集
  • 如何使用准备好的语句在 postgresql 中插入带有时区的时间戳?

    我正在尝试使用准备好的语句将一个字符串插入到数据库的带有时区字段的时间戳中 其中包括日期 时间和时区 问题是 Timestamp valueof 函数没有考虑字符串包含的时区 因此会导致错误 接受的格式是 yyyy m m d d hh m
  • Netezza 中的 HASH8 函数使用哪种 Jenkins 哈希算法?一次一个/lookup2/lookup3/SpookyHash?

    我需要实现 hash8 函数 或者用 Java 模拟它的输入 输出 Netezza 的简短文档说 hash8 实现了 Jenkins 算法 但是有多种算法 修订版那个名字 http en wikipedia org wiki Jenkins
  • iOS SecKeyRef(公钥)将其发送到服务器[重复]

    这个问题在这里已经有答案了 现在我的公钥有问题 我使用 SecKeyGeneratePair 来生成公钥和私钥 现在我必须将我的公钥发送到服务器 我使用下面的方法将 SecKeyRef 转换为 NSData 我总是得到相同的公钥 不过我将其
  • 仅在 Windows Chrome 上使用变换比例会导致文本模糊

    我遇到了一个关于 CSS 转换的非常令人沮丧的问题scale 我有一个文本块 我想在悬停时将其缩放 105 但它导致文本模糊 但仅限于 Windows 版本的 Chrome 我发现这个问题 https stackoverflow com q
  • Rails has_many 通过带有附加属性的表单

    我正在尝试创建一个表单 允许用户向活动添加 编辑 删除位置 我目前找到的所有例子要么是HABTM表单 不允许编辑存在于表单中的附加属性 has many through配置 或仅列出现有关系 下面的图片显示了我想要完成的任务 该列表将显示每