【问题标题】:Rails 5 - how to establish routes for namespaced modelsRails 5 - 如何为命名空间模型建立路由
【发布时间】:2017-03-25 03:46:08
【问题描述】:

我正在尝试学习如何在我的 Rails 5 应用程序中使用命名空间模型,以便更好地组织我的内容。

我有一个地址模型。它是多态的。每个设置和组织都有许多地址。 Settings 是一个在 user 下命名空间的模型。

关联是

用户

has_one :setting, dependent: :destroy 

设置

belongs_to :user

  has_many :addresses, as: :addressable#, class_name: Address
    accepts_nested_attributes_for :addresses,  reject_if: :all_blank, allow_destroy: true

组织

has_many :addresses, as: :addressable#, class_name: Address
    accepts_nested_attributes_for :addresses,  reject_if: :all_blank, allow_destroy: true

地址

belongs_to :addressable, :polymorphic => true, optional: true

路线 - 组织

resources :organisations do
    namespace :contacts do
      resources :addresses
      resources :phones 
    end
  end

路线 - 设置

resources :users, shallow: true do
    scope module: :users do
      resources :identities
      resources :settings do 
        namespace :contacts do
          resources :addresses
          resources :phones 
        end
      end 
    end
  end 

组织形式

<%= f.simple_fields_for :addresses do |f| %>
      <%= f.error_notification %>
        <%= render 'contacts/addresses/address_fields', f: f %>

    <% end %> 
      <%= link_to_add_association 'Add another address', f, :addresses, partial: 'contacts/addresses/address_fields' %> 

用户/设置表单

<%= simple_form_for [@user, @setting] do |f| %>
  <%= f.error_notification %>

    <%= simple_fields_for :addresses do |f| %>
            <%= f.error_notification %>
                <%= render 'contacts/addresses/address_fields', f: f %>
            <% end %>       
            <%= link_to_add_association 'Manage address', f, :addresses, partial: 'contacts/addresses/address_fields' %>    

  </div>
<% end %>  

关于我的地址功能的一切都适用于组织,但我在让它适用于我的设置时遇到了问题。

当我尝试使用用户/设置表单添加地址时遇到的问题是我收到一条错误消息:

ActionController::RoutingError at /contacts/addresses/1/edit
uninitialized constant Users::Contacts

用户和联系人之间没有直接关联。 Contacts 是我用来存储地址视图和控制器的命名空间文件夹的名称。

谁能看到我需要做什么才能从我的用户设置表单中访问地址表单功能?

rake routes 进行设置时,可以看到获取设置地址的路径格式,但不知道如何使用。

rake routes | grep setting
           setting_contacts_addresses GET      /settings/:setting_id/contacts/addresses(.:format)                      users/contacts/addresses#index
                                      POST     /settings/:setting_id/contacts/addresses(.:format)                      users/contacts/addresses#create
         new_setting_contacts_address GET      /settings/:setting_id/contacts/addresses/new(.:format)                  users/contacts/addresses#new

设置控制器

