在Rails 4.2.5 中使用嵌套资源,是否可以收集所有子元素并将它们显示在同一页面上?
Working with nested resources in Rails 4.2.5, Is it possible to gather all child elements and display them on the same page?
作为 Rails 的新手,我还没有理解参数和控制器对我整个应用程序的影响。我在整个程序中访问@variables 时遇到问题。例如,在使用父资源控制器时,当我尝试在控制器中定义@child 时,我经常会收到错误 "Couldn't find Project with 'id'=" 或“undefined method ‘children’ for nil:NilClass”。
class ProjectsController < ApplicationController
before_action :find_project, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
before_action :find_campaigns, only: [:index]
def index
if params[:search]
@projects = Project.search(params[:search]).order("created_at DESC")
else
@projects = Project.all.order('created_at DESC')
end
end
def new
@project = current_user.projects.build
end
def create
@project = current_user.projects.build(project_params)
# @project = Project.new(project_params)
if @project.save
redirect_to @project, notice: "Successfully created new Project"
else
render 'new'
end
end
def edit
end
def update
if @project.update(project_params)
redirect_to @project, notice: "Project was Successfully updated"
else
render 'edit'
end
end
def show
@random_project = Project.where.not(id: @project).order("RANDOM()").first
end
def destroy
@project.destroy
redirect_to root_path
end
private
def project_params
params.require(:project).permit(:title, :location, :goal, :investor, :description, :image, :category)
end
def find_project
@project = Project.find(params[:id])
end
def find_campaigns
@campaign = @project.campaigns.find(params[:id])
end
end
以上是我的子控制器。如果我添加一个名为 find_projects 的私有方法(这是我的父对象),有没有办法访问所有项目的所有子项并将它们显示在一页上?
您将遍历每个项目并访问其 children。首先删除您的 find_campaigns
方法和 before_action :find_campaigns
,因为它们不需要。
打开app/views/projects/index.html.erb
<% if @projects.any? %>
<ul class="projects">
<% @projects.each do |p| %>
<li>
<h3><%= p.name %></h3>
<% if p.campaigns.any? %>
<ul class="campaigns">
<% @p.campaigns.each do |c| %>
<li><%= c.name %><li>
<% end %>
</ul>
<% end %>
</li>
<% end %>
</ul>
<% end %>
然而,在执行此操作时需要小心,因为您会导致所谓的 N+1
查询,其中 @projects.each
的每次迭代都会执行单独的 SQL 查询以获取children 这真的很慢。
我们可以通过使用 includes
来避免这种情况,以便一次性加载广告系列:
def find_project
@project = Project.includes(:campaigns).find(params[:id])
end
您可能想看看 the Rails Guides,因为它有一些非常好的技巧,可以使用部分来清理上面的循环。
作为 Rails 的新手,我还没有理解参数和控制器对我整个应用程序的影响。我在整个程序中访问@variables 时遇到问题。例如,在使用父资源控制器时,当我尝试在控制器中定义@child 时,我经常会收到错误 "Couldn't find Project with 'id'=" 或“undefined method ‘children’ for nil:NilClass”。
class ProjectsController < ApplicationController
before_action :find_project, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
before_action :find_campaigns, only: [:index]
def index
if params[:search]
@projects = Project.search(params[:search]).order("created_at DESC")
else
@projects = Project.all.order('created_at DESC')
end
end
def new
@project = current_user.projects.build
end
def create
@project = current_user.projects.build(project_params)
# @project = Project.new(project_params)
if @project.save
redirect_to @project, notice: "Successfully created new Project"
else
render 'new'
end
end
def edit
end
def update
if @project.update(project_params)
redirect_to @project, notice: "Project was Successfully updated"
else
render 'edit'
end
end
def show
@random_project = Project.where.not(id: @project).order("RANDOM()").first
end
def destroy
@project.destroy
redirect_to root_path
end
private
def project_params
params.require(:project).permit(:title, :location, :goal, :investor, :description, :image, :category)
end
def find_project
@project = Project.find(params[:id])
end
def find_campaigns
@campaign = @project.campaigns.find(params[:id])
end
end
以上是我的子控制器。如果我添加一个名为 find_projects 的私有方法(这是我的父对象),有没有办法访问所有项目的所有子项并将它们显示在一页上?
您将遍历每个项目并访问其 children。首先删除您的 find_campaigns
方法和 before_action :find_campaigns
,因为它们不需要。
打开app/views/projects/index.html.erb
<% if @projects.any? %>
<ul class="projects">
<% @projects.each do |p| %>
<li>
<h3><%= p.name %></h3>
<% if p.campaigns.any? %>
<ul class="campaigns">
<% @p.campaigns.each do |c| %>
<li><%= c.name %><li>
<% end %>
</ul>
<% end %>
</li>
<% end %>
</ul>
<% end %>
然而,在执行此操作时需要小心,因为您会导致所谓的 N+1
查询,其中 @projects.each
的每次迭代都会执行单独的 SQL 查询以获取children 这真的很慢。
我们可以通过使用 includes
来避免这种情况,以便一次性加载广告系列:
def find_project
@project = Project.includes(:campaigns).find(params[:id])
end
您可能想看看 the Rails Guides,因为它有一些非常好的技巧,可以使用部分来清理上面的循环。