我正在尝试构建一个配置文件页面,该页面显示仅发送给所请求用户的帖子,并允许访问者编写自己的帖子。因为这个简化的示例应该有两个不同的控制器:用户和帖子,我为每个帖子操作制作了部分内容,以便在用户的show动作中呈现。
我的views目录的目录结构如下所示:
- posts
- _index.html.erb
- _new.html.erb
- users
- show.html.erb
... (etc.)
在用户show.html.erb
中显示这些部分内容的部分:
<section>
<h3>Posts:</h3>
<%= render '/posts/new', :post => Post.new %>
<%= render '/posts/index', :posts => Post.where(target_id: params[:id]) %>
</section>
我最终发现您可以将变量传递到此render
行中的部分变量,虽然这有效,但它非常混乱,可能并不遵循最佳做法。
理想情况下,我希望将这些部分与帖子控制器连接起来,这样我就可以在一个不是视图的地方编写更复杂的数据库查询:
class PostsController < ApplicationController
def new
@post = Post.new
end
def index
@posts = Post.where(target_id: params[:id])
end
def create
@post = Post.new(post_params)
@post.user_id = current_user.id
@post.target_id = params[:post][:target_id]
if @post.save
redirect_to :back, notice: 'You published a post!'
else
render new
end
end
private
def post_params
params.require(:post).permit(:body)
end
end
目前,我还没有找到办法。我知道这是一个新问题,但感谢您提前提供任何帮助。
答案 0 :(得分:2)
您正在尝试将控制器视为模型:在后控制器中进行后期工作,用户在用户控制器中工作。但控制器是面向任务的,而不是面向模型的。
由于您希望在用户表单中添加帖子信息,因此将其收集到用户控制器中是很典型的。 E.g。
class UsersController < ApplicationController
def show
...
@posts = Post.where(user_id: user.id)
end
end
在展示模板中显示@posts
个实例变量以及它调用的任何部分变量。但是许多程序员更喜欢通过render
参数明确地发送它,因为它更具功能性:
<%= render '/posts/post_list', posts: @posts %>
一方面,当您可以一目了然地看到所有部分依赖项时,它更容易重构。
答案 1 :(得分:0)
我同意@ Mori的建议。正如他所说,你试图在控制器中加入太多逻辑。我认为这是您试图将其从视图中删除的结果,这是正确的想法,但您希望业务逻辑在模型中。
此外,index
的{{1}}和new
操作永远不会被调用。例如,在调用渲染PostsController
时,即呈现视图,而不是控制器操作。因此,那些控制器动作没有理由存在。
我可能会以与Mori描述的方式不同的方式实现修复。建议的做法是尝试将尽可能少的实例变量从控制器传递到视图(see 3rd bullet in the linked section)。
由于它确实是我们在这里讨论的posts/new
的{{1}}动作,我作为有人试图理解你的代码会假设你传递给{{的实例变量1}}视图类似于show
。
在实例化UsersController
对象时,您可能希望使用show
方法。 @user
语句允许您使用尽可能少的查询来加载实例化所需的其他模型(防止N + 1查询情况)。如果有数千个匹配的帖子,你可能不想加载每一个帖子,所以我对其进行了任意限制。
<强> UsersController 强>
includes
查看强>
@user
如果要渲染编辑操作(includes
知道要使用哪个操作,则将部分替换为新def show
@user = User.find(params[:id]).includes(:received_posts).limit(10)
end
#....
作为名为<section>
<h3>Posts:</h3>
<% unless @user.id == current_user.id %>
<%= render 'posts/form', post: Post.new(user_id: @user.id) %>
<% end %>
<%= render @user.received_posts %>
</section>
的视图将允许您重复使用该表单通过调用传递的模型post
方法提交。
请注意,此代码假定posts/form
模型与设置为form_for
的帖子具有第二关系,但您可以将其更改为反映现实的内容。通过将persisted?
集合传递给render方法,Rails非常聪明,知道如果要呈现User
模型的集合以查找received_posts
部分并为每个部署渲染一个received_posts
。看起来IMO看起来更干净一点。只需确保将Post
代码移到其中即可。 posts/_post
暗示这是它自己的行为,而不是用作其他东西的部分行为。