Rails 4:从另一个控制器的视图访问模型

Rails 4: Access model from another controller's view

我对 rails 比较陌生,我正在为一家商店写一个网站,我有一个 locations_controller 用于多个商店位置,我还有一个 potentialClients_controller 用于当人们填写表格,使用他们的姓名、电子邮件等请求更多信息。

通过我的 locations_controller 我有每个位置的多个视图,在位置的视图中,我想包含一个访问 potentialClients_controller.

的表单

这是通过关系还是其他方式完成的?下面的视图抛出 First argument in form cannot contain nil or be empty 错误,因为在此视图中,@potential_clientnil

如何使 @potential_client 易于访问?

locations/Newton.html.erb

<div class="main-content">
    <h1>Newton, MA</h1>
    <div class="wrapper">
        <div class="form-container">
            <%= form_for @potential_client do |f| %>

                <%= f.label :name %>
                <%= f.text_field :name %><br />

                <%= f.label :email %>
                <%= f.email_field :email %><br />

                <%= f.label :phone %>
                <%= f.number_field :phone %><br />

                <%= f.label :message %>
                <%= f.text_field :message %><br />

                <%= f.submit "Submit" %>

            <% end %>
        </div>
    </div>
</div>

Jeremy,你试过这个吗? <%= form_for @potential_client do |f| %> 并在控制器操作中设置 @potential_client = PotentialClient.new

可能遗漏了一些东西,但似乎是最直接的方法。

假设:

  • 您有一个型号 potential_client.rb,其代码为:

    class PotentialClient < ActiveRecord::Base
      belongs_to :location
      # ..
      # ..
    end
    
  • 您有一个型号 location.rb,其代码为:

    class Location < ActiveRecord::Base
      has_many :potential_clients
      # ..
      # ..
    end
    

解法:

locations_controller.rb

class LocationsController < ApplicationController
   def newton
     @location = Location.find(1) # if your location with id=1 is newton
     # or if you are using an attribute to identify the location, i.e. name, then uncomment the following instead, and remove the line above
     # @location = Location.find_by(name: 'newton')
   end
end

locations/newton.html.erb

<div class="main-content">
    <h1>Newton, MA</h1>
    <div class="wrapper">
        <div class="form-container">
            <%= form_for @location.potential_clients.build do |f| %>

                <%= f.label :name %>
                <%= f.text_field :name %><br />

                <%= f.label :email %>
                <%= f.email_field :email %><br />
                <%= f.label :phone %>
                <%= f.number_field :phone %><br />

                <%= f.label :message %>
                <%= f.text_field :message %><br />

                <%= f.submit "Submit" %>

            <% end %>
        </div>
    </div>
</div>

推荐方案:

  • potentialClients_controller 重命名为 potential_clients_controller
  • locations_controller.rb

    LocationsController < ApplicationController
    
      def newton
        @location = Location.find(1) # if your location with id=1 is newton
        @potential_client = @location.potential_clients.build
      end
    
      # i.e.
      def einstein
        @location = Location.find(2) # if your location with id=2 is einstein
        @potential_client = @location.potential_clients.build
      end
    
      # ..
      # ..
    end
    
  • locations/newton.html.erb

    <div class="main-content">
        <h1>Newton, MA</h1>
        <div class="wrapper">
            <div class="form-container">
                <%= form_for @potential_client do |f| %>
    
                    <%= f.label :name %>
                    <%= f.text_field :name %><br />
    
                    <%= f.label :email %>
                    <%= f.email_field :email %><br />
    
                    <%= f.label :phone %>
                    <%= f.number_field :phone %><br />
    
                    <%= f.label :message %>
                    <%= f.text_field :message %><br />
    
                    <%= f.submit "Submit" %>
    
                <% end %>
            </div>
        </div>
    </div>
    

更好的推荐方案:

  • 通过删除 locations_controller 中的 def newtondef einstein(等)来干掉你的方法。与其静态定义这些方法,不如使用单一方法来删除重复代码:即 def new_potential_client,当然还有 def create_potential_client 操作。在这些操作中,您通过传递 params[:id] 来确定 locationnewton 还是 einstein。 IE。你的 url 可能类似于 /locations/9876/new_potential_client

  • 与上面那行相同,但您可能需要 /locations/newton/new_potential_client 而不是 /locations/9876/new_potential_client。然后,你需要鼻涕虫。我用的一个gem是friendly_id

最佳推荐方案:

  • 使用具有 RESTful 实现的浅嵌套资源路由。更多信息 HERE
  • 如果您使用浅嵌套资源路由,您的 url 将类似于 /locations/9876/potential_clients/new
  • 或者如果使用 friendly_id slug 名称,url 将类似于 /locations/newton/potential_clients/new