ActionController :: UrlGenerationError with:admin namespace和嵌套资源

时间:2016-05-25 17:55:14

标签: ruby ruby-on-rails-4 model-view-controller nested-routes

美好的一天StackOverflow,

我已经创建了一个管理命名空间,并且在命名空间内我有一个客户端资源并嵌套在这样的网站资源中:

# routes.rb

namespace :admin do

  resouurces :clients do
    resources :sites
  end

end

我在尝试从“网站”展示页面转到网站“编辑”页面时遇到以下错误:

ActionController::UrlGenerationError at /admin/clients/9A81622C/sites/88AA/edit

然后BetterErrors在错误消息下面给出了这个:

No route matches {:action=>"show", :client_id=>nil, :controller=>"admin/clients/sites", :id=>"88AA"} missing required keys: [:client_id]

admin_client_site的rake路由输出如下:

     admin_client_sites POST   /admin/clients/:client_id/sites(.:format)          admin/clients/sites#create
  new_admin_client_site GET    /admin/clients/:client_id/sites/new(.:format)      admin/clients/sites#new
 edit_admin_client_site GET    /admin/clients/:client_id/sites/:id/edit(.:format) admin/clients/sites#edit
      admin_client_site GET    /admin/clients/:client_id/sites/:id(.:format)      admin/clients/sites#show
                        PATCH  /admin/clients/:client_id/sites/:id(.:format)      admin/clients/sites#update
                        PUT    /admin/clients/:client_id/sites/:id(.:format)      admin/clients/sites#update
                        DELETE /admin/clients/:client_id/sites/:id(.:format)      admin/clients/sites#destroy

“show page”上的编辑链接目前如下,这就是问题所在(或者我相信):

<%= link_to "Edit", edit_admin_client_site_path(@client, @site) %>

客户的form_for,网站是:

<%= form_for [:admin, @client, @site], :url => admin_client_sites_url do |f| %>

我花了最后一天查看各种堆栈答案,仍然无法解决这个问题,非常感谢任何帮助,请提前感谢,如果您需要更多文档,请告诉我们!

编辑#1 - 添加客户端和站点模型

Client.rb
class Client < ActiveRecord::Base
  before_create :generate_client_ident

    # Model Relations
    has_many :sites, dependent: :destroy

    # Model Validations
    validates_uniqueness_of :client_ident

    # Unique Admin Identifier
    def generate_client_ident
      begin
        self.client_ident = SecureRandom.hex(4).upcase
        other_client = Client.find_by(client_ident: self.client_ident)
      end while other_client
    end

    # Vanity URL
    def to_param
      client_ident
    end
end


Site.rb
class Site < ActiveRecord::Base
  before_create :generate_site_ident

  # Model Relations
  belongs_to :client

  # Model Validations
  validates_uniqueness_of :site_ident

  # Unique Admin Identifier
  def generate_site_ident
    begin
      self.site_ident = SecureRandom.hex(2).upcase
      other_site = Site.find_by(site_ident: self.site_ident)
    end while other_site
  end

  # Vanity URL
  def to_param
    site_ident
  end

end

编辑#2 - 添加控制器

class Admin::Clients::SitesController < ApplicationController
  before_action :authenticate_admin_admin!
  before_action :set_site, only: [:show, :edit, :update, :destroy]

  # GET /sites
  # GET /sites.json
  def index
    @sites = Site.all
  end

  # GET /sites/1
  # GET /sites/1.json
  def show
    @client = Client.find_by_client_ident(params[:id])
  end

  # GET /sites/new
  def new
    @client = Client.find_by_client_ident(params[:id])
    @site = Site.new
  end

  # GET /sites/1/edit
  def edit
    @client = Client.find_by_client_ident(params[:id])
  end

  # POST /sites
  # POST /sites.json
  def create
    @client = Client.find_by_client_ident(params[:id])
    @site = Site.new(site_params)
    @site.client = @client

    respond_to do |format|
      if @site.save
        format.html { redirect_to admin_clients_url, notice: 'Site was successfully created.' }
        format.json { render :show, status: :created, location: [:admin, @client] }
      else
        format.html { render :new }
        format.json { render json: @site.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 [:admin, @client], notice: 'Site was successfully updated.' }
        format.json { render :show, status: :ok, location: [:admin, @client] }
      else
        format.html { render :edit }
        format.json { render json: @site.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_by_site_ident(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def site_params
      params.require(:site).permit(:client_id, :site_ident)
    end
end

class Admin::ClientsController < ApplicationController
  before_action :authenticate_admin_admin!
  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_by_client_ident(params[:id])
    @site = @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 [:admin, @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 [:admin, @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 [:admin, @client], 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_by_client_ident(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def client_params
      params.fetch(:client, {}).permit(:client_ident, :client_name, :street_number, :street_name, :unit_apt, :grid, :city,
                             :province, :postal_code, :office_tel, :office_ext, :cell_tel, :fax, :contact_email, :same_as_above,
                             :bill_to_client_name, :bill_to_street_number, :bill_to_street_name, :bill_to_grid, :bill_to_city,
                             :bill_to_province, :bill_to_postal_code)
    end
end

编辑#3添加错误的ScreenShot enter image description here

编辑#4 - 点击“网站显示页面”上的编辑链接时添加Rails服务器日志

Started GET "/admin/clients/9A81622C/sites/88AA" for ::1 at 2016-05-25 14:10:51 -0600
Processing by Admin::Clients::SitesController#show as HTML
  Parameters: {"client_id"=>"9A81622C", "id"=>"88AA"}
  Admin Load (0.4ms)  SELECT  "admins".* FROM "admins" WHERE "admins"."id" = $1  ORDER BY "admins"."id" ASC LIMIT 1  [["id", 1]]
  Site Load (0.2ms)  SELECT  "sites".* FROM "sites" WHERE "sites"."site_ident" = $1 LIMIT 1  [["site_ident", "88AA"]]
  Client Load (0.2ms)  SELECT  "clients".* FROM "clients" WHERE "clients"."id" = $1 LIMIT 1  [["id", 9]]
  Rendered admin/clients/sites/show.html.erb within layouts/application (3.4ms)
Completed 500 Internal Server Error in 12ms (ActiveRecord: 0.8ms)

2 个答案:

答案 0 :(得分:0)

看起来问题可能出在您的Sites控制器中。在查看您尝试设置@client的方式时,我发现您将其视为:@client = Client.find_by_client_ident(params[:id])

但是在嵌套params[:id]的这个级别会引用网站的ID,而不是客户端。我不确切知道您如何使用/存储client_ident与客户的实际id相比,我希望看到以下内容:

@client = Client.find_by_id(params[:client_id])

这是因为在您的路由中,您为.../clients/:client_id/sites/:site_id设置了路径,因此:client_id将被传入。在这种情况下,当您尝试在Sites控制器中查找客户端时您将网站的ID作为参数传递而不是client_id

如果您的client_ident!= client.id,那么我就不会尝试使用params[:id]Client.find_by_client_ident查找/加载记录,因为那些不应该是{39}} ;匹配(除非,就像我说的,我在你如何实现client_ident时遗漏了一些东西)。

让我们知道您的想法以及该更改是否适合您:)

答案 1 :(得分:0)

我知道这个问题可能很久以前就已经回答了......但是看看你的代码我发现这里有错误

&#13;
&#13;
resouurces :clients do
&#13;
&#13;
&#13;

资源