Rails:如何在“创建”操作中重定向到“显示”嵌套资源的“动作”?

时间:2012-10-02 20:12:58

标签: ruby-on-rails

您好我目前有3个型号:用户,相册,照片。我已经注册了,但还没有登录/会话,因为我试图让专辑/照片创作先完成。但是,当我创建相册时,URL会从

更改

http://localhost:3000/users/13/albums/new(没问题)

http://localhost:3000/albums/76/photos/76(问题)

这里的问题是: 1. user_id从网址中消失。 它把我送到了错误的网址。如下所示,我将重定向到[@user,@ album]。这不应该是专辑控制器的节目动作吗?我想要像/ users / 13 / albums / 1这样的网址。相反,它将我发送到photos#show。 3.即使这是错误的链接,为什么专辑ID和照片ID总是一样的? 76/76 77/77等......我不知道它来自哪里......

这是我的档案:

专辑控制器

def show
  @user = User.find(params[:user_id])
  @album = @user.albums.find(params[:id])
  @photo = @album.photos.build(params[:photo])
  respond_to do |format|
    if @album.save
      format.html { redirect_to album_photo_path(@album), notice: 'Album was successfully created.' }
      format.json { render json: @album, status: :created, location: @album}
    else
      format.html { render action: "new" }
      format.json { render json: @album.errors, status: :unprocessable_entity }
    end
  end
end

def update
end

def edit
end

def create
  @user = User.find(params[:user_id])
  @album = @user.albums.build(params[:album])
  respond_to do |format|
    if @user.save
      format.html { redirect_to [@user, @album], notice: 'Album was successfully created.' }
      format.json { render json: @album, status: :created, location: @album}
    else
      format.html { render action: "new" }
      format.json { render json: @album.errors, status: :unprocessable_entity }
    end
  end 
end

相册/ new.html.erb

<%= form_for (@album), url: user_albums_path, :html => { :id => "uploadform", :multipart => true } do |f| %>



<div>
    <%= f.label :name %>
    <%= f.text_field :name %>


    <%= f.label :description %>
    <%= f.text_area :description %>

    <br>

    <%=f.submit %>
</div>
<% end %>

配置/路由

Pholder::Application.routes.draw do
resources :users do
  resources :albums 
end

resources :albums do
  resources :photos
end

如果您需要更多文件,请告诉我。

2 个答案:

答案 0 :(得分:5)

以下是您的用例运行的一系列请求:

首先,表单会向您的Album#create操作提交一些数据。

Album#create请求成功后,请求会重定向到Albums#show操作。

Albums#show操作中,控制器使用您当前的用户和新相册实例化@user@album,然后在相册的photos集合中构建新的Photo对象

操作然后再次保存Album记录。由于没有任何改变,这实际上没有做任何事情。但它没有做任何事情成功,因此它继续将请求重定向到album_photo_path,而这就是事情变成梨状的。根据定义,此路线会在照片的父级相册的上下文中导致Photo#show操作。该路线需要两个参数,一个专辑和一张照片。正如在您的代码中调用的那样,它不应该 - 而是抛出路由错误异常。 (相信我,我试过了。)

但是,不要像这样挂在minutae上,而是打算盲目推荐!

听起来您并不打算将Album#show操作保存到相册并通过格式错误的路线重定向到Photo#show。我认为这是你所有三个问题的根源。最后,我认为您AlbumsController的{​​{1}}行动需要看起来像这样:

show

希望这有帮助!


编辑解决Edmund的评论:

当然,您可以设置def show @user = User.find(params[:user_id]) @album = @user.albums.find(params[:id]) end 操作以允许用户添加照片。这将涉及对我上面建议的两处更改。

在你的控制器中,你将在Album#show的照片集上实例化一张新照片,就像你之前一样:

@album

然后,在def show @user = User.find(params[:user_id]) @album = @user.albums.find(params[:id]) @photo = @album.photos.build end 模板(例如Album#show)中,您需要提供一张用于提交新照片的表单:

app/views/albums/show.html.erb

此表单会将其内容提交给<%= form_for [@user, @album, @photo] do |f| %> <%= f.text_field :caption %> <%= f.file_field :image %> <%- end %> ,您可能会注意到它尚不存在。所以最后的改变是将照片作为资源嵌套在user_album_photos_path

routes.rb

这将为您提供使用表单所需的路线。现在,您只需要添加一个resources :users do resources :albums do resources :photos end end 操作来处理表单提交,就可以参加比赛了!

答案 1 :(得分:0)

我相信您的创建操作应如下所示:

def create
  @user = User.find(params[:user_id])
  @album = @user.albums.build(params[:album])
  respond_to do |format|
    if @user.save
      format.html { redirect_to user_album_path(@album), notice: 'Album was successfully created.' }
      format.json { render json: @album, status: :created, location: @album}
    else
      format.html { render action: "new" }
      format.json { render json: @album.errors, status: :unprocessable_entity }
    end
  end 
end