更新深度嵌套模式与轨和angularjs [英] Updating deeply nested models with rails and angularjs
问题描述
我已经研究了这个问题非常多,专门为深嵌套模型无解。我想出了以下修补程序,不知道是否有更好的方法。
I have researched this question very much, with no solution specifically for deeply nested models. I have come up with the following fix, wondering if there is a better way.
我试图削减下来是几乎一样简单,我可以把它解释这个问题,我的解决方案。
I've tried to cut this down to be nearly as simple as I can make it to explain the issue and my solution.
问题是,存在着以下的ActiveRecord模型轨道:
The issue is that there exist the following ActiveRecord models in rails:
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 $资源呼叫发送到'模板/:身份证'和更新整个儿链。 (每片链之前创建的,在模板创建过程。当模板定稿时需要有一个统一的更新。)
and in angular, the goal is to send a single ngResource $resource call to 'templates/:id' and update the entire chain of children. (Each piece of the chain is created prior, in the template creation process. The need for a unified update occurs when the template is finalized.)
### 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如上图所示:
As far as I have worked out, the fix is to declare *_attributes as shown above:
params[:template][:sections_attributes] = params[:sections]
由于角无力送参数Rails是寻找格式。
because of angular's inability to send the format of parameters that rails is looking for.
这显然感觉就像一个哈克的解决方案。有没有更好的办法,而使用angularjs处理深度嵌套的轨道模式?
This obviously feels like a hacky solution. Is there no better way to handle deeply nested rails models while using angularjs?
推荐答案
如此GitHub上的Rails问题,这是与AngularJS $资源发送参数使用 accepts_nested_attributes_for
。
As discussed in this Rails github issue, this is an acknowledged issue with the way that AngularJS $resource sends parameters, versus what Rails expects when using accepts_nested_attributes_for
.
每这一问题,并且直到在Rails解决这个解决了,这里是可以在上述实施例可以改变以分离其各部分更可管理的一个位
Per that issue, and until this is resolved in a Rails fix, here is what can be changed in the above example to separate its parts to be a bit more manageable:
添加到任何轨道控制器,模型使用 accepts_nested_attributes_for
:
Add to any rails controller which model uses 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
移动清理滑轨控制器Update方法嵌套的 * _属性
声明的AngularJS控制器保存模型前:
Clean up the Rails controller Update method by moving the nested *_attributes
declarations to the AngularJS controller before saving the model:
$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})
这不是pretty但是这一切似乎可以为这一非常具体的问题进行,直到它打补丁。
It's not pretty but that's seemingly all that can be done for this very specific issue until it's patched.
这篇关于更新深度嵌套模式与轨和angularjs的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!