首页 文章

Rails 4嵌套浅路由:如何在子控制器中获取父ID?

提问于
浏览
4

在我的Rails 4应用程序中,有四种模型:

class User < ActiveRecord::Base
  has_many :administrations
  has_many :calendars, through: :administrations
end

class Calendar < ActiveRecord::Base
  has_many :administrations
  has_many :users, through: :administrations
  has_many: :posts
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Post < ActiveRecord::Base
  belongs_to :calendar
end

有了这个路由:

Rails.application.routes.draw do

  root to: 'pages#home'

  devise_for :users, :path => 'account'

  resources :calendars do
    resources :posts, shallow: true
  end

end

这给出了这些路线:

Prefix Verb   URI Pattern                                 Controller#Action
                   posts GET    /posts(.:format)                            posts#index
                         POST   /posts(.:format)                            posts#create
                new_post GET    /posts/new(.:format)                        posts#new
               edit_post GET    /posts/:id/edit(.:format)                   posts#edit
                    post GET    /posts/:id(.:format)                        posts#show
                         PATCH  /posts/:id(.:format)                        posts#update
                         PUT    /posts/:id(.:format)                        posts#update
                         DELETE /posts/:id(.:format)                        posts#destroy
                    root GET    /                                           pages#home
        new_user_session GET    /account/sign_in(.:format)                  devise/sessions#new
            user_session POST   /account/sign_in(.:format)                  devise/sessions#create
    destroy_user_session DELETE /account/sign_out(.:format)                 devise/sessions#destroy
           user_password POST   /account/password(.:format)                 devise/passwords#create
       new_user_password GET    /account/password/new(.:format)             devise/passwords#new
      edit_user_password GET    /account/password/edit(.:format)            devise/passwords#edit
                         PATCH  /account/password(.:format)                 devise/passwords#update
                         PUT    /account/password(.:format)                 devise/passwords#update
cancel_user_registration GET    /account/cancel(.:format)                   devise/registrations#cancel
       user_registration POST   /account(.:format)                          devise/registrations#create
   new_user_registration GET    /account/sign_up(.:format)                  devise/registrations#new
  edit_user_registration GET    /account/edit(.:format)                     devise/registrations#edit
                         PATCH  /account(.:format)                          devise/registrations#update
                         PUT    /account(.:format)                          devise/registrations#update
                         DELETE /account(.:format)                          devise/registrations#destroy
       user_confirmation POST   /account/confirmation(.:format)             devise/confirmations#create
   new_user_confirmation GET    /account/confirmation/new(.:format)         devise/confirmations#new
                         GET    /account/confirmation(.:format)             devise/confirmations#show
             user_unlock POST   /account/unlock(.:format)                   devise/unlocks#create
         new_user_unlock GET    /account/unlock/new(.:format)               devise/unlocks#new
                         GET    /account/unlock(.:format)                   devise/unlocks#show
          calendar_posts GET    /calendars/:calendar_id/posts(.:format)     posts#index
                         POST   /calendars/:calendar_id/posts(.:format)     posts#create
       new_calendar_post GET    /calendars/:calendar_id/posts/new(.:format) posts#new
                         GET    /posts/:id/edit(.:format)                   posts#edit
                         GET    /posts/:id(.:format)                        posts#show
                         PATCH  /posts/:id(.:format)                        posts#update
                         PUT    /posts/:id(.:format)                        posts#update
                         DELETE /posts/:id(.:format)                        posts#destroy
               calendars GET    /calendars(.:format)                        calendars#index
                         POST   /calendars(.:format)                        calendars#create
            new_calendar GET    /calendars/new(.:format)                    calendars#new
           edit_calendar GET    /calendars/:id/edit(.:format)               calendars#edit
                calendar GET    /calendars/:id(.:format)                    calendars#show
                         PATCH  /calendars/:id(.:format)                    calendars#update
                         PUT    /calendars/:id(.:format)                    calendars#update
                         DELETE /calendars/:id(.:format)                    calendars#destroy

