Загрузка файлов в Ruby on Rails с помощью формы с удаленным доступом: true
Я пытаюсь загрузить файлы, используя форму Rails, где для пульта установлено значение true. Я использую Rails 4.1.1. Допустим, моя модель - это Сообщение, и он использует JavaScript, чтобы пользователь мог легко отправлять несколько сообщений без перезагрузки страницы. Форма устанавливается так:
<%= form_for @message, url: {action: "create"}, html: {:class => "message-form", multipart: true}, remote: true do |f| %>
Пользователь может загрузить изображения с сообщением, если они хотят это сделать. MessageImage действует как вложенный атрибут в форме и объявляется следующим образом ( http://railscasts.com/episodes/196-nested-model-form-revised way):
<%= f.fields_for :message_images do |builder| %>
<%= render 'message_image_fields', f: builder %>
<%= link_to_add_fields "Add an image", f, :message_images %>
<% end %>
На моем контроллере действие примерно так:
if @message.save
flash.now[:success] = "Message sent"
else
flash.now[:alert] = "Error sending the message"
end
respond_to do |format|
format.html { render 'new' }
format.js { render 'new' }
end
Теперь это работает отлично, пока пользователь не отправляет изображения, но если они это делают, он использует format.html вместо format.js. Удаление format.html дает ActionController::UnknownFormat-исключение.
Теперь это очевидно связано с тем, что вы не можете отправлять файлы с удаленным значением true. Я попытался немного поискать и нашел этот драгоценный камень https://github.com/JangoSteve/remotipart, который, кажется, именно то, что я ищу. Я установил его, следуя инструкциям, но по какой-то причине он все еще не работает и выдает ActionController::UnknownFormat-исключение, если я удаляю format.html. Однако я не смог найти ни одного примера с вложенными атрибутами. Есть ли какие-либо альтернативы для этого драгоценного камня или любой другой способ исправить это, или я должен просто установить, что он отображает HTML, если пользователь отправляет файлы?
1 ответ
JQuery
Я не знаю, как получить вложенный модельный аспект этого, но мы уже делали загрузку файлов с помощью JQuery / asynchronicity до этого (зарегистрируйтесь, войдите в профиль):
Мы использовали jquery-file-upload
gem - в основном позволяет передавать файлы через Ajax на серверную часть вашего контроллера. Чтобы дать вам четкое представление о том, как мы это сделали:
-
Код
#app/assets/javascripts/application.js
$('#avatar').fileupload({
url: '/profile/' + $(this).attr('data_id'),
dataType: 'json',
type: 'post',
add: function (e, data) {
$(this).avatar_loading('avatar_loading');
data.submit();
},
success: function (data, status) {;
$("#avatar_img").fadeOut('fast', function() {
$(this).attr("src", data.avatar_url).fadeIn('fast', function(){
$(this).avatar_loading('avatar_loading');
});
});
}
});
#app/views/users/index.html.erb
<%= form_for :upload, :html => {:multipart => true, :id => "avatar"}, :method => :put, url: profile_path(current_user.id), "data_id" => current_user.id do |f| %>
<div class="btn btn-success fileinput-button avatar" id="avatar_container">
<%= f.file_field :avatar, :title => "Upload New" %>
<%= image_tag(@user.profile.avatar.url, :width=> '100%', :id => "avatar_img", :alt => name?(@user)) %>
</div>
<% end %>
#app/controllers/profile_controller.rb
Class ProfileController < ApplicationController
def update
def update
@profile = User.find(current_user.id)
@profile.profile.update(upload_params)
respond_to do |format|
format.html { render :nothing => true }
format.js { render :partial => 'profiles/update.js' }
format.json {
render :json => @profile.profile.as_json(:only => [:id, :avatar], :methods => [:avatar_url])
}
end
def upload_params
params.require(:upload).permit(:avatar, :public, :description)
end
end
end
-
Реализация
Для вашей реализации я бы рекомендовал сначала создать сообщение, а затем заставить пользователя добавить к нему несколько изображений в другом действии.
После того, как у вас это получится, вы можете заставить его работать как одна форма