#ruby-on-rails #activerecord #ruby-on-rails-4 #actioncontroller
#ruby-on-rails #activerecord #ruby-on-rails-4 #actioncontroller
Вопрос:
У меня возникли проблемы с доступом к настройке модели изображения, например:
Запрос has_one
has_many
изображений галереи
Из представления show модели запроса мне нужно получить доступ к изображениям ее галереи, и это выдает мне ошибку undefined method 'pictures' for nil:NilClass
.
Модели:
class Request < ActiveRecord::Base
belongs_to :user
has_one :gallery
has_many :pictures, through: :gallery
end
class Gallery < ActiveRecord::Base
has_many :pictures, :dependent => :destroy
belongs_to :request
end
class Picture < ActiveRecord::Base
belongs_to :gallery
has_attached_file :image,
:path => ":rails_root/public/images/:id/:filename",
:url => "/images/:id/:filename"
do_not_validate_attachment_file_type :image
end
Запрашивает контроллер:
class RequestsController < ApplicationController
before_action :set_request, only: [:show, :edit, :update, :destroy]
def show
@request = Request.find(params[:id])
@gallery = @request.gallery
@pictures = @gallery.pictures
end
def new
@request = Request.new
@gallery = Gallery.new(params[:request_id])
@gallery = @request.gallery
@pictures = @gallery.pictures
end
def create
@request = Request.new(request_params)
respond_to do |format|
if @request.save
format.html { redirect_to @request, notice: 'Request was successfully created.' }
format.json { render :show, status: :created, location: @request }
else
format.html { render :new }
format.json { render json: @request.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_request
@request = Request.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def request_params
params.require(:request).permit(:title, :description, :username, gallery_attributes: [:id, :name, :description]).merge(user_id: current_user.id)
end
end
Контроллер галерей:
class GalleriesController < ApplicationController
def show
@gallery = Gallery.find(params[:id])
@pictures = @gallery.pictures
respond_to do |format|
format.html # show.html.erb
format.json { render json: @gallery }
end
end
def new
@gallery = Gallery.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @gallery }
end
end
def create
@gallery = Gallery.new(gallery_params)
respond_to do |format|
if @gallery.save
if params[:images]
params[:images].each { |image|
@gallery.pictures.create(image: image)
}
end
format.html { redirect_to @gallery, notice: 'Gallery was successfully created.' }
format.json { render json: @gallery, status: :created, location: @gallery }
else
format.html { render action: "new" }
format.json { render json: @gallery.errors, status: :unprocessable_entity }
end
end
end
def gallery_params
params.require(:gallery).permit(:name, :description, :cover, :token)
end
end
Контроллер изображений:
class PicturesController < ApplicationController
def show
@picture = Picture.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @picture }
end
end
def new
@gallery = Gallery.find(params[:gallery_id])
@picture = @gallery.pictures.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: @picture }
end
end
def create
@picture = Picture.new(params[:picture])
if @picture.save
respond_to do |format|
format.html {
render :json => [@picture.to_jq_upload].to_json,
:content_type => 'text/html',
:layout => false
}
format.json {
render :json => [@picture.to_jq_upload].to_json
}
end
else
render :json => [{:error => "custom_failure"}], :status => 304
end
end
Запрос показать вид: (сокращенный)
<%- model_class = Request -%>
<% unless @pictures.empty? %>
<% @pictures.each do |pic| %>
<li class="span3" id="picture_<%= pic.id %>">
<div class="thumbnail">
<%= image_tag pic.image.url %>
<div class="caption">
</div>
</div>
</li>
<% end %>
<% end %>
В представлении запроса я пытаюсь получить доступ к @pictures, который должен предоставить мне все изображения из галереи запроса. Я ненавижу публиковать так много кода, но я новичок в этом и не хочу ничего упускать. Есть идеи?
Комментарии:
1. Причина, по которой вы получаете эту ошибку, заключается в том, что
@request.gallery
возвращает null, что означает, что вашrequest
неgallery
связан с ним.2. Вы знаете, что я могу сделать, чтобы это исправить? Я думал, что мой контроллер запросов создавал его, когда я создавал запрос.
Ответ №1:
В этой части есть серьезные проблемы:
def show
@request = Request.find(params[:id])
@gallery = @request.gallery
@pictures = @gallery.pictures
end
def new
@request = Request.new
@gallery = Gallery.new(params[:request_id])
@gallery = @request.gallery
@pictures = @gallery.pictures
end
В show
вам нужно проверить, есть ли в запросе галерея или нет (если вы не добавляете проверку для ассоциации, вы можете сделать это следующим образом: validates_presence_of :gallery
в Request
модели). Другой способ — добавить нулевую проверку:
def show
@request = Request.find(params[:id])
unless @request.gallery.nil?
@gallery = @request.gallery
@pictures = @gallery.pictures
end
end
Но если вы ожидаете, что это модели, добавьте ассоциацию:
class Request < ActiveRecord::Base
belongs_to :user
has_one :gallery
validates_presence_of :gallery
has_many :pictures, through: :gallery
end
Также в новом действии просто создайте @request
, с ним не связана галерея. Также вы определяете @gallery
2 раза, я не знаю причины. Вы могли бы ее построить:
def new
@request = Request.new
@gallery = @request.build_gallery
@pictures = @gallery.pictures
end
Я также не могу понять, что это params[:request_id]
такое. Если это новое для запроса, какой идентификатор у вас уже есть?
Обновлено
Как я вижу, теперь вам нужно просто изменить new
действие.
def new
@request = Request.new
end
Комментарии:
1. Спасибо за помощь. Я понимаю, что мой код в беспорядке, я просто экспериментировал, потому что не мог понять проблему. Что я должен был прояснить, так это то, что мне нужно, чтобы галерея создавалась при создании запроса, чтобы я мог использовать оба в одной форме. Вы знаете, как я мог бы это сделать?
2. Да,
@request.build_gallery
сделайте именно это, но вам нужно отправить ему некоторые параметры, и вы должны сделать это вcreate
действии. Там будет только@request = Request.new request_params
то, гдеrequest_params
будут включены параметры галереи и автоматически назначены.3. Еще раз спасибо, зише, наконец-то это работает. Ты меня хорошо научил. Счастливого пути.