最后,这里是 posts_controller.rb 的内容:

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  # GET /posts
  # GET /posts.json
  def index
    @posts = Post.all
  end

  # GET /posts/1
  # GET /posts/1.json
  def show
  end

  # GET /posts/new
  def new
    @post = Post.new
  end

  # GET /posts/1/edit
  def edit
  end

  # POST /posts
  # POST /posts.json
  def create
    @calendar = Calendar.find(params[:calendar_id])
    @post = @calendar.posts.create(post_params)

    respond_to do |format|
      if @post.save
        format.html { redirect_to calendar_path(@calendar), notice: 'Post was successfully created.' }
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /posts/1
  # PATCH/PUT /posts/1.json
  def update
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to calendar_path, notice: 'Post was successfully updated.' }
        format.json { render :show, status: :ok, location: @post }
      else
        format.html { render :edit }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /posts/1
  # DELETE /posts/1.json
  def destroy
    @calendar = Calendar.find(params[:calendar_id])
    @post.destroy
    respond_to do |format|
      format.html { redirect_to calendar_path(@calendar), notice: 'Post was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

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

    # Never trust parameters from the scary internet, only allow the white list through.
    def post_params
      params.require(:post).permit(:date, :time, :subject, :format, :copy, :media)
    end
end

我一直遇到类似的错误 .

Issue #1 :当我尝试从 show.html.erb 日历视图中删除帖子时:

<h2><%= @calendar.name %> Calendar</h2>

<h3>Posts</h3>
<% if @calendar.posts.any? %>
    <table>
        <tr>
            <th>Date</th>
            <th>Time</th>
            <th>Subject</th>
            <th>Format</th>
            <th>Copy</th>
            <th>Media</th>
        </tr>
  <% @calendar.posts.each do |post| %>
        <tr>
        <td><%= post.date %></td>
            <td><%= post.time %></td>
            <td><%= post.subject %></td>
            <td><%= post.format %></td>
            <td><%= post.copy %></td>
            <td><%= post.media %></td>
        <td><%= link_to 'View', post %></td>
        <td><%= link_to 'Update', edit_post_path(post) %></td>
        <td><%= link_to 'Delete', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
        </tr>
    </table>
  <% end %>
...

我明白了:

ActiveRecord::RecordNotFound in PostsController#destroy
Couldn't find Calendar with 'id'=

Issue #2 :当我尝试从 edit.html.erb 帖子视图更新帖子时:

<h1>Editing Post</h1>

<%= render 'form' %>

<%= link_to 'Show', @post %> |
<%= link_to 'Back', posts_path %>

我明白了:

ActiveRecord::RecordNotFound in PostsController#update
Couldn't find Calendar with 'id'=

Issue #3 :当我尝试从show.html.erb帖子视图返回 show.html.erb 日历视图时:

<div>
    <p>Date</p>
    <%= @post.date %>
</div>
<div>
    <p>Time</p>
    <%= @post.time %>
</div>
<div>
    <p>Subject</p>
    <%= @post.subject %>
    </div>
<div>
    <p>Format</p>
    <%= @post.format %>
    </div>
<div>
    <p>Copy</p>
    <%= @post.copy %>
</div>
<div>
    <p>Media</p>
    <%= @post.media %>
</div>

<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>

我明白了:

ActiveRecord::RecordNotFound in PostsController#show
Couldn't find Calendar with 'id'=

如果我对错误的解释是正确的,那么每次,问题似乎都是我无法检索 post 属于 postid .

换句话说,我无法从子(post)控制器中检索父(日历)id .

我相信这是一个与我的嵌套浅层资源相关的问题以及我在视图中构建链接的方式 .

我无法弄清楚如何使这些链接工作 .

如果您可以为我提供解决方案 - 最重要的是推理 - 对于上述三种情况之一,我绝对能够为其他两种情况提出解决方案 .

任何的想法?

1 回答

  • 3

    我找到了解决我的三个问题的每个问题 .

    Issue #1 :我换了:

    format.html { redirect_to calendar_path(@calendar), notice: 'Post was successfully destroyed.' }
    

    有:

    format.html { redirect_to calendar_path(@post.calendar_id), notice: 'Post was successfully destroyed.' }
    

    posts_controller.rb .

    Issue #2 :我换了:

    <%= link_to 'Back', posts_path %>
    

    有:

    <%= link_to 'Back', calendar_path(@post.calendar_id) %>
    

    edit.html.erb 帖子视图中 .

    Issue #3 :我换了:

    <%= link_to 'Back', posts_path %>
    

    有:

    calendar_path(@post.calendar_id)
    

    show.html.erb 帖子视图中

相关问题