接受has_one未填充的嵌套属性表单

时间:2015-07-09 17:42:40

标签: ruby-on-rails nested-forms nested-attributes has-one

我创建了一个Preference模型来管理电子邮件设置。现在,嵌套表单没有显示在实际页面上。我尝试了一系列不同的策略,但无法弄清楚。

我确定我在本地设置了首选项,将fields_for更改为(@ user.preference),但没有工作等等。

我使用的是Rails 4.2.2,Ruby 2.2.1版。

模式

  create_table "preferences", force: :cascade do |t|
    t.datetime "created_at",                    null: false
    t.datetime "updated_at",                    null: false
    t.integer  "user_id",                       null: false
    t.boolean  "new_match",      default: true, null: false
    t.boolean  "accepted_match", default: true, null: false
    t.boolean  "match_reminder", default: true, null: false
    t.boolean  "new_message",    default: true, null: false
  end

用户模型

  has_one :preference, dependent: :destroy
  accepts_nested_attributes_for :preference

偏好模型

class Preference < ActiveRecord::Base
  belongs_to :user
end

包含嵌套表单部分内容的实际表单:

<%= form_for(@user, id: "editing-info") do |f| %>
  <ul class="tabs">
    <li class="tab-link current" data-tab="tab-account">
      <%= t("edit_user.tabs.account") %>
    </li>
    <li class="tab-link" data-tab="tab-interests">
      <%= t("edit_user.tabs.interests") %>
    </li>
    <li class="tab-link" data-tab="tab-settings">
      <%= t("edit_user.tabs.settings") %>
    </li>
  </ul>

  <div class="tab-content current" id="tab-account">
    <%= render "users/tabs/account", f: f %>
  </div>  

  <div class="tab-content" id="tab-interests">
    <%= render "users/tabs/interests", f: f %>
  </div>

  <div class="tab-content" id="tab-settings">
    <%= render "users/tabs/settings", f: f %>
  </div>

  <div id="button-container">
    <%= link_to 'Cancel',
      user_path(current_user),
      data: { disable_with: "Loading..." },
      class: "cancel-desktop" %>

    <%= f.submit "Save",
      data: { disable_with: "Loading..." },
      class: "save main-save-button-edit" %>
  </div>
<% end %>

包含嵌套表单的部分

<div id="settings">
  <h4 class="notifications-label">Notifications</h4>
  <div class="notifications setting-category info-holder">
    <div class="mobile setting-holder">
      <%= f.label :mobile, "Mobile", class: "setting-label" %>
      <%= f.text_area :mobile, placeholder: "Add mobile number", class: "setting-input" %>
    </div>
    <div class="email-holder setting-holder main-email-edit">
      <%= f.label :email, "Email", class: "setting-label" %>
      <%= f.text_area :email, placeholder: "Add email address", class: "setting-input" %>
    </div>
    <p class="setting-descrip">This email is where Glassbreakers notifications will be sent. Please continue to use your email associated with your LinkedIn account to sign in.</p>
  </div>
  <h4 class="email-label">Emails</h4>
  <%= f.fields_for :preference do |user_preference| %>
    <div class="email-notifications-holder">
      <div class="email-holder">
        <%= user_preference.label :new_match, "Getting a new match each week" %>
        <%= user_preference.check_box :new_match, class: "checkbox new_match_email" %>
      </div>
      <div class="email-holder">
        <%= user_preference.label :match_reminder, "New matches Thursday reminder", class: "match_reminder_email" %>
        <%= user_preference.check_box :match_reminder, class: "checkbox thursday_reminder_email"   %>
      </div>
      <div class="email-holder">
        <%= user_preference.label :accepted_match, "A Glassbreakers accepted a match", class: "accepted_match_email" %>
        <%= user_preference.check_box :accepted_match, class: "checkbox accept_match_email"   %>
      </div>
      <div class="email-holder">
        <%= user_preference.label :new_message, "Received a new message" %>
        <%= user_preference.check_box :new_message, class: "checkbox new_message_email"  %>
      </div>
    </div>
  <% end %>
  <h4 class="connect-label">Connections</h4>
  <div class="connections info-holder">
    <p class="inform">You'll receive new matches every Tuesday. Make sure to respond to your matches before then.</p>
    <div class="pausing">
      <label><%= t("edit_user.settings.pausing_header") %></label>
      <%= react_component(
        "MatchingPausedSetting",
        {
          matchingPaused: current_user.matching_paused?,
          pauseMatchingURL: user_matching_pauses_path(current_user)
        }
      ) %>
    </div>
    <p class="setting-descrip pause-descrip">Pausing connections means you will not receive new potential connections each week. You will be able to send and receive new messages.</p>
  </div>
  <h4 class="contact-label">Contact</h4>
  <div id="contact-info" class="info-holder">
    <p class="inform">Have a question?  We love hearing from you. Contact Courtney, our communication manager, at <a href="mailto:info@glassbreakers.co" target="_top">info@glassbreakers.co</a>.</p>
  </div>
</div>

与user_params相关的用户控制器

  def user_params
    filtered_params = params.require(:user).permit(
      :email,
      :mobile,
      :bio_because,
      :bio_meet,
      :description,
      :github_link,
      :linkedin_link,
      :title,
      :twitter_link,
      preference_attributes: [
        :id,
        :new_match,
        :accepted_match,
        :match_reminder,
        :new_message,
      ],
      user_onboard_skills_attributes: [
        :skill_id,
        :industry_id,
        :years_experience,
        :id,
        :_destroy,
      ],
      interest_ids: [],
    )

    filtered_params[:user_onboard_skills_attributes] =
      filter_user_onboard_skills_attributes(
        filtered_params[:user_onboard_skills_attributes]
      )

    filtered_params
  end

2 个答案:

答案 0 :(得分:1)

如果你的嵌套表单实际上在用户表单中,那么调整你的fields_for声明就可以了:

<%= f.fields_for @user.preference do |preference_fields| %>

另请注意,我从preference_fields将块变量重命名为f,因为您的父表单似乎已使用f

文档对此方法有很好的解释,应该回答任何其他问题:

fields_for documentation

为后代编辑:

由于您的用户模型没有关联的偏好模型,因此字段未正确显示,可以通过手动将偏好模型与用户关联或使用类似于此问题中找到的策略来修复: Rails: Create association if none is found to avoid nil errors。在模型级别进行预警,以确保在创建新用户时创建关联。

答案 1 :(得分:0)

使用&f;#39;您无法获得用户和偏好设置的两个字段。 您需要使用

获取fields_for首选项
 <%= f.fields_for :preference do |user_preference| %>

,对于首选项字段,您将使用user_preference