如何重构这个rails代码 - 一个键/值模型

时间:2009-08-25 12:10:59

标签: ruby-on-rails refactoring

我有以下型号:

class FieldEntryValue < ActiveRecord::Base
  belongs_to :field_entry
end

class FieldEntry < ActiveRecord::Base
  belongs_to :field
  belongs_to :media
  has_many :field_entry_values, :dependent => :destroy
  accepts_nested_attributes_for :field_entry_values, :allow_destroy => true
end

FieldEntriesController有以下方法:

  def new
    @field_entry = FieldEntry.new
    session[:media_id] = params[:media_id]
    session[:field_id] = params[:field_id]
    @field_entry.field = Field.find(params[:field_id])
    generate_fields(true)
    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @field_entry }
    end
  end

  def create
    @field_entry = FieldEntry.new(params[:field_entry])
    @field_entry.media_id = session[:media_id]
    @field_entry.field_id = session[:field_id]
    generate_fields(false)
    respond_to do |format|
      if @field_entry.save
        flash[:notice] = 'FieldEntry was successfully created.'
        format.html { redirect_to(@field_entry) }
        format.xml  { render :xml => @field_entry, :status => :created, :locati$
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @field_entry.errors, :status => :unprocess$
      end
    end
  end

  def generate_fields(do_build)
    @ftype = @field_entry.field.field_type.name
    if @ftype == 'string'
      @field_entry.field_entry_values.build if do_build
      @field_entry.field_entry_values[0].key='name'
    elsif @ftype == 'url'
      2.times{ @field_entry.field_entry_values.build } if do_build
      @field_entry.field_entry_values[0].key='name'
      @field_entry.field_entry_values[1].key='url'
    elsif @ftype == 'imdb'
      1.times{ @field_entry.field_entry_values.build } if do_build
      @field_entry.field_entry_values[0].key='value'
    end
  end

我有一个部分由new和edit加载:

<% form_for(@field_entry) do |f| %>
  <%= f.error_messages %>

  <% f.fields_for :field_entry_values do |fv_f| %>
    <p>
    <%= fv_f.label :key %><br />
    <%= fv_f.text_field :value %>
    </p>
  <% end %>

  <p>
    <%= f.submit 'Save' %>
  </p>
<% end %>

视图应根据类型显示变量计数字段,并使用给定的属性键作为数据的标签和值。

对于类型字符串作为示例,我需要一个标签“Name”(应该是键)和值

除了"fv_f.label :key"显示字符串键而不是键字段的值外,这种方式大多有效。

  1. 如何在视图中显示@field_entry.field_entry_values.key作为标签的值?

  2. 如何让控制器更好/更短。例如,我是否真的需要在new和create方法中设置@field_entry.field_entry_values[0].key='name'以使其显示在视图中并保存在数据库中?

  3. thanx的建议;)我是一个Rails newby,我希望我做的不是太错了;)

2 个答案:

答案 0 :(得分:0)

尝试1。

<% form_for(@field_entry) do |f| %>
  <%= f.error_messages %>

  <% @field_entry.field_entry_values.each do |fv| %>

  <% f.fields_for fv do |fv_f| %>
    <p>
    <%= fv_f.label :value, fv.key %><br />
    <%= fv_f.text_field :value %>

    <%= # this will eliminate the need for generate_fields in create %>
    <%= fv_f.hidden_field :key %> 
    </p>
  <% end %>

  <% end %>
  <p>
    <%= f.submit 'Save' %>
  </p>
<% end %>

答案 1 :(得分:0)

我为问题1找到了更好的解决方案,在rails 2.3中,fields_for循环目标有一个对象属性来获取字段的对象:

<% form_for(@field_entry) do |f| %>
  <%= f.error_messages %>
    <% f.fields_for :field_entry_values do |fv_f| %>
    <p>
      <%= fv_f.label :value, fv_f.object.key%>
      <br />
      <%= fv_f.text_field :value %>
      <%= fv_f.hidden_field :key %>
    </p>
  <% end %>
  <p>
    <%= submit_tag %>
  </p>
<% end %>

点2无法改进很多,也许generate_fields方法可以作为过滤器加载。但除此之外,我现在看不到任何东西,至少在这个数据库结构中是这样。

但是感谢你的帮助:so1o,至少hidden_​​field的东西是有帮助的。