简体   繁体   中英

Rails 4: Access model from another controller's view

I am relatively new to rails and am writing a website for a store where I have a locations_controller for the multiple store locations and I also have a potentialClients_controller for when people fill out a form, requesting more information using their name, email, etc.

Through my locations_controller I have several views for each location, and in the location's view, I want to include a form that accesses the potentialClients_controller .

Is this done through relationships or some other way? The view below throws First argument in form cannot contain nil or be empty error because in this view, @potential_client is nil .

How do I make @potential_client accessible?

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>

Assumptions:

  • You have a model potential_client.rb having a code:

     class PotentialClient < ActiveRecord::Base belongs_to :location # .. # .. end 
  • You have a model location.rb having a code:

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

Solution:

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>

Recommended Solution:

  • rename potentialClients_controller to 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 # ie 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> 

Better Recommended Solution:

  • DRY up you methods by removing def newton and def einstein (etc) in your locations_controller . Instead of these methods that are statically defined, it is better to use a single method to remove duplicate code: ie def new_potential_client and also of course the def create_potential_client actions. In these actions, you identify if the location is newton or einstein by passing the params[:id] . IE your url might be something like /locations/9876/new_potential_client

  • Same as the line just above, but instead of /locations/9876/new_potential_client , you might want /locations/newton/new_potential_client instead. Then, you would need slugs for this. One gem I use is friendly_id

Best Recommended Solution:

  • Use Shallow-Nested Resource Routing having RESTful implementation. More info HERE
  • If you use Shallow-Nested Resource Routing, your url would look something like /locations/9876/potential_clients/new
  • Or if using friendly_id slug names, url will look like /locations/newton/potential_clients/new

Jeremy, have you tried this? <%= form_for @potential_client do |f| %> <%= form_for @potential_client do |f| %> and in the controller action set @potential_client = PotentialClient.new

Might be missing something but seems to be the most straightforward way to do this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM