Rails 5 多个嵌套属性无路由错误未初始化常量站点
Rails 5 multiple nested attributes no Routing Error uninitialized constant Sites
你好,我有一个带有三个嵌套模型 Client、Site 和 Damper 的小应用程序。当我添加一个客户端或 client_site 时,一切都很好......但是当我添加一个阻尼器时,我得到
Routing Error
uninitialized constant Sites
在控制台中
Started GET "/clients/1/sites/1/dampers/new" for my ip at 2018-10-26 18:05:29 +1000
ActionController::RoutingError (uninitialized constant Sites):
app/controllers/clients/sites/dampers_controller.rb:1:in `<main>'
路线
resources :clients do
resources :sites, controller: 'clients/sites' do
resources :dampers, controller: 'clients/sites/dampers'
end
end
型号
app/models/client.rb
class Client < ApplicationRecord
has_many :sites
end
app/models/site.rb
class Site < ApplicationRecord
belongs_to :client
has_many :dampers
end
app/models/damper.rb
class Damper < ApplicationRecord
belongs_to :site
end
请注意我犯了一个错误,这最初是 :sites 但即使在更改之后错误仍然存在。
控制器
app/controllers/clients_controller.rb
class ClientsController < ApplicationController
before_action :set_client, only: [:show, :edit, :update, :destroy]
# GET /clients
# GET /clients.json
def index
@clients = Client.all
end
# GET /clients/1
# GET /clients/1.json
def show
@client = Client.find(params[:id])
@sites = @client.sites
end
# GET /clients/new
def new
@client = Client.new
end
# GET /clients/1/edit
def edit
end
# POST /clients
# POST /clients.json
def create
@client = Client.new(client_params)
respond_to do |format|
if @client.save
format.html { redirect_to @client, notice: 'Client was successfully created.' }
format.json { render :show, status: :created, location: @client }
else
format.html { render :new }
format.json { render json: @client.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /clients/1
# PATCH/PUT /clients/1.json
def update
respond_to do |format|
if @client.update(client_params)
format.html { redirect_to @client, notice: 'Client was successfully updated.' }
format.json { render :show, status: :ok, location: @client }
else
format.html { render :edit }
format.json { render json: @client.errors, status: :unprocessable_entity }
end
end
end
# DELETE /clients/1
# DELETE /clients/1.json
def destroy
@client.destroy
respond_to do |format|
format.html { redirect_to clients_url, notice: 'Client was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_client
@client = Client.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def client_params
params.require(:client).permit(:name)
end
end
app/controllers/clients/sites_controller.rb
class Clients::SitesController < ApplicationController
before_action :set_client
before_action :set_site, except: [:new, :create]
# GET /sites
# GET /sites.json
def index
@sites = Site.all
end
# GET /sites/1
# GET /sites/1.json
def show
@client = Client.find(params[:client_id])
@site = @client.sites.find(params[:id])
end
# GET /sites/new
def new
@site = Site.new
end
# GET /sites/1/edit
def edit
end
# POST /sites
# POST /sites.json
def create
@site = Site.new(site_params)
@site.client = @client
respond_to do |format|
if @site.save
format.html { redirect_to @client, notice: 'Site was successfully created.' }
format.json { render :show, status: :created, location: @client }
else
format.html { render :new }
format.json { render json: @client.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /sites/1
# PATCH/PUT /sites/1.json
def update
respond_to do |format|
if @site.update(site_params)
format.html { redirect_to @client, notice: 'Site was successfully updated.' }
format.json { render :show, status: :ok, location: @site }
else
format.html { render :edit }
format.json { render json: @client.errors, status: :unprocessable_entity }
end
end
end
# DELETE /sites/1
# DELETE /sites/1.json
def destroy
@site.destroy
respond_to do |format|
format.html { redirect_to sites_url, notice: 'Site was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_site
@site = Site.find(params[:id])
end
def set_client
@client = Client.find(params[:client_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def site_params
params.require(:site).permit(:name, :client_id)
end
end
app/controllers/clients/sites/dampers_controller.rb
class Sites::DampersController < ApplicationController
before_action :set_client
before_action :set_site
before_action :set_damper, except: [:new, :create]
# GET /dampers
# GET /dampers.json
def index
@dampers = Damper.all
end
# GET /dampers/1
# GET /dampers/1.json
def show
end
# GET /dampers/new
def new
@damper = Damper.new
end
# GET /dampers/1/edit
def edit
end
# POST /dampers
# POST /dampers.json
def create
@damper = Damper.new(damper_params)
@damper.site = @site
respond_to do |format|
if @damper.save
format.html { redirect_to @site, notice: 'Damper was successfully created.' }
format.json { render :show, status: :created, location: @site }
else
format.html { render :new }
format.json { render json: @site.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /dampers/1
# PATCH/PUT /dampers/1.json
def update
respond_to do |format|
if @damper.update(damper_params)
format.html { redirect_to @site, notice: 'Damper was successfully updated.' }
format.json { render :show, status: :ok, location: @site }
else
format.html { render :edit }
format.json { render json: @site.errors, status: :unprocessable_entity }
end
end
end
# DELETE /dampers/1
# DELETE /dampers/1.json
def destroy
@damper.destroy
respond_to do |format|
format.html { redirect_to dampers_url, notice: 'Damper was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_damper
@damper = Damper.find(params[:id])
end
def set_site
@site = Site.find(params[:site_id])
end
def set_client
@client = Client.find(params[:client_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def damper_params
params.require(:damper).permit(:location, :number, :site_id, :client_id)
end
end
您创建了一个名为 Sites::DampersController
的控制器,它是一个 class DampersController
定义在名为 [=14 的命名空间(模块,class,...)内=], 但你忘了定义最后一个。
您可以这样创建它:
module Sites
class DampersController < ApplicationController
end
end
或者去掉 Sites::
部分。
您还需要更新路由,以指定正确的控制器名称。
更一般地,更容易遵循rails默认路由生成:
resources :clients do
resources :sites do
resources :dampers
end
end
这将创建指向以下控制器的路由:
ClientsController
SitesController
DampersController
如果您真的打算将其他控制器放在子文件夹中,按照您原来的路线,您需要定义以下内容:
- 控制器
ClientsController
- 模块
Clients
- 控制器
SitesController
内部模块 Clients
- 模块
Sites
内部模块 Clients
- 控制器
DampersController
内部模块 Clients::Sites
为了自动加载,也必须在子文件夹中组织:
- app/controllers
- clients_controllers.rb
- 客户/
- sites__controllers.rb
- 站点/
- dampers_controllers.rb
ActionController::RoutingError (uninitialized constant Sites)
dampers_controller.rb
位于 controllers/clients/sites
之下,因此您需要将 class 名称 更改为
class Clients::Sites::DampersController < ApplicationController
而不是
class Sites::DampersController < ApplicationController
为了 命名空间
此外,我建议你看看controller-namespaces-and-routing
你好,我有一个带有三个嵌套模型 Client、Site 和 Damper 的小应用程序。当我添加一个客户端或 client_site 时,一切都很好......但是当我添加一个阻尼器时,我得到
Routing Error
uninitialized constant Sites
在控制台中
Started GET "/clients/1/sites/1/dampers/new" for my ip at 2018-10-26 18:05:29 +1000
ActionController::RoutingError (uninitialized constant Sites):
app/controllers/clients/sites/dampers_controller.rb:1:in `<main>'
路线
resources :clients do
resources :sites, controller: 'clients/sites' do
resources :dampers, controller: 'clients/sites/dampers'
end
end
型号
app/models/client.rb
class Client < ApplicationRecord
has_many :sites
end
app/models/site.rb
class Site < ApplicationRecord
belongs_to :client
has_many :dampers
end
app/models/damper.rb
class Damper < ApplicationRecord
belongs_to :site
end
请注意我犯了一个错误,这最初是 :sites 但即使在更改之后错误仍然存在。
控制器
app/controllers/clients_controller.rb
class ClientsController < ApplicationController
before_action :set_client, only: [:show, :edit, :update, :destroy]
# GET /clients
# GET /clients.json
def index
@clients = Client.all
end
# GET /clients/1
# GET /clients/1.json
def show
@client = Client.find(params[:id])
@sites = @client.sites
end
# GET /clients/new
def new
@client = Client.new
end
# GET /clients/1/edit
def edit
end
# POST /clients
# POST /clients.json
def create
@client = Client.new(client_params)
respond_to do |format|
if @client.save
format.html { redirect_to @client, notice: 'Client was successfully created.' }
format.json { render :show, status: :created, location: @client }
else
format.html { render :new }
format.json { render json: @client.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /clients/1
# PATCH/PUT /clients/1.json
def update
respond_to do |format|
if @client.update(client_params)
format.html { redirect_to @client, notice: 'Client was successfully updated.' }
format.json { render :show, status: :ok, location: @client }
else
format.html { render :edit }
format.json { render json: @client.errors, status: :unprocessable_entity }
end
end
end
# DELETE /clients/1
# DELETE /clients/1.json
def destroy
@client.destroy
respond_to do |format|
format.html { redirect_to clients_url, notice: 'Client was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_client
@client = Client.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def client_params
params.require(:client).permit(:name)
end
end
app/controllers/clients/sites_controller.rb
class Clients::SitesController < ApplicationController
before_action :set_client
before_action :set_site, except: [:new, :create]
# GET /sites
# GET /sites.json
def index
@sites = Site.all
end
# GET /sites/1
# GET /sites/1.json
def show
@client = Client.find(params[:client_id])
@site = @client.sites.find(params[:id])
end
# GET /sites/new
def new
@site = Site.new
end
# GET /sites/1/edit
def edit
end
# POST /sites
# POST /sites.json
def create
@site = Site.new(site_params)
@site.client = @client
respond_to do |format|
if @site.save
format.html { redirect_to @client, notice: 'Site was successfully created.' }
format.json { render :show, status: :created, location: @client }
else
format.html { render :new }
format.json { render json: @client.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /sites/1
# PATCH/PUT /sites/1.json
def update
respond_to do |format|
if @site.update(site_params)
format.html { redirect_to @client, notice: 'Site was successfully updated.' }
format.json { render :show, status: :ok, location: @site }
else
format.html { render :edit }
format.json { render json: @client.errors, status: :unprocessable_entity }
end
end
end
# DELETE /sites/1
# DELETE /sites/1.json
def destroy
@site.destroy
respond_to do |format|
format.html { redirect_to sites_url, notice: 'Site was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_site
@site = Site.find(params[:id])
end
def set_client
@client = Client.find(params[:client_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def site_params
params.require(:site).permit(:name, :client_id)
end
end
app/controllers/clients/sites/dampers_controller.rb
class Sites::DampersController < ApplicationController
before_action :set_client
before_action :set_site
before_action :set_damper, except: [:new, :create]
# GET /dampers
# GET /dampers.json
def index
@dampers = Damper.all
end
# GET /dampers/1
# GET /dampers/1.json
def show
end
# GET /dampers/new
def new
@damper = Damper.new
end
# GET /dampers/1/edit
def edit
end
# POST /dampers
# POST /dampers.json
def create
@damper = Damper.new(damper_params)
@damper.site = @site
respond_to do |format|
if @damper.save
format.html { redirect_to @site, notice: 'Damper was successfully created.' }
format.json { render :show, status: :created, location: @site }
else
format.html { render :new }
format.json { render json: @site.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /dampers/1
# PATCH/PUT /dampers/1.json
def update
respond_to do |format|
if @damper.update(damper_params)
format.html { redirect_to @site, notice: 'Damper was successfully updated.' }
format.json { render :show, status: :ok, location: @site }
else
format.html { render :edit }
format.json { render json: @site.errors, status: :unprocessable_entity }
end
end
end
# DELETE /dampers/1
# DELETE /dampers/1.json
def destroy
@damper.destroy
respond_to do |format|
format.html { redirect_to dampers_url, notice: 'Damper was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_damper
@damper = Damper.find(params[:id])
end
def set_site
@site = Site.find(params[:site_id])
end
def set_client
@client = Client.find(params[:client_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def damper_params
params.require(:damper).permit(:location, :number, :site_id, :client_id)
end
end
您创建了一个名为 Sites::DampersController
的控制器,它是一个 class DampersController
定义在名为 [=14 的命名空间(模块,class,...)内=], 但你忘了定义最后一个。
您可以这样创建它:
module Sites
class DampersController < ApplicationController
end
end
或者去掉 Sites::
部分。
您还需要更新路由,以指定正确的控制器名称。
更一般地,更容易遵循rails默认路由生成:
resources :clients do
resources :sites do
resources :dampers
end
end
这将创建指向以下控制器的路由:
ClientsController
SitesController
DampersController
如果您真的打算将其他控制器放在子文件夹中,按照您原来的路线,您需要定义以下内容:
- 控制器
ClientsController
- 模块
Clients
- 控制器
SitesController
内部模块Clients
- 模块
Sites
内部模块Clients
- 控制器
DampersController
内部模块Clients::Sites
为了自动加载,也必须在子文件夹中组织:
- app/controllers
- clients_controllers.rb
- 客户/
- sites__controllers.rb
- 站点/
- dampers_controllers.rb
ActionController::RoutingError (uninitialized constant Sites)
dampers_controller.rb
位于 controllers/clients/sites
之下,因此您需要将 class 名称 更改为
class Clients::Sites::DampersController < ApplicationController
而不是
class Sites::DampersController < ApplicationController
为了 命名空间
此外,我建议你看看controller-namespaces-and-routing