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_client
是 nil
。
如何使 @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 newton
和 def einstein
(等)来干掉你的方法。与其静态定义这些方法,不如使用单一方法来删除重复代码:即 def new_potential_client
,当然还有 def create_potential_client
操作。在这些操作中,您通过传递 params[:id]
来确定 location
是 newton
还是 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
我对 rails 比较陌生,我正在为一家商店写一个网站,我有一个 locations_controller
用于多个商店位置,我还有一个 potentialClients_controller
用于当人们填写表格,使用他们的姓名、电子邮件等请求更多信息。
通过我的 locations_controller
我有每个位置的多个视图,在位置的视图中,我想包含一个访问 potentialClients_controller
.
这是通过关系还是其他方式完成的?下面的视图抛出 First argument in form cannot contain nil or be empty
错误,因为在此视图中,@potential_client
是 nil
。
如何使 @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 newton
和def einstein
(等)来干掉你的方法。与其静态定义这些方法,不如使用单一方法来删除重复代码:即def new_potential_client
,当然还有def create_potential_client
操作。在这些操作中,您通过传递params[:id]
来确定location
是newton
还是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