Я пытаюсь сделать ajax-обновление полиморфной модели и получить ошибку:
undefined method 'images' for #<Image:0x007fc6517ea378>
app/controllers/images_controller.rb, line 22
(Он жалуется на @imageable.images
этой строки @image = @imageable.images.find(params[:id])
)
Эта модель/контроллер отлично функционирует, когда CRUDing экземпляры ее из других моделей, но, похоже, получает эту ошибку при попытке обновить ее напрямую.
Почему работает при использовании во вложенной форме, но не при обращении напрямую?
image.rb
class Image < ActiveRecord::Base
default_scope order('images.id ASC')
attr_accessible :asset,
:asset_cache,
:active
belongs_to :imageable, polymorphic: true
mount_uploader :asset, ImageUploader
def self.default
return ImageUploader.new
end
end
images_controller.rb
class ImagesController < ApplicationController
before_filter :load_imageable
load_and_authorize_resource
def new
@image = @imageable.images.new
end
def create
@image = @imageable.images.new(params[:image])
respond_to do |format|
if @image.save
format.html { redirect_to @imageable, notice: "Image created." }
else
format.html { render :new }
end
end
end
def update
@image = @imageable.images.find(params[:id])
respond_to do |format|
if @image.update_attributes(params[:image])
format.html { redirect_to @imageable, notice: 'Image was successfully updated.' }
else
format.html { render :edit }
end
end
end
def destroy
@image = @imageable.images.find(params[:id])
@image.destroy
end
private
def load_imageable
resource, id = request.path.split('/')[1, 2]
@imageable = resource.singularize.classify.constantize.find(id)
end
end
ajax call
$(document).on("click", ".toggle-image-active", function(event) {
var id = $(this).attr("data-id");
var currently_active = $(this).attr("data-active");
var active = true;
if (currently_active == "true") {
active = false;
}
$.ajax({
type: "PUT",
dataType: "script",
url: '/images/' + id,
contentType: 'application/json',
data: JSON.stringify({ resource:{active:active}, _method:'put' })
}).done(function(msg) {
console.log( "Data Saved: " + msg );
});
});
То, что я не понимал, и причина, по которой это не работает, заключается в том, что @imageable
на самом деле является моделью, к которой принадлежит модель image
, а не сама модель image
.
В качестве решения я определил действие пользовательского контроллера и сделал для него сообщение.
class ImagesController < ApplicationController
before_filter :load_imageable
skip_before_filter :load_imageable, :only => :set_active
load_and_authorize_resource
def set_active
Image.find(params[:id]).update_attributes(params[:image])
render :nothing => true, :status => 200, :content_type => 'text/html'
end
Хотя это работает, это может быть не лучшее решение, поэтому я открыт для предложений.
post '/images/set_active/:id' => 'images#set_active'