我正在建立一个用户可以在其中创建项目的网站。每个项目包含几篇论文。可以通过回答几个问题来评论每篇论文。
我有四个模型(用户,项目,论文,问题)。
在questions_controller
中,我创建了一个动作replies
,目的是选择所有包含特定project_id
和paper_id
的答复。
在对象@replies
中,我想选择所有论文并投影URL中显示的project_id
和paper_id
。
http://0.0.0.0:3000/projects/3/papers/2/questions/1/replies
我想选择所有带有project_id == 3
和paper_id == 2
的回复
为此,我编写了以下代码:
questions_controller.rb
def replies
@project = Project.find(params[:project_id])
@paper = Paper.find(params[:paper_id])
@replies = Question.where("project_id = ? AND paper_id = ?", params[:project_id], params[:paper_id])
end
并在其中传递了@replies
:
views / questions / replies.html.erb
<% @replies.each do |reply| %>
<%= reply %>
<% end %>
但是,它不起作用。实际上,我在@replies
中进行的查询未在我的 views / questions / replies.html.erb 中传递任何内容。
我不确定自己在做什么错。
routes.rb
Rails.application.routes.draw do
resources :projects do
resources :papers do
resources :questions do
collection do
get 'replies'
end
end
end
end
devise_for :users
root to: 'pages#home'
project.rb
class Project < ApplicationRecord
belongs_to :user
has_many :papers, dependent: :destroy
has_many :questions
end
paper.rb
class Paper < ApplicationRecord
belongs_to :project
has_many :questions
has_one_attached :paper_pdf
end
question.rb
class Question < ApplicationRecord
belongs_to :user
belongs_to :paper
belongs_to :project
end
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :projects
has_many :questions
end
答案 0 :(得分:0)
您的应用程序设计中存在不同的问题。
第一个是问题的关系:
class Question < ApplicationRecord
belongs_to :user
belongs_to :paper
belongs_to :project
end
我了解您在此处尝试做的事情:一个问题可以应用于不同的模型:用户,纸张,项目。尽管存在问题:问题只能引用这些模型之一(一个问题同时应用于不同的对象,这很奇怪)。然后,当您创建一个与用户有关的新问题时,纸张(paper_id
)和项目(project_id
)的外键将为空。
这不是一个好的设计。这样做的方法是使Question模型成为多态模型。
如果如上所述,如果Question仅适用于论文,那么为什么Question是Paper以外的其他模型的子代?
第二个问题:您尝试使用两个外键获取“问题”:
@replies = Question.where("project_id = ? AND paper_id = ?", params[:project_id], params[:paper_id])
正如我之前在问题1中所述,您的Question模型可能有3个外键(属于它的3个模型),但是一个问题一次不能引用多个模型。
因此,当您尝试同时使用这2个外键来提问时,您可能无法获得查询的答案。
第三个问题:使用浅层嵌套,您的路线太深:
http://0.0.0.0:3000/projects/3/papers/2/questions/1/replies
这里不需要三个嵌套级别。您似乎是新手,因此可能不会感到直观,但请在下面查看我的建议
建议:
如果我正确阅读了您的问题布局,则问题仅适用于论文。
然后,如果您想获得与本文相关的所有问题,最好在此模型中而不是问题模型中创建一个新方法get replies
。
使其成为成员,而不是集合:
路线:
...
resources :papers do
member do
get 'replies'
end
end
...
然后,当您的路线以papers/5/replies
结尾
您可以在纸张控制器中触发以下代码:
def replies
@paper = Paper.find(params[:id])
@replies = @paper.questions
end
您注意到我的操作代码实际上并不需要路线中的任何先前ID。我只选择与数字5相关的params[:id]
。纸张模型的ID。
如果您有深层嵌套的路由,您将意识到该路由中有一些未使用的数据。路线中真正重要的数据是最后一个参数。也许是前面的参数。
如果您需要确保论文属于当前用户项目,只需将当前用户与论文ID进行比较即可:
unless current_user.id == Paper.find(params[:id]).project.user.id
redirect_to root_path
然后就这样