基于现有资源的表格挑战Rails问题

时间:2011-08-19 12:41:14

标签: ruby-on-rails forms associations

您有一组通过支架创建的相关模型,例如一个 house ,它有许多 rooms ,每个都有很多 windows ,每个 windows 都有 lock
这些资源已经充满了数据,即有人输入了所有信息,例如:一个叫做“厨房”的房间有各种与之相关的窗户,这些窗户每个都有五个不同的锁与它们相关联。

有人出现并说:

  

您是否可以创建一个表单,让某人创建一个新项目,在那里他们可以选择不同的房间,窗口,然后指定他们希望该项目的锁定? (这些已经在系统中,没有什么新东西可以添加,只是与新项目的关联)

这听起来像一个嵌套的形式,但我浪费了很多时间试图解决这个问题 - 有许多级别的嵌套,这使得这很棘手。有什么建议吗?

3 个答案:

答案 0 :(得分:1)

基于会话的解决方案

使用如此深层嵌套的模型前端的选择框是不够的...... 假设这样,您可能想要创建一个current_house,其id在会话中存在(就像current_user一样)。

一旦你的current_house通过导航到你的项目列表视图并点击add_to链接添加不同的项目:

  # house_controller.rb
  def add_to
    current_house.polymorphic_items << Kitchen.find(params[:id])
    redirect_to :back
  end

但是这种基于会话的解决方案有很多种方法可以实现购物车/订单系统。您可能需要添加一个current_item来添加树的每个叶子中的内容,即您房屋的房间。

E.G点击你刚添加的厨房后:

before_filter :set_current_item

def add_to
  current_item.windows << Window.find(id)
end

current_item beeing polymorphic:起居室,浴室等。 但是,如何实现这些正是取决于您的域模型......

作为关于嵌套表格的经验法则,我会遵循路线的轨道指导:不要超过一个级别,否则你最终会陷入混乱。

答案 1 :(得分:0)

是的,这是一个嵌套表格。 Railscasts nested forms是一个很好的起点。

如果系统中已有所有内容,您可能只需要选择框,以便他们可以选择所需内容。另请查看.build方法。如果您有多个嵌套级别,您也可以通过自己传入外键来手动设置关联。

答案 2 :(得分:0)

我认为你可以用一个级别的嵌套属性来建模,给定下面的模型(基于Windows / Locks预先存在,只需要将它们混合并匹配到具有给定锁的一组窗口中):

class House < ActiveRecord::Base
  has_many :rooms
end

class Room < ActiveRecord::Base
  belongs_to :house
  has_many :window_configs
end

class WindowConfig < ActiveRecord::Base
  belongs_to :room
  belongs_to :window
  belongs_to :lock
end

class Lock < ActiveRecord::Base
  has_many :window_configs
end

class Window < ActiveRecord::Base
  has_many :window_configs
end

...基于该模型设置,您可以拥有一个单独的房屋形式,您可以动态添加子房间'定义,每个房间都有一个名称和一组window_configs,每个窗口都有两个选择框(选择一个窗口定义,然后是锁定义)。因为你动态地添加了多个具有多个窗口的房间,所以你需要一些JS来填充新的表单元素,但它们都可以存在于一个嵌套的表单中。

form_for :house do |form|
  # Dynamically add a Room form for each room you want with js
  form.fields_for :room do |room_attributes|
    room_attributes.text_field :name
    # Dynamically add window_config forms on Room w/ JS
    room_attributes.fields_for :window_config do |window_attributes|
      window_attributes.select :window_id, Window.all
      window_attributes.select :lock_id, Lock.all