i have researched question much, no solution nested models. have come following fix, wondering if there better way.
i've tried cut down simple can make explain issue , solution.
the issue there exist following activerecord models in rails:
deeply nested object tree
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 and in angular, goal send single ngresource $resource call 'templates/:id' , update entire chain of children. (each piece of chain created prior, in template creation process. need unified update occurs when template finalized.)
### classfactory.coffee ### # # create connection api # ... return $resource('api/:class/:id', { format: 'json' }, {...}) # ... ### edittemplatecontroller.coffee ### # # create angular template resource, save it, , redirect editing view # ... $scope.template = new classfactory({class: 'templates'}) $scope.template.$save({class: 'templates'}, (res)-> $location.path('templates/'+res.id+'/edit') ) # # update angular object # ... $scope.savetemplate = -> $scope.template.$update({class: 'templates', id: $scope.template.id}) #... ### templates_controller.rb ### # # create single db interaction deliberately declared parameters , nested *_attributes parameters # ... def update params[:template][:sections_attributes] = params[:sections] params[:template][:sections_attributes].each |paramsection| paramsection[:columns_attributes] = paramsection[:columns] paramsection[:columns_attributes].each |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 # ... as far have worked out, fix declare *_attributes shown above:
params[:template][:sections_attributes] = params[:sections] because of angular's inability send format of parameters rails looking for.
this feels hacky solution. there no better way handle nested rails models while using angularjs?
as discussed in this rails github issue, acknowledged issue way angularjs $resource sends parameters, versus rails expects when using accepts_nested_attributes_for.
per issue, , until resolved in rails fix, here can changed in above example separate parts bit more manageable:
add rails controller model uses accepts_nested_attributes_for:
class modelcontroller < applicationcontroller nested_attributes_names = model.nested_attributes_options.keys.map |key| key.to_s.concat('_attributes').to_sym end wrap_parameters include: model.attribute_names + nested_attributes_names # ... end clean rails controller update method moving nested *_attributes declarations angularjs controller before saving 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}) it's not pretty that's seemingly can done specific issue until it's patched.
Comments
Post a Comment