Rails 4 嵌套路由返回父级的显示页面

Rails 4 Nested Routing Back to Parent's Show Page

在我的网络应用程序中,我创建了两个模块;客户和工人。我的问题是我无法创建从 workers#index 到 clients#show 的 'Back' link。换句话说,我想在 URL:

中创建它
http://localhost:3000/clients/1

我认为这与没有输入正确的 URL 助手有关。当我 运行 rake routes 我看到我想要的路径时,这让我相信我已经正确地嵌套了资源。但是我似乎无法输入正确的参数返回到 client#show 页面而不是 clients#index。

Prefix Verb   URI Pattern                                    Controller#Action
    client_workers GET    /clients/:client_id/workers(.:format)          workers#index
                   POST   /clients/:client_id/workers(.:format)          workers#create
 new_client_worker GET    /clients/:client_id/workers/new(.:format)      workers#new
edit_client_worker GET    /clients/:client_id/workers/:id/edit(.:format) workers#edit
     client_worker GET    /clients/:client_id/workers/:id(.:format)      workers#show
                   PATCH  /clients/:client_id/workers/:id(.:format)      workers#update
                   PUT    /clients/:client_id/workers/:id(.:format)      workers#update
                   DELETE /clients/:client_id/workers/:id(.:format)      workers#destroy
           clients GET    /clients(.:format)                             clients#index
                   POST   /clients(.:format)                             clients#create
        new_client GET    /clients/new(.:format)                         clients#new
       edit_client GET    /clients/:id/edit(.:format)                    clients#edit
            client GET    /clients/:id(.:format)                         clients#show
                   PATCH  /clients/:id(.:format)                         clients#update
                   PUT    /clients/:id(.:format)                         clients#update
                   DELETE /clients/:id(.:format)                         clients#destroy
              root GET    /                                              clients#index

在 app/views/workers/show.html.erb 我有 link 的: <%= link_to 'Back', client_path(@client) %>.

工人控制器

class WorkersController < ApplicationController
  before_action :set_worker, only: [:show, :edit, :update, :destroy]

  # GET /clients/:client_id/workers
  # GET /clients/:post_id/workers.xml
  def index
    #1st you retrieve the client thanks to params[:client_id]
    client = Client.find(params[:client_id])
    #2nd you get all the workers of this client
    @workers = client.workers

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @comments }
    end
  end

  # GET /clients/:client_id/workers/:id
  # GET /workers/:id.xml
  def show
    #1st you retrieve the client thanks to params[:client_id]
    @client = Client.find(params[:client_id])
    #2nd you retrieve the comment thanks to params[:id]
    @worker = client.workers.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @comment }
    end
  end

  # GET /clients/:client_id/workers/new
  # GET /clients/:client_id/workers/new.xml
  def new
    #1st you retrieve the post thanks to params[:post_id]
    client = Client.find(params[:client_id])
    #2nd you build a new one
    @worker = client.workers.build

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @comment }
    end
  end

  # GET /posts/:post_id/comments/:id/edit
  # GET /clients/:client_id/workers/:id/edit
  def edit
    #1st you retrieve the post thanks to params[:post_id])
    client = Client.find(params[:client_id])
    #2nd you retrieve the comment thanks to params[:id]
    @worker = client.workers.find(params[:id])
  end

  # POST /client/:client_id/workers
  # POST /client/:client_id/worker.xml
  def create
    #1st you retrieve the post thanks to params[:post_id]
    client = Client.find(params[:client_id])
    #2nd you create the comment with arguments in params[:comment]
    @worker = client.workers.create(worker_params)

    respond_to do |format|
      if @worker.save
        #1st argument of redirect_to is an array, in order to build the correct route to the nested resource comment
        format.html { redirect_to([@worker.client, @worker], :notice => 'Worker was successfully created.') }
        #the key :location is associated to an array in order to build the correct route to the nested resource comment
        format.xml  { render :xml => @worker, :status => :created, :location => [@worker.client, @worker] }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @worker.errors, :status => :unprocessable_entity }
      end
    end
  end

  # PUT /client/:client_id/Workers/:id
  # PUT /client/:client_id/workers/:id.xml
  def update
    #1st you retrieve the post thanks to params[:post_id]
    client = Client.find(params[:client_id])
    #2nd you retrieve the comment thanks to params[:id]
    @worker = client.workers.find(params[:id])

    respond_to do |format|
      if @worker.update_attributes(worker_params)
        #1st argument of redirect_to is an array, in order to build the correct route to the nested resource comment
        format.html { redirect_to([@worker.client, @worker], :notice => 'Worker was successfully updated.') }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @worker.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /client/:client_id/workers/1
  # DELETE /client/:client_id/worker/1.xml
  def destroy
    #1st you retrieve the post thanks to params[:post_id]
    client = Client.find(params[:client_id])
    #2nd you retrieve the comment thanks to params[:id]
    @worker = client.workers.find(params[:id])
    @worker.destroy

    respond_to do |format|
      #1st argument reference the path /posts/:post_id/comments/
      format.html { redirect_to(client_workers_url) }
      format.xml  { head :ok }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_worker
      @worker = Worker.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def worker_params
      params.require(:worker).permit(:first_name, :last_name, :birth_day, :birth_month, :birth_year, :birth_city, :birth_state, :client_id)
    end
end

您想要的 url 需要 /clients/ 之后的 :id。您的路由表示 /clients/:id 的路径为 client_path 而不是 clients_path。 (client GET /clients/:id(.:format)clients#show )。 所以,如果你在 workers#index 页面中有那个 id,你可以把它写成

<%= link_to 'Back', client_path(@client) %>。交叉检查语法并尝试。

感谢评论中的每一个人,我们才得以找到答案。我决定将答案组合在一起,这样遇到此问题的其他人就可以更轻松地找到这个 post.

正确的link是:<%= link_to 'Back', client_path(@client) %>

为此,我必须将 WorkersController #show 和 #index 方法更改为以下内容:

class WorkersController < ApplicationController
def index
  #1st you retrieve the client thanks to params[:client_id]
  @client = Client.find(params[:client_id])
  #2nd you get all the workers of this client
  @workers = @client.workers

  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml => @comments }
  end
end

# GET /clients/:client_id/workers/:id
# GET /workers/:id.xml
def show
  #1st you retrieve the client thanks to params[:client_id]
  @client = Client.find(params[:client_id])
  #2nd you retrieve the comment thanks to params[:id]
  @worker = client.workers.find(params[:id])

  respond_to do |format|
    format.html # show.html.erb
    format.xml  { render :xml => @comment }
  end
end

本质上,将局部变量 client 更改为实例变量 @client 以便可以访问。