使用rails和angularjs更新深层嵌套模型

我已经非常研究了这个问题,没有专门针对深层嵌套模型的解决方案。 我想出了以下修复,想知道​​是否有更好的方法。

我试图将其减少到几乎一样简单,我可以解释这个问题和我的解决方案。

问题是rails中存在以下ActiveRecord模型:

深层嵌套的对象树

class Template has_many :sections, dependent: :destroy accepts_nested_attributes_for :sections has_many :columns, through: :sections, dependent: :destroy has_many :fields, through: :columns, dependent: :destroy class Section belongs_to :template has_many :columns, dependent: :destroy accepts_nested_attributes_for :columns class Column belongs_to :section has_many :fields, dependent: :destroy accepts_nested_attributes_for :fields class Field belongs_to :column‏ 

并且在角度上,目标是将单个ngResource $ resource调用发送到’templates /:id’并更新整个子链。 (在模板创建过程中,每个链的每个部分都是先创建的。当模板完成时,需要进行统一更新。)

 ### ClassFactory.coffee ### # # Create a connection to the API # ... return $resource('api/:class/:id', { format: 'json' }, {...}) # ... ### EditTemplateController.coffee ### # # Create angular template resource, save it, and redirect to editing view # ... $scope.template = new ClassFactory({class: 'templates'}) $scope.template.$save({class: 'templates'}, (res)-> $location.path('templates/'+res.id+'/edit') ) # # Update the angular object # ... $scope.saveTemplate = -> $scope.template.$update({class: 'templates', id: $scope.template.id}) #... ### templates_controller.rb ### # # Create a single DB interaction with deliberately declared parameters and nested *_attributes parameters # ... def update params[:template][:sections_attributes] = params[:sections] params[:template][:sections_attributes].each do |paramSection| paramSection[:columns_attributes] = paramSection[:columns] paramSection[:columns_attributes].each do |paramColumn| paramColumn[:fields_attributes] = paramColumn[:fields] end end template = current_user.templates.find(params[:id]) template.update_attributes(allowed_params) head :no_content end private def allowed_params params.require(:template).permit( :name, sections_attributes: [ :id, :name, columns_attributes: [ :id, :fields_attributes: [ :id, :name, :value ] ] ] end # ... 

据我所知,修复是声明* _attributes,如上所示:

 params[:template][:sections_attributes] = params[:sections] 

因为angular无法发送rails正在寻找的参数格式。

这显然感觉像是一个hacky解决方案。 使用angularjs时,没有更好的方法来处理深层嵌套的rails模型吗?

正如在这个Rails github问题中所讨论的,这是一个公认的问题,AngularJS $资源发送参数的方式,与Rails在使用accepts_nested_attributes_for时的期望。

根据该问题,直到在Rails修复程序中解决此问题,以上示例中可以更改以将其部分分开以便更易于管理:

添加到任何rails控制器,该模型使用accepts_nested_attributes_for

 class ModelController < ApplicationController nested_attributes_names = Model.nested_attributes_options.keys.map do |key| key.to_s.concat('_attributes').to_sym end wrap_parameters include: Model.attribute_names + nested_attributes_names # ... end 

在保存模型之前,通过将嵌套的*_attributes声明移动到AngularJS控制器来清理Rails控制器更新方法:

 $scope.saveTemplate = -> $scope.template.sections_attributes = $scope.template.sections $scope.template.sections_attributes.forEach((section)-> section.columns_attributes = section.columns section.columns_attributes.forEach((column)-> column.fields_attributes = column.fields ) ) $scope.template.$update({class: 'templates', id: $scope.template.id}) 

它并不漂亮,但看起来就可以为这个非常具体的问题做些什么,直到它被修补。