Rails 3.2 create a form that's used in the foo

2019-02-21 02:23发布

问题:

I want to create a form that's used to sign up to a mailing list in the footer of my webpage. What I did was create a partial that renders this small form in the footer of the application layout.

Here is the code for the partial:

<%= form_for(@mailing_list) do |f| %>
  <% if @mailing_list.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@mailing_list.errors.count, "error") %> prohibited this mailing_list from being saved:</h2>

      <ul>
      <% @mailing_list.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :first_name %><br />
    <%= f.text_field :first_name %>
  </div>
  <div class="field">
    <%= f.label :last_name %><br />
    <%= f.text_field :last_name %>
  </div>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.text_field :email %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

I'm still learning rails so that's generated code from scaffolding. From what I gather I need to instantiate the @mailing_list variable with @mailing_list = MailingList.new but the problem here is that NEW action in the mailing list controller doesn't get called because I'm not necessarily visiting that page. This form is in the footer of every page.

What would be the proper way to create this form? Is there a way to do this without calling MailingList.new in every controller?

Thanks!

回答1:

change your form to this

<%= form_for MailingList.new, html: { remote: true } do |f| %>

so you don't have to worry about instance variables. You should also pass remote: true so the form is submitted via ajax. To show error, create a file called create.js.erb under app/views/mailing_lists and add the following (just a simple script that appends the errors before the form)

$('.error-messages').remove();
<% if @mailist_list.errors.any? %>
  $('#new_mailing_list').before('<ul class="error-messages"></ul>');
  <%= @mailing_list.errors.full_messages.each do |msg| %>
    $('.error-messages').append('<li><%= escape_javascript msg %></li>');  
  <% end %>
<% end %>


回答2:

You can change your form_for method to this:

<%= form_for :mailing_list, url: mailing_lists_path do |f| %>

Then you no longer need to initialize @mailing_list for every page.

The caveat is that you cannot render the errors in the footer. You would need to create a new.html.erb view using the code in the question, that can be rendered if there are any errors when saving in the create action.