class Users::SettingsController < ApplicationController
    before_action :set_setting, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!
  after_action :verify_authorized

  def index
    @settings = Setting.all
    authorize @settings

  end

  def show
    # authorize @setting

    @addresses = @setting.addresses.all

    @phones = @setting.phones

  end


  def new
    @setting = Setting.new
    @setting.addresses_build 
    @setting.phones_build
    authorize @setting

  end

  def edit
     @setting.addresses_build unless @setting.addresses
     @setting.phones_build unless @setting.phones

  end

  def create
    @setting = Setting.new(setting_params)
    authorize @setting

    respond_to do |format|
      if @setting.save
        format.html { redirect_to @setting }
        format.json { render :show, status: :created, location: @setting }
      else
        format.html { render :new }
        format.json { render json: @setting.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
   respond_to do |format|
      if @setting.update(setting_params)
        format.html { redirect_to @setting }
        format.json { render :show, status: :ok, location: @setting }
      else
        format.html { render :edit }
        format.json { render json: @setting.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @setting.destroy
    respond_to do |format|
      format.html { redirect_to settings_url }
      format.json { head :no_content }
    end
  end


  private
    # Use callbacks to share common setup or constraints between actions.
    def set_setting
      @setting = Setting.find(params[:id])
      authorize @setting
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def setting_params
      params.require(:setting).permit( :newsletter,
        addresses_attributes: [:id, :description, :unit, :building, :street_number, :street, :city, :region, :zip, :country, :time_zone, :latitude, :longitude, :_destroy],
        phones_attributes: [:phone_number,  :country, :phone_type],

       )
    end

end

组织管理者

class OrganisationsController < ApplicationController
  before_action :set_organisation, only: [:show, :edit, :update, :destroy]

  def index
    @organisations = Organisation.all
    authorize @organisations
  end

  def show
    @addresses = @organisation.addresses.all

    # @hash = Gmaps4rails.build_markers(@addresses) do |address, marker|
    #     marker.lat address.latitude
    #     marker.lng address.longitude
    #     marker.infowindow address.full_address
    # end
    @bips = @organisation.bips
    @proposals = @organisation.proposals#.in_state(:publish_openly)    
  end

  def new
    @organisation = Organisation.new
    @organisation.addresses#_build
  end

  def edit
    @organisation.addresses_build unless @organisation.addresses
  end

  def create
    @organisation = Organisation.new(organisation_params)

    respond_to do |format|
      if @organisation.save
        format.html { redirect_to @organisation, notice: 'Organisation was successfully created.' }
        format.json { render :show, status: :created, location: @organisation }
      else
        format.html { render :new }
        format.json { render json: @organisation.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @organisation.update(organisation_params)
        format.html { redirect_to @organisation, notice: 'Organisation was successfully updated.' }
        format.json { render :show, status: :ok, location: @organisation }
      else
        format.html { render :edit }
        format.json { render json: @organisation.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @organisation.destroy
    respond_to do |format|
      format.html { redirect_to organisations_url, notice: 'Organisation was successfully destroyed.' }
      format.json { head :no_content }
    end
  end




private
    # Use callbacks to share common setup or constraints between actions.
    def set_organisation
      @organisation = Organisation.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def organisation_params
      params.fetch(:organisation, {}).permit(:title, :comment,
        addresses_attributes:   [:id, :description, :unit, :building, :street_number, :street, :city, :region, :zip, :country, :time_zone, :latitude, :longitude, :_destroy],
        phones_attributes:      [:id, :phone_number,  :country, :phone_type, :_destroy]
        )
    end


end

【问题讨论】:

    标签: ruby-on-rails routes namespaces nested associations


    【解决方案1】:

    我不太明白你想要完成什么。下面的这些代码允许您为用户创建新设置。您可以向该设置添加更多地址。如果要编辑地址名称,必须进入该地址所属设置的编辑页面。

    routes.rb

    resources :users, shallow: true do
      scope module: :users do
        resources :settings
      end
    end
    

    users/settings_controller.rb

    class Users::SettingsController < ApplicationController
      before_action :prepare_user, only: [:index, :new, :create]
      before_action :prepare_setting, only: [:show, :edit, :update]
    
      def new
        @setting = Setting.new
      end
    
      def create
        @setting = @user.build_setting(setting_params)
        if @setting.save
          redirect_to @setting
        else
          render 'new'
        end
      end
    
      def show
      end
    
      def edit
      end
    
      def update
        if @setting.update(setting_params)
          redirect_to @setting
        else
          render 'edit'
        end
      end
    
      private
    
      def prepare_user
        @user = User.find(params[:user_id])
      end
    
      def prepare_setting
        @setting = Setting.find(params[:id])
      end
    
      def setting_params
        params.require(:setting).permit(:name, addresses_attributes: [:name, :id])
      end
    end
    

    用户/设置/new.html.erb

    <h1>New Setting</h1>
    <%= render 'form' %>
    

    用户/设置/_form.html.erb

    <%= simple_form_for [@user, @setting] do |f| %>
      <%= f.input :name %>
      <div>
        <%= f.simple_fields_for :addresses do |f| %>
          <%= f.error_notification %>
            <%= render 'contacts/addresses/address_fields', f: f %>
        <% end %>
        <%= link_to_add_association 'Add another address', f, :addresses, partial: 'contacts/addresses/address_fields' %>
      </div>
      <%= f.submit %>
    <% end %>
    

    联系人/地址/address_fields.html.erb

    <%= f.input :name, label: 'Address name' %>
    <%= f.input :id, as: :hidden %>
    

    【讨论】:

    • 您认为应该在 [] 中添加什么内容?这是否意味着我还需要为范围内的设置声明指定某些操作?
    • 一个空的 [] 就可以了。设置的所有路由都在scope module: :users 内的第一个resoures :settings 中定义。第二个resources :settings只是为addressesphone定义嵌套资源,不在users命名空间下
    • 我试过了,还是一样的错误:未初始化常量Users::Contacts
    • 现在我得到这个错误:未定义的局部变量或方法 `edit_contacts_address_path'
    • 现在错误提示:缺少部分联系人/地址/_form,application/_form with {:locale=>[:en], :formats=>[:html], :variants=>[] , :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder]}。搜索:
    猜你喜欢
    • 2017-03-21
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    相关资源
    最近更新 更多