Rails: how to redirect the "show" action of a nested resource to the "create" action?

Hi. I currently have 3 models: user, album, photo. I have done the registration, but not the login / sessions yet, since I am trying to create an album / photo first. However, when I create an album, the URL changes from

http://localhost:3000/users/13/albums/new (no problem)

to

http://localhost:3000/albums/76/photos/76 (problem)

problems here: 1. user_id disappears from the url. 2. He sends me the wrong address. As you can see below, I am redirecting to [@user, @album]. Shouldn't this be a demo of the album controller? I wanted something like / users / 13 / albums / 1 as the url. Instead, it sends me to photos#show . 3. Although this is not a valid link, why is the album id and photo id always the same? 76/76 77/77 etc. I do not know where this comes from.

here are my files:

album controller

 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 

albums / 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 %> 

Config / Routes

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

let me know if you need more files.

+4
source share
2 answers

Here is a series of queries that your use case goes through:

First, the form passes some data to your Album#create action.

After the Album#create request completes successfully, the request is redirected to the Albums#show action.

In the Albums#show action, the controller creates instances of @user and @album with your current user and new album, and then creates a new Photo object in the Album photos collection.

Then the action saves the Album record again. Since nothing has changed, it actually does nothing. But it does not do anything successfully, so it redirects the request to album_photo_path , and this is what happens in a pear-shaped form . This route, as defined, results in a Photo#show action in the context of the parent photo album. The route expects two arguments: an album and a photo. As called in the code, it should not handle the routing error exception. (Believe me, I tried.)

Instead of hanging on minutae like this, though, I'm going to make a blind recommendation instead!

It looks like you did not intend to perform your Album#show action to save the album and redirect to Photo#show via the wrong route. I think this is the source of all three of your problems. And ultimately, I think your AlbumsController show action should look like this:

 def show @user = User.find(params[:user_id]) @album = @user.albums.find(params[:id]) end 

Hope this helps!


Edited to post Edmund's comment:

Absolutely, you can configure the Album#show action so that users can add photos. This will be due to the two changes that I propose above.

In your controller, you will create a new photo in the @album Photos collection, as before:

 def show @user = User.find(params[:user_id]) @album = @user.albums.find(params[:id]) @photo = @album.photos.build end 

Then in the Album#show template (for example, app/views/albums/show.html.erb ) you must enable the form to submit a new photo:

 <%= form_for [@user, @album, @photo] do |f| %> <%= f.text_field :caption %> <%= f.file_field :image %> <%- end %> 

This form should present its contents in user_album_photos_path , which, as you can see, does not exist yet. So the final change will be to embed Photos as a resource in routes.rb :

 resources :users do resources :albums do resources :photos end end 

This will provide you with the route necessary to use the form. Now you just need to add the Photo#create action to process the form submission, and you will go racing!

+4
source

I believe that your action should look like this:

 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 
-1
source

Source: https://habr.com/ru/post/1437461/


All Articles