星舰识别指南:飞行员与星舰的关联

在这篇指南中,将跟随王牌反抗军飞行员,他们将接近应用程序的表面。他们将通过应用程序的超级结构,建立自己(飞行员)与他们驾驶的星舰之间的关系。

控制器

由于所有的重工作都由定义在领域模型中的ActiveRecord配置处理,星舰模型的控制器相当标准。作为快速回顾,这里是ships_controller中的create方法的样子:

def create @ship = Ship.new(params[:ship]) if @ship.save redirect_to(ships_path, :notice => "The #{@ship.name} ship has been saved successfully.") else render(:new, :error => @ship.errors) end end

如果对查看完整的控制器感兴趣,可以在这里查看。

辅助方法

借鉴了Railscast,添加了一些辅助方法来简化生活:

module ApplicationHelper def link_to_remove_fields(name, f, options = {}) f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)", options) end def link_to_add_fields(name, f, association, options = {}) new_object = f.object.class.reflect_on_association(association).klass.new fields = f.fields_for(association, new_object, :child_index => "new_#{ association }") do |builder| render(association.to_s.singularize + "_fields", :f => builder) end link_to_function(name, "add_fields(this, '#{ association }', '#{ escape_javascript(fields) }')", options) end end

上面的代码几乎是从Railscast中逐字复制的,但认为仍然值得一提:

link_to_remove_fields:这个方法将创建一个隐藏的_destroy字段(这告诉否应该删除记录),以及一个将调用JavaScript方法来更新_destroy字段的超链接。

link_to_add_fields:这个方法将:

  • 创建关联对象的新实例(在这种情况下是一个新的飞行员)。
  • 构建一个可以用来编辑新飞行员对象的表单。
  • :child_index将是一个占位符,将由JavaScript生成的唯一值替换(稍后会详细介绍)。
  • 构建包含飞行员对象的表单的超链接。

fields_for方法让看看link_to_add_fields的第二行和第三行(上面显示的代码中的第8行和第9行)。使用fields_for方法为构建飞行员输入字段。在高层次上,fields_for方法允许构建一个HTML表单,而不需要

标签。这意味着可以将字段放入“父”表单中,而不会有任何问题。

fields_for方法接受一些参数:

  • record_name:想要创建的记录类型的名称。在这种情况下,将为此参数传递“Pilots”。
  • record_object:想要添加/编辑的对象的实例。在这种情况下,这将是一个飞行员对象。在link_to_add_fields方法的上一行(上面显示的代码中的第7行)创建了一个新的飞行员对象。
  • options:可能想要传递给fields_for方法的任何选项。在这种情况下,想要一种方法来唯一地识别创建的每个飞行员。因此,使用:child_index,并将其设置为“占位符”。对于这个特定的例子,占位符文本将是“new_pilots”。这个占位符将被表单显示时(即当add_fields JavaScript方法被调用时)生成的唯一标识符替换。

在fields_for块中,要求它渲染_pilot_fields.html.erb部分视图。注意第二个参数,:f => builder是父表单(即包含正在处理的船的输入字段的表单)。这意味着在调用fields_for时渲染的飞行员字段将是“添加船”表单的一部分,这正是想要的。

此时,fields变量应该看起来有点像这样(整理得可以实际阅读):

Add a Pilot XML

在link_to_add_fields方法的最后一行(上面显示的代码中的第12行),将fields变量的内容传递给link_to_function方法。link_to_function方法将设置一个将调用add_fields JavaScript方法的链接(在下一部分描述)。fields值将用作add_fields方法的content参数。

JavaScript

没有一点JavaScript的网络应用是不完整的。上面显示的辅助方法使用了Rails内置的link_to_function辅助方法。link_to_function将用于调用下面显示的JavaScript方法。

function remove_fields(link) { $(link).prev("input[type=hidden]").val("1"); $(link).closest(".fields").hide(); } function add_fields(link, association, content) { var new_id = new Date().getTime(); var regex = new RegExp("new_" + association, "g"); $(link).parent().after(content.replace(regex, new_id)); $("#new-pilot-fields").modal("show"); }

remove_fields函数相当直接:

  • 找到“删除”链接之前的隐藏输入字段(_destroy字段),并将其值设置为1(即true,意味着希望ActiveRecord为删除这个记录)。
  • 找到最近的具有class="fields"的元素(在情况下,这将是一个&ltTR>元素)并隐藏它。就这样!就UI而言,已经删除了一个飞行员!

add_fields函数有点复杂,但没有什么太花哨的:

  • 生成一个基于当前时间的任意唯一ID。
  • 构建一个将搜索“new_” + [关联的名称]的正则表达式(在情况下是“new_pilots”)。
  • 在content(代表飞行员表单的字符串)中搜索并替换“new_pilots”为在第1步生成的唯一ID。
  • 将飞行员表单添加到DOM。

非常清楚,fields_for方法描述的HTML将被添加到“添加船”屏幕(还没有看到,但相信 - 它即将到来)。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485