在Ruby / Rails应用程序中命名/生成表单字段的麻烦

时间:2011-12-12 17:04:39

标签: ruby-on-rails

我对Ruby / Rails有点新鲜,我发现它涉及很多“魔术”。这可能是一件好事,但它也很难弄清楚为什么有些东西可行或(在这种情况下)没有。我的问题是弄清楚如何命名/配置我的表单字段,以便“只是工作。”

我正在使用四个主要对象,数据集,要求,模块和配置(下面命名数据集,module_requirements,mods和module_configuration)。模块具有要求(多对多),并且可能有多个数据集满足特定要求(多对一)。模块可能有许多配置(一对多)。通过这些关系,我们可以看到配置可能与许多数据集(多对多)相关联。特定配置与某些特定数据集之间的实际关联通过has_and_belongs_to_many关系进行管理。

我正在创建一个界面,允许用户通过选择将用于填充相关模块要求的数据集来编辑配置。

因此,用户位于“配置”页面上,并看到一个下拉框列表,每个需求一个。每个下拉列表都填充了可以满足给定要求的各种数据集。我的问题是我无法弄清楚如何构造表单字段,以便在提交表单时保存选定的数据集。

==> The basic data model in more detail:

class Dataset < ActiveRecord::Base
    belongs_to :module_requirement
    has_many :mods, :through => :module_requirement
    has_many :module_configurations, :through => :mods
end

class ModuleRequirement < ActiveRecord::Base
  belongs_to :dataset_type
  has_and_belongs_to_many :mod
  has_many :module_configuration, :through => :mod, :source => :module_configurations
  has_many :dataset
end

class Mod < ActiveRecord::Base
  validates :name,        :presence => true
  validates :description, :presence => true,
                          :length => { :minimum => 5 }

  has_and_belongs_to_many :module_requirements  
  has_many :module_configurations
  has_many :datasets, :through => :module_requirements
end

class ModuleConfiguration < ActiveRecord::Base
  belongs_to :mod
  has_many :module_requirements, :through => :mod
  has_and_belongs_to_many :datasets
end

==> From module_configurations_controller.rb:

def edit
    @module_configuration = ModuleConfiguration.find(params[:id])

    # List datasets by their requirements to provide a drop down box for each requirement listing only relevant datasets
    @datasetsByReq = Hash.new

    Dataset.all.collect{ |d| if(!d.module_requirement.nil?)
                               @datasetsByReq[d.module_requirement.id] ||= Array.new   # Create an empty array if needed
                               @datasetsByReq[d.module_requirement.id].push(d)         # Append config to the array
                             end }   

    # Find the selected dataset for each requirement                             
    @selectedDataset = Hash.new
    @module_configuration.datasets.all.collect{ |d| @selectedDataset[d.module_requirement.id] = d}
end


def update
    @module_configuration = ModuleConfiguration.find(params[:id])

    respond_to do |format|
      if @module_configuration.update_attributes(params[:module_configuration])
        format.html { redirect_to @module_configuration, notice: 'Module configuration was successfully updated.' }
        format.json { head :ok }
      else
        format.html { render action: "edit" }
        format.json { render json: @module_configuration.errors, status: :unprocessable_entity }
      end
    end
  end

==> From module_configurations/edit.html.erb

<%= simple_form_for(@module_configuration) do |f| %>

  ... other fields here ...

  <!-- Produce one dropdown filled with datasets per requirement: -->
  <% config.mod.module_requirements.each do |req| %>
    <%= f.fields_for :datasets , req do |r|%>

      <% selected = @selectedDataset[req.id].nil? ? -1 : @selectedDataset[req.id].id%>              <== Problem is likely here...

      <%= collection_select :requirement_id, :dataset_id, @datasetsByReq[req.id] || [], :id, :name, <== ...and/or here
                         :include_blank => 'None specified', :selected => selected %> 
    <% end %>
  <% end %>
<% end %>

编辑module_configuration时,用户应该能够为每个需求选择一个数据集。上面的代码产生了下拉确定,但我无法弄清楚如何命名它们,以便在提交表单时保存数据。

使用最新版本的所有内容,在Linux上运行。

感谢您提供的任何帮助!

<小时/> 不再寻求解决方案,通过不同的机制解决。我确实确认问题与collection_select的命名方式有关,但我担心完整的解释会如此深奥和具体,以至于它对社区来说毫无用处。

1 个答案:

答案 0 :(得分:0)

我在理解你的不同模型的逻辑时遇到了一些麻烦,因为这些类之间似乎存在很多关系,而我现在很难理解这些关系。但是如果您的表单使用关系正确地与您的模型一起工作,那么您应该没问题。

如果您只是在保存表单时遇到问题,那么您的模型需要知道他们应该保存嵌套属性或模型以及与当前模型的关系。您可以在模型中使用以下命令执行此操作:

accepts_nested_attributes_for :relationship_name

所以例如,一个类可能是这样的:

class ModuleConfiguration < ActiveRecord::Base
  belongs_to :mod
  has_many :module_requirements, :through => :mod
  has_and_belongs_to_many :datasets
  accepts_nested_attributes_for :datasets
end

这将为模型添加必要的方法以保存关系模型中的数据。我的另一个经验法则是,当你使用模型中的关系时,你永远不应该在表单中使用循环。这是因为f.fields_for :relationship_name将自动循环关系。在Rails中,只要你感觉自己正在对抗谷物,它通常意味着有更简单的方法。