如何在表单声明块之外添加额外的表单字段

Uzb*_*jon 9 ruby-on-rails ruby-on-rails-plugins ruby-on-rails-3

主要目标:允许插件,宝石向预定义表单添加其他表单字段.

例如,应用程序有一个设计登录表单:

<%= form_for(resource, :as => resource_name, ...) do |f| %>
  <%= devise_error_messages! %>
  ...
<% end %>
所有注册表单中添加一个附加字段.

有没有办法从我的rails-plugin/railtie向表单添加一个额外的字段,并定义一个promo code回调方法(对我的附加字段数据采取行动)?

优点:

  • 它允许在2天或一周内删除功能,只需将其从gem文件中删除即可
  • 保证核心站点的功能不被破坏,它简单地回归到原始功能
  • 保证开发人员没有在主应用程序中的任何地方留下任何代码
  • plugin/railtie负责保存/更新属于它的数据

看看ActionView代码,似乎没有内置的方法.你的想法是什么?

注意:Drupal的on_submit钩子就是一个很好的例子.

Tom*_*ing 1

想法的步骤:

1)定义一个模型如AdditionalField(id, field_name, field_type, default_value, is_required)

2)然后创建一个函数,例如:

def self.for_form(my_form_name = nil)
 if my_form_name.nil?
  self.all
else
  self.find(:all, :contitions => {:form_type => my_form_name.type} # or whatever selection criteria
end
Run Code Online (Sandbox Code Playgroud)

3)然后您可以迭代找到的AdditionalFields并根据需要构建正确的字段类型。

我将此解决方案用于比较网站,他们需要为每种不同的比较类型配置调查问卷。

这是我使用的渲染代码,您需要修改它以适合您的情况。关系是:

convention -< booking >- user
convention -< convention_question
booking -< guests
guest -< guest_answers
Run Code Online (Sandbox Code Playgroud)

问题助手

def render_guest_questions(guest, convention_question)      

    fields_for "booking[guest_answer_attributes][]", convention_question do |m|
      case convention_question.display_type
      when "Text"
        '<td>' + text_field_tag("booking[guest_answer_attributes][convention_question_#{guest.id}_#{convention_question.id}]") + '</td>'
      when "Boolean"
        '<td>' + hidden_field_tag("booking[guest_answer_attributes][convention_question_#{guest.id}_#{convention_question.id}]", "No") + check_box_tag("booking[guest_answer_attributes][convention_question_#{guest.id}_#{convention_question.id}]", "Yes") + '</td>'
      end
    end

end
Run Code Online (Sandbox Code Playgroud)

控制器

# TURN GUEST/QUESTIONS INTO guest answers
if params[:booking] && !params[:booking].blank? && !params[:booking][:guest_answer_attributes].blank?
    params[:booking][:guest_answer_attributes].each do |k,v|
      handle_answers(k, v)
    end
end

def handle_answers(k, v)
  x = k.mb_chars.split(/_/)
  g_id = x[2]
  q_id = x[3]
  item = GuestAnswer.find_or_create_by_guest_id_and_convention_question_id(
                  {:guest_id => g_id,
                  :convention_question_id => q_id, 
                  :answer => v})
 end
Run Code Online (Sandbox Code Playgroud)