ajax не отвечает - create.js.erb
Я работаю с гемом jquery-file-upload-rails для загрузки нескольких изображений с предварительным просмотром в моей форме. Загрузка файла работает, но часть с новыми фотографиями отображается только после обновления браузера! Может быть, кто-то может увидеть, что не так.
Я вызываю загрузчик файлов для загрузки фотоизображений на странице редактирования проекта:
= f.fields_for :photos, Photo.new do |ff|
= ff.file_field :img_file, multiple: true, name: "project[photos_attributes][][img_file]", id: 'new_photo'
Фотоконтроллер:
def create
@project = Project.find(params[:project_id])
@photo = @project.photos.create(params[:photo].permit(:img_file))
respond_to do |format|
format.js
format.html
end
end
photos.js.coffee, чтобы заставить работать камень jquery-file-uploader-rails:
jQuery ->
$('#new_photo').fileupload
dataType: 'script'
create.js.erb
$('#photos').html("<%= j render(@photo) %>");
_photo.html.haml
.photo
- @project.photos.each do |photo|
= image_tag photo.img_file.thumb
= link_to 'Remove', photo, data: { confirm: "Are you sure?" }, method: :delete
Так что я могу загружать фотографии. Но мой аякс не работает, даже если я ставлю только предупреждение ("помощь"); в моем create.js.erb он не отвечает. Что я делаю неправильно? Спасибо заранее!
ОБНОВЛЕНИЕТекущая ситуация (с помощью Rich Peck):
Мои модели:
class Project < ActiveRecord::Base
has_many :photos, dependent: :destroy
accepts_nested_attributes_for :photos, allow_destroy: true
end
class Photo < ActiveRecord::Base
belongs_to :project
validates :img_file, presence: true
mount_uploader :img_file, ImageUploader
end
Контролер проектов:
def edit
@project = Project.find(params[:id])
@project.photos.build
end
def update
@project = Project.find(params[:id])
@project.update(project_params)
end
params.require(:project).permit(photos_attributes: [:img_file])
/ Проекты / редактировать
= form_for @project do |f|
= f.fields_for :photos do |p|
= p.file_field :img_file, multiple: true, id: 'new_photo'
#photos
= render 'photos/photo'
/ Фото / _photo
.photo
= image_tag photo.img_file.thumb if photo.img_file?
= link_to 'Remove', photo, data: { confirm: "Are you sure?" }, method: :delete
/photos/create.js.erb
$('#photos').html("<%= j render(@photo) %>");
/javascripts/photos.js.coffee
jQuery ->
$('#new_photo').fileupload
dataType: 'script'
3 ответа
Для загрузки файла AJAX для работы в jquery-file-upload
драгоценный камень
ты должен добавить :html => { :multipart => true}
к вашей форме
<%= form_for Upload.new, :html => { :multipart => true} } do |f| %>
...
<%end%>
Пожалуйста, ознакомьтесь с примером формы jQuery-File-Upload
Несколько вопросов.
#app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
respond_to :js, :html
def new
@project = Project.new
@project.photos.build #-> this will replace Photo.new in fields_for
end
def create
@project = Project.new project_params
@project.save
respond_with @project
end
private
def project_params
params.require(:project).permit(photos_attributes: [:img_file])
end
end
#app/views/projects/new.haml
= form_for @project do |f|
= f.fields_for :photos do |ff|
= ff.file_field :img_file, multiple: true, id: 'new_photo'
При использовании вложенных атрибутов вы никогда не должны объявлять name
атрибут ваших вложенных полей. Мало того, что это против соглашения, но это также оставляет дверь открытой для взлома и ошибок.
Если вы используете nested attributes
нужно пройти мимо @project
сначала объект, что означает, что форма будет либо передавать projects#update
или же projects#create
... не photos#create
что у тебя сейчас.
Я также настоятельно рекомендую использовать responders
драгоценный камень, он очистит ваш код в массовом порядке.
-
Если вы хотите создать новый Photo
объект самостоятельно, вы хотите использовать следующее:
#config/routes.rb
resources :projects do
resources :photos #-> url.com/projects/:project_id/photos/new
end
#app/controllers/photos_controller.rb
class PhotosController < ApplicationController
respond_to :js, :html
def new
@project = Project.find params[:project_id]
@photo = @project.photos.new
end
def create
@project = Project.find params[:project_id]
@photo = @project.photos.new photo_params
@photo.save
respond_with @photo
end
private
def photo_params
params.require(:photo).permit(:img_file)
end
end
#app/views/photos/new.haml
= form_for @photo do |f|
= f.file_field :img_field
Ваш код JS неверен...
$('#photos').html("<%= j render(@photo) %>");
По умолчанию Rails обрабатывает "коллекции", вызывая _[collection_singular_name].html.erb
- в твоем случае _photo.html.erb
, Он просматривает коллекцию, чтобы показать это каждый раз. Чтобы исправить это, просто удалите петлю из вашего частичного:
#app/views/photos/_photo.html.erb
= image_tag photo.img_file.thumb
= link_to 'Remove', photo, data: { confirm: "Are you sure?" }, method: :delete
Решение
Решите, создаете ли вы project
или же photo
,
Если вы создаете photo
, вы должны использовать отдельный photos
контроллер (обрисован в общих чертах выше). Если вы создаете новый проект, вы должны использовать nested attributes
должным образом. Мы использовали JQuery-File-Upload
Несколько раз до этого (вы можете бесплатно зарегистрироваться только в тестовом приложении):
Ваша структура кода выглядит хорошо, только контроллер и JS, которые имеют проблемы.
Обновить
Чтобы добавить новое фото через проект edit
Форма, просто используйте следующее:
#app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
def edit
@project = Project.find params[:id]
@project.photos.build
end
def update
@project = Project.find params[:id]
@project.update project_params
end
private
def project_params
params.require(:project).permit(photos_attributes: [:img_file])
end
end
#app/views/projects/edit.html.erb
<%= form_for @project do |f| %>
<%= f.fields_for :photos do |p| %>
<%= p.file_field :img_file %>
<% end %>
<%= f.submit %>
<% end %>
Использование
$('#photos').html(escape_javascript("<%= j render(@photo) %>"));
см. http://api.rubyonrails.org/classes/ActionView/Helpers/JavaScriptHelper.html