【问题标题】:Rails 4: Access model from another controller's viewRails 4:从另一个控制器的视图访问模型
【发布时间】:2016-02-01 21:27:12
【问题描述】:

我对 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>

【问题讨论】:

  • 您可以尝试传入 Potential_client.new 或任何您的模型名称。
  • 这不起作用,因为它正在寻找locations_controller中的方法

标签: ruby-on-rails forms associations rails-activerecord


【解决方案1】:

假设:

  • 你有一个模型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。您的网址可能类似于/locations/9876/new_potential_client

  • 与上一行相同,但您可能需要/locations/newton/new_potential_client 而不是/locations/9876/new_potential_client。然后,您将需要蛞蝓。我使用的一颗宝石是friendly_id

最佳推荐解决方案:

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

【讨论】:

  • 感谢您的详尽回答!我将努力使推荐的解决方案发挥作用,但现在我在使用您的解决方案时收到以下错误:NoMethodError in LocationsController#newtonundefined method 'potential_clients' for nil:NilClass
  • @JeremyThomas,您尝试了导致该错误的Recommended Solution?还是只是Solution?如果仅使用简单的Solution,而您遇到了该错误,则意味着在locations/newton.html.erb 中,@location 为 Nil / Nothing / No Value。您需要确保在您的locations_controller#newton 中,@location 将具有值
  • 我更新了答案的Solution 部分,明确添加了locations_controller.rb 中的内容
  • 非常感谢!我将尝试按照您的指示以更好的方式完成此任务,但当前的解决方案有效!
  • 还有一个问题.. 如果我使用表单创建一个potential_client,并且我的模型有一个location_id 字段来链接到该位置,我如何从我的@ 中访问location_id 987654363@?
【解决方案2】:

杰里米,你试过这个吗? <%= form_for @potential_client do |f| %> 并在控制器动作集中@potential_client = PotentialClient.new

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

【讨论】:

  • 是的,我试过了。在我的potentialClients_controller 我有@potential_client = PotentialClient.new,但这个视图正在我的locations_controller 中查看,这就是它没有找到它的原因。在我的位置模型中我添加了has_many :potential_clients,在我的潜在客户模型中我添加了belongs_to :location,但仍然没有运气
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多