我已经搜索了相关问题,但仍然在使用我的AngularJS前端返回的rails 4到JSON中更新嵌套属性时遇到问题。
问题:下面的代码概述了从我的Rails4应用程序中从AngularJS传递到Candidate模型的JSON。 Candidate模型有很多Works,我试图通过Candidate模型更新Works模型。由于某种原因,Works模型无法更新,我希望有人可以指出我缺少的东西。谢谢你的帮助。
这是候选人AngularJS前端的json:
{"id"=>"13", "nickname"=>"New Candidate", "works_attributes"=>[
{"title"=>"Financial Analyst", "description"=>"I did things"},
{"title"=>"Accountant", "description"=>"I did more things"}]}
Rails然后通过添加候选标头将此JSON转换为以下内容,但不包括候选标头下的嵌套属性,无法通过候选模型更新works_attributes :
{"id"=>"13", "nickname"=>"New Candidate", "works_attributes"=>[
{"title"=>"Financial Analyst", "description"=>"I did things"},
{"title"=>"Accountant", "description"=>"I did more things"}],
"candidate"=>{"id"=>"13", "nickname"=>"New Candidate"}}
candidate_controller.rb包含一个简单的更新:
class CandidatesController < ApplicationController
before_filter :authenticate_user!
respond_to :json
def update
respond_with Candidate.update(params[:id], candidate_params)
end
private
def candidate_params
params.require(:candidate).permit(:nickname,
works_attributes: [:id, :title, :description])
end
end
candidate.rb模型包含以下代码,用于定义与作品模型的has_many关系:
class Candidate < ActiveRecord::Base
## Model Relationships
belongs_to :users
has_many :works, :dependent => :destroy
## Nested model attributes
accepts_nested_attributes_for :works, allow_destroy: true
## Validations
validates_presence_of :nickname
validates_uniqueness_of :user_id
end
最后,works.rb模型定义了has_many关系的另一面:
class Work < ActiveRecord::Base
belongs_to :candidate
end
我感谢您提供的任何帮助,因为我确信我错过了一些相当简单的事情。
谢谢!
答案 0 :(得分:7)
我也在使用Rails和AngularJS之间的JSON API。我使用与RTPnomad相同的解决方案,但找到了一种不必硬编码include属性的方法:
class CandidatesController < ApplicationController
respond_to :json
nested_attributes_names = Candidate.nested_attributes_options.keys.map do |key|
key.to_s.concat('_attributes').to_sym
end
wrap_parameters include: Candidate.attribute_names + nested_attributes_names,
format: :json
# ...
end
请参阅Rails中的issue,了解他们是否/何时解决此问题。
更新10/17
等待公关合并:rails/rails#19254。
答案 1 :(得分:6)
我找到了一种基于rails http://edgeapi.rubyonrails.org/classes/ActionController/ParamsWrapper.html
的rails文档来解决我的问题的方法基本上,Rails ParamsWrapper默认启用从前端包装JSON,并在Rails中使用根元素,因为AngularJS不会在根包装元素中返回数据。以上文档包含以下内容:
“在没有:include或:exclude选项集的ActiveRecord模型上,它只会包装类方法attribute_names返回的参数。”
这意味着我必须使用以下语句显式包含嵌套属性,以确保Rails包含所有元素:
class CandidatesController < ApplicationController
before_filter :authenticate_user!
respond_to :json
wrap_parameters include: [:id, :nickname, :works_attributes]
...
如果有更好的方法在AngularJS和Rails之间传递JSON数据,请为此问题添加另一个答案
答案 2 :(得分:1)
你也可以将patch参数包装设置为始终包含nested_attributes,方法是将其放入例如function convertNumberToWords(amount) {
var words = new Array();
words[0] = '';
words[1] = 'One';
words[2] = 'Two';
words[3] = 'Three';
words[4] = 'Four';
words[5] = 'Five';
words[6] = 'Six';
words[7] = 'Seven';
words[8] = 'Eight';
words[9] = 'Nine';
words[10] = 'Ten';
words[11] = 'Eleven';
words[12] = 'Twelve';
words[13] = 'Thirteen';
words[14] = 'Fourteen';
words[15] = 'Fifteen';
words[16] = 'Sixteen';
words[17] = 'Seventeen';
words[18] = 'Eighteen';
words[19] = 'Nineteen';
words[20] = 'Twenty';
words[30] = 'Thirty';
words[40] = 'Forty';
words[50] = 'Fifty';
words[60] = 'Sixty';
words[70] = 'Seventy';
words[80] = 'Eighty';
words[90] = 'Ninety';
amount = amount.toString();
var atemp = amount.split(".");
var number = atemp[0].split(",").join("");
var n_length = number.length;
var words_string = "";
if (n_length <= 9) {
var n_array = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0);
var received_n_array = new Array();
for (var i = 0; i < n_length; i++) {
received_n_array[i] = number.substr(i, 1);
}
for (var i = 9 - n_length, j = 0; i < 9; i++, j++) {
n_array[i] = received_n_array[j];
}
for (var i = 0, j = 1; i < 9; i++, j++) {
if (i == 0 || i == 2 || i == 4 || i == 7) {
if (n_array[i] == 1) {
n_array[j] = 10 + parseInt(n_array[j]);
n_array[i] = 0;
}
}
}
value = "";
for (var i = 0; i < 9; i++) {
if (i == 0 || i == 2 || i == 4 || i == 7) {
value = n_array[i] * 10;
} else {
value = n_array[i];
}
if (value != 0) {
words_string += words[value] + " ";
}
if ((i == 1 && value != 0) || (i == 0 && value != 0 && n_array[i + 1] == 0)) {
words_string += "Crores ";
}
if ((i == 3 && value != 0) || (i == 2 && value != 0 && n_array[i + 1] == 0)) {
words_string += "Lakhs ";
}
if ((i == 5 && value != 0) || (i == 4 && value != 0 && n_array[i + 1] == 0)) {
words_string += "Thousand ";
}
if (i == 6 && value != 0 && (n_array[i + 1] != 0 && n_array[i + 2] != 0)) {
words_string += "Hundred and ";
} else if (i == 6 && value != 0) {
words_string += "Hundred ";
}
}
words_string = words_string.split(" ").join(" ");
}
return words_string;
}
初始值设定项中:
wrap_parameters.rb