【问题标题】:How to create a link_to delete action that removes a has_many through association?如何创建通过关联删除 has_many 的 link_to delete 操作?
【发布时间】:2016-11-23 17:09:29
【问题描述】:

花了最后一天半的时间在 SO 上浏览精彩的线程并在线阅读其他内容,但我仍然无法掌握解决方案以及这些移动部件如何协同工作。

我通过 CountyTownshipRangeSurvey 在 County 和 TownshipRange 之间建立了多对多关系。这种关系通过嵌套资源在路由文件中表示出来。

我希望用户能够删除两条记录之间的关联,但我遇到的问题是 TownshipRange 索引页面上的删除链接只接受 township_range id 值而不接受关联的县 id 值。请注意,查看索引页面(包含删除链接)时会显示正确的县 ID 参数。

我怎么能允许这样做?

我的直觉是我需要在两个地方进行更改。首先,到路线文件,以便它接受县 id,其次,到视图中的 link_to。

作为后续问题...我意识到我正在尝试将功能放入 township_ranges_controller。这是问题的一部分吗?将此功能移动到一个单独的控制器中是否会更好,该控制器专门用于创建“直通表”关联?

感谢大家的宝贵见解!如果您需要更多代码 sn-ps,请告诉我!

模型县.rb

class County < ApplicationRecord
  has_many :township_ranges, through: :county_township_range_surveys
  has_many :county_township_range_surveys
  ...
end

模型 township_range.rb

class TownshipRange < ApplicationRecord
  has_many :counties, through: :county_township_range_surveys
  has_many :county_township_range_surveys
  ...
end

模型county_township_range_survey.rb

class CountyTownshipRangeSurvey < ApplicationRecord
  belongs_to :county
  belongs_to :township_range
  ...
end

控制器 township_ranges_controller.rb

before_action :set_township_range, only: [:show, :edit, :update, :destroy]

...

# QUESTION: How do I find the appropriate county?
def destroy
  @county = County.find(params[:id]) # This does not work
  @county.township_ranges.destroy(@township_range)
  redirect_to township_ranges_path(@county)
  flash[:success] = "Township and Range has been deleted"
end

....

private

    def set_township_range
      @township_range = TownshipRange.find(params[:id])
    end

    ...

routes.rb 的相关部分(扩展为 20161124)

resources :states, shallow: true do
  resources :counties do
    resources :township_ranges do
      resources :sections
    end
  end
end

Rails routes 表示生成的路由不会为 DELETE 操作查找关联的counties/:id。

    township_ranges GET    /counties/:id/township_ranges(.:format)     township_ranges#index
                    POST   /counties/:id/township_ranges(.:format)     township_ranges#create
 new_township_range GET    /counties/:id/township_ranges/new(.:format) township_ranges#new
edit_township_range GET    /township_ranges/:id/edit(.:format)         township_ranges#edit
     township_range GET    /township_ranges/:id(.:format)              township_ranges#show
                    PATCH  /township_ranges/:id(.:format)              township_ranges#update
                    PUT    /township_ranges/:id(.:format)              township_ranges#update
                    DELETE /township_ranges/:id(.:format)              township_ranges#destroy

如果我像这样单独隔离嵌套,它将寻找完整的路线DELETE counties/:county_id/township_range/:id/

resources :counties do
  resources :township_ranges 
end

但这可以防止县嵌套在州之下,这不是我所追求的......

township_range/index.html.erb

<td><%= link_to 'Destroy', township_range, method: :delete, 
          data: { confirm: "Delete #{township_range.township} 
          #{township_range.range} ?" } %></td>

development.log(根据@Wish Zone 的要求进行链接更新)

Started GET "/counties/25/township_ranges" for 127.0.0.1 at 2016-11-23 15:23:20 -0600
Processing by TownshipRangesController#index as HTML
  Parameters: {"id"=>"25"}
  [1m[36mCounty Load (0.1ms)[0m  [1m[34mSELECT  "counties".* FROM "counties" WHERE "counties"."id" = ? LIMIT ?[0m  [["id", 25], ["LIMIT", 1]]
  Rendering township_ranges/index.html.erb within layouts/application
  [1m[36mTownshipRange Load (34.5ms)[0m  [1m[34mSELECT "township_ranges".* FROM "township_ranges" INNER JOIN "county_township_range_surveys" ON "township_ranges"."id" = "county_township_range_surveys"."township_range_id" WHERE "county_township_range_surveys"."county_id" = ?[0m  [["county_id", 25]]
  Rendered township_ranges/index.html.erb within layouts/application (72.6ms)
Completed 500 Internal Server Error in 113ms (ActiveRecord: 35.2ms)



ActionView::Template::Error (No route matches {:action=>"show", :controller=>"township_ranges", :county_id=>#<County id: 25, name: "comanche", abbreviation: nil, state_id: 35, created_at: "2016-11-22 16:24:52", updated_at: "2016-11-22 16:24:52">, :id=>nil} missing required keys: [:id]):
    22:         <td><%= link_to 'Edit', edit_township_range_path(township_range) %></td>
    23:         <%# QUESTION: Do I need to modify the link here so it somehow takes in the county id param? %>
    24:         <%# NOTE: This will likely also require some sort of customization to the routes file so that the county_id is passed as a param %>
    25:         <td><%= link_to 'Destroy', township_range_path(id: @township_range, county_id: @county), method: :delete,
    26:                   data: { confirm: "Delete #{township_range.township} #{township_range.range} ?" } %></td>
    27:       </tr>
    28:     <% end %>

【问题讨论】:

  • 路线应该是 township_range(id: township_range , country_id: country) 并且在控制器中你可以找到 Country.find(params[:country_id])

标签: ruby-on-rails ruby-on-rails-5


【解决方案1】:

根据你的情况Route应该是

township_range_path(id: @township_range , county_id: @county)

在控制器中你可以找到

County.find(params[:county_id])

由 Spectator6 添加:最终的答案是删除我最初在路线中的成员行为。工作删除路径最终是

township_range_path(id: township_range, county_id: @county)

再次感谢@Wish Zone 的耐心等待,并帮助我更好地理解link_to 路径和路线:)

【讨论】:

  • 好的,谢谢。如何在路由文件中实现?我假设这会以某种方式覆盖资源 :township_ranges?
  • @Spectator6 那边不需要修改
  • @Spectator6 你的请求会这样:删除 /township_ranges/9?country_id=12
  • 啊,好吧,所以将它应用到索引中的链接,这是你的意思吗? link_to 'Destroy', township_range_path(id: @township_range, County_id: @county), method: :delete ...
  • @Spectator6 是
猜你喜欢
  • 2012-05-13
  • 1970-01-01
  • 2014-06-03
  • 1970-01-01
  • 2012-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-12
相关资源
最近更新 更多