Rails 5 - using polymorphic associations - rendering the views
我正在尝试学习如何在Rails 5应用程序中使用多态关联。我最近问了这个问题,但是我对其进行了多次编辑,以显示我尝试的所有内容,但变得混乱了
我有一个名为Organisation,Proposal和Package :: Bip的模型。
关联为:
组织
1 2 | has_many :bips, as: :ipable, class_name: Package::Bip accepts_nested_attributes_for :bips, reject_if: :all_blank, allow_destroy: true |
提案
1 2 | has_many :bips, as: :ipable, class_name: Package::Bip accepts_nested_attributes_for :bips, reject_if: :all_blank, allow_destroy: true |
Package :: Bip
1 | belongs_to :ipable, :polymorphic => true, optional: true #, inverse_of: :bip |
Package :: Bip可以与"组织"或"投标"相关联。我正在努力弄清楚如何显示Package :: Bips仅属于提案提案中的提案,而对于组织而言则相同。
我的package :: bip表具有以下两列:
1 2 | # ipable_id :integer # ipable_type :string |
ipable_type设置为投标或组织。
在我的提案秀中,我有:
1 2 3 4 5 | <% if @proposal.bips.present? %> <%#= render @proposal.bips %> <%= link_to proposal_package_bips_path(@proposal) do %> <% end %> <% end %> |
我找到了这个帖子。我理解它的意思是我也应该可以尝试以下操作:我也尝试过:
1 2 3 | <% if @proposal.bips.present? %> <%= render @proposal.bips %> <% end %> |
我认为(@proposal)应该是决定返回哪个package_bip实例的约束因素。但是,事实并非如此。我不确定正在做什么,因为所有package_bips都已渲染(包括与组织相关联的package_bips)。
在我的投标控制器中,我有:
1 2 3 4 5 6 7 8 9 10 | def index @proposals = Proposal.all # @bips = @proposal.bips # authorize @proposals end def show @bips = @proposal.bips#.where(ipable_type: 'Proposal') end |
在我的Package :: BipsController中,我有
1 2 3 4 5 6 7 | def index if params[:ipable_type] =="Proposal" @bips = Package::Bip.where(:ipable_type == 'Proposal') else params[:ipable_type] == 'Organisation' @bips = Package::Bip.where(:ipable_type == 'Organisation') end |
但是,当我保存所有这些并尝试使用时,我得到了错误的结果。
目前,数据库中有4个Package :: Bip实例。
1 2 3 | Package::Bip.pluck(:ipable_type) (0.8ms) SELECT"package_bips"."ipable_type" FROM"package_bips" => ["Proposal","Proposal","Proposal","Organisation"] |
3个属于建议,1个属于组织。
属于投标的3个投标分别属于不同的投标。
1 2 3 | Package::Bip.pluck(:ipable_id) (0.8ms) SELECT"package_bips"."ipable_id" FROM"package_bips" => [15, 13, 16, 1] |
我的目标是提案展示视图或组织展示视图应仅显示属于该特定提案的Bips。
但是,当我渲染提案展示视图时,它具有:
1 | <%= link_to proposal_package_bips_path(@proposal) do %> |
依次,我的views / package / bips / index.html.erb具有:
1 2 3 | <% @bips.each do |ip| %> <%= ip.title.titleize %> <%#= link_to 'More details', package_bip_path(ip) %> |
我希望该视图呈现一个包含1个package_bip实例的列表。取而代之的是,我列出了所有4个实例(proposal.bips属于不同的投标,而bib之一属于组织)。这些都不应该在索引中呈现。
此外,我无法在bips / index.html.erb中添加到bips / show.html.erb的链接。这是因为该链接看起来像:
1 | <%= link_to 'More details', package_bip_path(ip) %> < |
当我尝试使用其中的链接呈现索引时,出现错误消息:
1 | undefined method `package_bip_path' for #<#<Class:0x007fbce68389c0>:0x007fbcfdc31c18> |
我认为链接可能需要包含提案或组织。
我的路线被嵌套:
1 2 3 4 5 6 7 8 9 | resources :proposals do namespace :package do resources :bips end resources :organisations do namespace :package do resources :bips end |
从控制台,我可以搜索要应用的过滤器。
1 2 3 4 5 6 7 8 9 | p = Proposal.last Proposal Load (4.8ms) SELECT "proposals".* FROM"proposals" ORDER BY"proposals"."id" DESC LIMIT $1 [["LIMIT", 1]] => #<Proposal id: 16, user_id: 4, title:"test tenor", description:"test tenor", created_at:"2016-11-08 21:58:38", updated_at:"2016-11-08 21:58:38"> 2.3.1p112 :199 > p.bips Package::Bip Load (0.3ms) SELECT"package_bips".* FROM"package_bips" WHERE"package_bips"."ipable_id" = $1 AND"package_bips"."ipable_type" = $2 [["ipable_id", 16], ["ipable_type","Proposal"]] => #<ActiveRecord::Associations::CollectionProxy [#<Package::Bip id: 19, identifier:"test tenor", description: nil, conditions:"test tenor", ipable_id: 16, ipable_type:"Proposal", created_at:"2016-11-08 21:58:38", updated_at:"2016-11-08 21:58:38", title:"test tenor", status: nil, classification:"Copyright">]> 2.3.1p112 :200 > p.bips.count (3.5ms) SELECT COUNT(*) FROM"package_bips" WHERE"package_bips"."ipable_id" = $1 AND"package_bips"."ipable_type" = $2 [["ipable_id", 16], ["ipable_type","Proposal"]] => 1 |
但这在我的任何尝试中都不会延续到代码中。
任何人都可以向我介绍一些资源,这些资源可以帮助我弄清楚如何设置我的多态视图,以便它们可以正确地进行过滤,以便我可以使用典型的索引链接(例如,显示/编辑),以便他们可以被视为属于提案/组织中的一个或另一个?
更新
我现在已经找到了该帖子。
我尝试采用以下建议的流程:
在投标控制器中将创建动作更改为:
def创建
如果参数[:organisation_id]
父= Organisation.find(params [:organisation_id])
elsif params [:proposal_id]
父= Proposal.find(params [:proposal_id])
结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | bip = Package::Bip.new Package::Bip.ipable = parent # @bip = Package::Bip.new(bip_params) # authorize @bip respond_to do |format| if @bip.save format.html { redirect_to @bip } format.json { render :show, status: :created, location: @bip } else format.html { render :new } format.json { render json: @bip.errors, status: :unprocessable_entity } end end |
end
将投标视图更改为:
尝试此操作时,没有出现任何错误,但是所有Package :: Bips都显示在投标显示视图中。
尽管有具有组织ID的Package :: Bip,但这仍然是
。
1 2 3 | Package::Bip.all.pluck(:ipable_type) (0.9ms) SELECT"package_bips"."ipable_type" FROM"package_bips" => ["Proposal","Proposal","Proposal","Organisation","Proposal"] |
当我重新启动服务器并重试时,我收到一条错误消息,内容为:
1 | undefined method `empty?' for #<Class:0x007ff20920e218> |
错误消息指向我的新行:
1 | <%= polymorphic_path(@proposal, Package::Bip) %> |
日志显示:
1 2 | Started POST"/__better_errors/3f34303f5f5c670f/variables" for ::1 at 2016-11-13 10:58:13 +1100 Package::Bip Load (0.4ms) SELECT"package_bips".* FROM"package_bips" WHERE"package_bips"."ipable_id" = $1 AND"package_bips"."ipable_type" = $2 [["ipable_id", 15], ["ipable_type","Proposal"]] |
此帖子显示了类似的问题,可以通过在路径中添加\\'[] \\'来解决。
然后我尝试:
1 | <%= link_to polymorphic_path([@proposal, Package::Bip]) do %> |
我仍然会获得所有bip的列表(甚至包括那些属于组织或具有不同ID的提案的bib)。
我从日志中看到的可能是一个线索(如果确实如此-它在我头上)。
1 2 3 4 5 6 7 | Started GET"/proposals/15/package/bips" for ::1 at 2016-11-13 11:24:32 +1100 Processing by Package::BipsController#index as HTML Parameters: {"proposal_id"=>"15"} User Load (1.1ms) SELECT "users".* FROM"users" WHERE"users"."id" = $1 ORDER BY"users"."id" ASC LIMIT $2 [["id", 4], ["LIMIT", 1]] Rendering package/bips/index.html.erb within layouts/application Package::Bip Load (0.6ms) SELECT"package_bips".* FROM"package_bips" Rendered package/bips/index.html.erb within layouts/application (5.4ms) |
该日志似乎未显示任何迹象表明它正在将提案或提案ID过滤器应用于package_bips。
这对我来说没有任何意义,因为我的路线仅在前缀为组织或提案的情况下可用:
1 2 3 4 5 6 7 8 9 | rake routes | grep package_bip organisation_package_bips GET /organisations/:organisation_id/package/bips(.:format) package/bips#index new_organisation_package_bip GET /organisations/:organisation_id/package/bips/new(.:format) package/bips#new edit_organisation_package_bip GET /organisations/:organisation_id/package/bips/:id/edit(.:format) package/bips#edit organisation_package_bip GET /organisations/:organisation_id/package/bips/:id(.:format) package/bips#show proposal_package_bips GET /proposals/:proposal_id/package/bips(.:format) package/bips#index new_proposal_package_bip GET /proposals/:proposal_id/package/bips/new(.:format) package/bips#new edit_proposal_package_bip GET /proposals/:proposal_id/package/bips/:id/edit(.:format) package/bips#edit proposal_package_bip GET /proposals/:proposal_id/package/bips/:id(.:format) package/bips#show |
此外,当我尝试在上一个链接的帖子中使用show路径时,在我的views / package / bips / index.html.erb中的显示方式为:
1 2 | <% @bips.each do |ip| %> <%= link_to polymorphic_path([@ipable, ip]) %> |
然后我看到一条错误消息:
1 | undefined method `package_bip_path' for #<#<Class:0x007f9e8ac29248>:0x007f9e939c9508> |
TARYN关于寻找问题的建议
背景。在我的提案控制器中,我的提案定义为:
1 2 3 | def set_proposal @proposal = Proposal.find(params[:id]) end |
在控制台中,我尝试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | params = {:proposal_id => 15} => {:proposal_id=>15} 2.3.1p112 :031 > @proposal = Proposal.find(params[:proposal_id]) Proposal Load (0.7ms) SELECT "proposals".* FROM"proposals" WHERE"proposals"."id" = $1 LIMIT $2 [["id", 15], ["LIMIT", 1]] => #<Proposal id: 15, user_id: 4, title:"testing filter", description:"testing filter", byline:"testing filter", nda_required: true, created_at:"2016-11-08 00:59:09", updated_at:"2016-11-08 00:59:09"> 2.3.1p112 :033 > @proposal.bips Package::Bip Load (0.7ms) SELECT"package_bips".* FROM"package_bips" WHERE"package_bips"."ipable_id" = $1 AND"package_bips"."ipable_type" = $2 [["ipable_id", 15], ["ipable_type","Proposal"]] => #<ActiveRecord::Associations::CollectionProxy [#<Package::Bip id: 17, identifier:"testing filter", description: nil, conditions:"testing filter", ipable_id: 15, ipable_type:"Proposal", created_at:"2016-11-08 00:59:09", updated_at:"2016-11-08 00:59:09", title:"testing filter", status: nil, classification:"Patent">, #<Package::Bip id: 21, identifier:"dd", description: nil, conditions:"dd", ipable_id: 15, ipable_type:"Proposal", created_at:"2016-11-10 22:47:54", updated_at:"2016-11-10 22:47:54", title:"ldsjflkjklsdjfl", status: nil, classification:"Design">]> 2.3.1p112 :034 > @proposal.bips.count (6.3ms) SELECT COUNT(*) FROM"package_bips" WHERE"package_bips"."ipable_id" = $1 AND"package_bips"."ipable_type" = $2 [["ipable_id", 15], ["ipable_type","Proposal"]] => 2 |
这将给出正确的结果。
在投标控制器中,显示操作,我有:
1 2 3 4 5 6 | def show @images = @proposal.images byebug puts 'testing proposal controller' @bips = @proposal.bips#.where(ipable_type: 'Proposal') end |
尝试时,我可以浏览提案参数:
1 2 3 4 5 6 | params <ActionController::Parameters {"controller"=>"proposals","action"=>"show","id"=>"15"} permitted: false> (byebug) proposal_params *** ActionController::ParameterMissing Exception: param is missing or the value is empty: proposal nil |
其他具有此问题的人将其归因于其强params方法中的\\'require \\'语句。
我的proposal_params定义为:
1 2 3 4 5 6 7 8 9 10 11 | def proposal_params params.require(:proposal).permit(:title, :description, :byline, :nda_required, :randd_maturities_list, #Package bips_attributes: [:id, :status, :classification, :identifier, :conditions, :title, :_destroy, tenor_attributes: [:id, :express_interest, :commencement, :expiry, :enduring, :repeat, :frequency, :_destroy] ], ) end |
我认为这是正确的。
这些消息很奇怪,因为我还可以遍历再见bug语句中的每个列入白名单的项目,并获得正确的响应。例如:
1 2 | @proposal.id 15 |
当我尝试通过Package :: bips控制器中的再见错误进行索引操作时,我可以看到:
1 2 | params.inspect "<ActionController::Parameters {"controller"=>"package/bips", "action"=>"index", "proposal_id"=>"15"} permitted: false>" |
在我的代码中,allowed:false属性似乎是一个问题。
这是我的下一条查询内容。
答案在这里:https://rubyplus.com/articles/3901-Polymorphic-Association-in-Rails-5
技巧似乎在本文所示的load_commentable方法中。对于我来说,它太复杂了以至于无法理解,但它确实有效。
非常高兴能乐于分享他们所知道的信息的人们提供了多少帮助。谢谢你泰伦