我现在已经阅读和研究了大约3天。 这是我的最后一招。
land.rb:
has_many :uploads , :dependent => :destroy
accepts_nested_attributes_for :uploads, :allow_destroy => true,:reject_if => :all_blank
upload.rb
belongs_to :land
_land_form_partial.html.erb
<%= form_for land , :html => {:multipart => true} do |f| %>
<%= f.fields_for :uploads do |builder| %>
<div class="land_fields">
<%= builder.label :filename, "Image" %>
<%= builder.text_field :filename %> <br/>
Delete: <%= builder.check_box :_destroy %>
</div>
<% end %>
#... buttons and other fields
<% end %>
lands_controller.rb
def update
if @land.update_attributes(land_params)
flash[:success] = "Land updated"
redirect_to lands_path
else
flash[:alert] = @land.errors.full_messages.first
redirect_to edit_land_path
end
end
def land_params
params.require(:land).permit( uploads_attributes: [ :id, :filename ] )
end
当我在文本字段中添加内容并更新它时,所有更新都正确。如果我单击复选框,它将不会删除该字段。
有人可以对此有所了解吗?
此外我尝试awesome_nested_fields除了删除实际记录外,一切正常。
提前谢谢。
编辑:解决方案:(我喜欢把解决方案放在问题中以防万一有人想在移动设备上查看它,因为我讨厌当我无法立即看到解决方案时)
感谢@nTraum
def land_params
params.require(:land).permit( uploads_attributes: [ :id, :filename, :_destroy ] )
end
一切都会花花公子:)
答案 0 :(得分:51)
您还需要允许嵌套模型的:_destroy
参数,因为当您选中表单中的“删除”复选框时会使用此参数。这是Rails标记必须销毁的模型实例的方式。
def land_params
params.require(:land).permit(uploads_attributes: [:id, :filename, :_destroy])
end
答案 1 :(得分:12)
OP没有和我一样的问题,但对于遇到这个问题的任何人来说,对我来说,allow_destroy: true
调用accepts_nested_attributes
时没有/* Head Master Info >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
/* Top Level Google Drive Folder ID */
var TopDriveFolderID = "0B2rN5b8fW77ldXZXOXFLZGlSamc";
var BaseNumberOfFilesInFolder = 4;
var NewSSAnalyzerSheetId = "1VyL8XL1x41H6yetcrwfUhVcch-DUsngY4-bHCbo-_xM";
/* End Head Master Info >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/* Body >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/* Functions to iterate through all sub folders */
function listFolders() {
var parentFolder = DriveApp.getFolderById(TopDriveFolderID);
var childFolders = parentFolder.getFolders();
while(childFolders.hasNext()) {
var child = childFolders.next();
// Logger.log(child.getName() + " |Drive_ID: " + child.getId());
var folderId = child.getId();
// **the folderId Variable is also the folder ID,
// hence they are used interchangeably **
/* SpreadSheet Combiner >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/* Name of combined Spreadsheet*/
var newSpreadSheetName = DriveApp.getFolderById(folderId).getName();
/* Retrieve the desired folder */
var myFolder = DriveApp.getFolderById(folderId);
/* Get all spreadsheets that resided on that folder */
var spreadSheets = myFolder.getFilesByType("application/vnd.google-apps.spreadsheet");
var spreadSheetName = myFolder.getName();
// Logger.log(spreadSheetName);
/* Check if a file needs to be created or if one already exists*/
var theFolder = DriveApp.getFolderById(folderId);
var files = theFolder.getFiles();
var fname = theFolder.getName();
var cnt = 0;
var file;
/* Check the quantity of files in a folder to see if you need to combine the sheets and create a file*/
while (files.hasNext()) {
cnt++;
file = files.next();
//Logger.log(file.getName());
if (cnt > BaseNumberOfFilesInFolder) {
Logger.log("File already exists")
break;
}
;
};
// If a file needs to be created this checks it and creates it
Logger.log(cnt + " is the number of files '"+ newSpreadSheetName+ "' has.");
if (cnt > BaseNumberOfFilesInFolder){
Logger.log("No file needs to be created")
}else{
/* Create the new spreadsheet that you store other sheets */
var newSpreadSheet = SpreadsheetApp.create(newSpreadSheetName);
/* Iterate over the spreadsheets over the folder */
while(spreadSheets.hasNext()) {
var sheet = spreadSheets.next();
/* Open the spreadsheet */
var spreadSheet = SpreadsheetApp.openById(sheet.getId());
/* Get all its sheets */
for(var y in spreadSheet.getSheets()) {
/* Copy the sheet to the new merged Spread Sheet */
spreadSheet.getSheets()[y].copyTo(newSpreadSheet);
/* In order to move the file to the folder we want and because
google considers the SpreadSheet a Google Spreadsheet
instead of a file, we have to convert the SpreadSheet to a file in
order to move it.Thats what the next 2 lines of code do.*/
var getNewSSid = newSpreadSheet.getId();
var SStoGFile = DriveApp.getFileById(getNewSSid);
/* Actually moving the file*/
DriveApp.getFolderById(folderId).addFile(SStoGFile);
/* Deleting the duplicate file that was created in the process*/
var rootFolder = DriveApp.getRootFolder();
DriveApp.getRootFolder().removeFile(SStoGFile);
}
}
/*Code to add our base analysis template to the new combined template that was created;*/
//Grabs the template
var sss = SpreadsheetApp.openById(NewSSAnalyzerSheetId); //replace with source ID
var ss = sss.getSheetByName('Analysis Tab'); //replace with source Sheet tab name
var range = ss.getRange('A1:E6'); //assign the range you want to copy
var data = range.getValues();
//Copies the template info into the current newly created sheet
var tssId = newSpreadSheet.getId();
var tss = SpreadsheetApp.openById(tssId); //replace with destination ID
var ts = tss.getSheetByName('Sheet1'); //replace with destination Sheet tab name
ts.getRange(1,1,6,5).setValues(data); //you will need to define the size of the copied data see getRange()
Logger.log("New File was created with the name - " + newSpreadSheetName)
}
};
/* End SpreadSheet Combiner >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
getSubFolders(child);
}
/* Necessary Function to help the above loop through the sub folders */
function getSubFolders(parent) {
parent = parent.getId();
var childFolder = DriveApp.getFolderById(parent).getFolders();
while(childFolder.hasNext()) {
var child = childFolder.next();
Logger.log(child.getName());
getSubFolders(child);
}
return;
}
/* End iterate through Sub Folders */
。模特。