【问题标题】:Rails nested attributes and has_many :through associations not showing fields_forRails嵌套属性和has_many:通过关联不显示fields_for
【发布时间】:2015-01-18 06:11:33
【问题描述】:

这是我的模型:

class Company < ActiveRecord::Base

  has_many :roles, :dependent => :destroy, :inverse_of => :user
  has_many :users, :through => :roles
  validates :name, presence: true

end

class User < ActiveRecord::Base

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  has_many :roles, :dependent => :destroy, :inverse_of => :user
  has_many :companies, :through => :roles
  accepts_nested_attributes_for :roles, :limit => 1, :allow_destroy => true

end

class Role < ActiveRecord::Base

  belongs_to :user, :inverse_of => :roles
  belongs_to :company, :inverse_of => :roles

  #accepts_nested_attributes_for :companies, :limit => 1, :allow_destroy => true
  accepts_nested_attributes_for :company

end

这里的想法是公司是独一无二的,用户可以通过一个角色与多个公司相关联。我在 User 模型上设置了用于身份验证和注册的设计。效果很好,我可以注册为新用户。

我想在注册过程中添加公司名称。我正在尝试嵌套形式:

<%= form_for(resource, :html => {:class => "form-signin" }, as: resource_name, url: registration_path(resource_name)) do |f| %>
    <%= render partial: "shared/flash" %>
    <%= devise_error_messages! %>
    <h1 class="form-signin-heading text-muted">Register</h1>
    <%= f.email_field :email, class: "form-control", placeholder: "Email", autofocus: true %>
    <%= f.password_field :password, class: "form-control", placeholder: "Password", autocomplete: "off" %>
    <%= f.password_field :password_confirmation, class: "form-control", placeholder: "Password Confirmation", autocomplete: "off" %>

    <%= f.fields_for :roles do |r| %>
    <%= r.fields_for :company do |c| %>
          <%= c.text_field :name, class: "form-control", placeholder: "Company", autocomplete: "off" %>
    <% end %>
    <% end %>
    <button class="btn btn-lg btn-primary btn-block" type="submit">
        Register
    </button>
<% end %>

我发现了一些其他 SA 答案,指出需要通过关联以及一些单/复数问题通过 has_many 向下钻取 accepts_nested_attributes_for。修复这些后,我的表单加载没有错误,除了 fields_for 块是空的。

现在我承认我的模型可能是这里的问题。我从几年前开发的应用程序中复制了代码,所以我不知道为什么要这样做。

最后,我想在用户注册时创建公司和角色。我计划将角色的创建添加到公司控制器,但我至少需要先创建公司。

更新

我做了更多的挖掘并将我的表单更新为:

    <% company = resource.companies.build %>
    <%= f.fields_for :company, company do |c| %>
          <%= c.text_field :name, class: "form-control", placeholder: "Company", autocomplete: "off" %>
    <% end %>

我意识到我的 Devise 控制器没有构建嵌套的 Company 资源。我想远离定制的设计控制器。我的表单提交并创建了我的用户,但由于公司和角色没有得到保存,我仍然在这里遗漏了一些东西。

【问题讨论】:

    标签: devise nested-forms nested-attributes


    【解决方案1】:

    经过一些挖掘和实验,我是如何解决这个问题的:

    模型

    class User < ActiveRecord::Base
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, :validatable
      has_many :roles, :dependent => :destroy, :inverse_of => :user
      has_many :companies, :through => :roles
      accepts_nested_attributes_for :roles, :limit => 1, :allow_destroy => true
    
    end
    
    class Role < ActiveRecord::Base
      belongs_to :user, :inverse_of => :roles
      belongs_to :company, :inverse_of => :roles
      accepts_nested_attributes_for :company
    end
    
    class Company < ActiveRecord::Base
      has_many :roles, :dependent => :destroy, :inverse_of => :user
      has_many :users, :through => :roles
      validates :name, presence: true
    end
    

    自定义设计注册控制器

    class RegistrationsController < Devise::RegistrationsController
    
        # GET /resource/sign_up
      def new
        build_resource({})
        @role = resource.roles.build(role: "owner", active: 1, default_role: 1)
        @company = @role.build_company
        set_minimum_password_length
        yield resource if block_given?
        respond_with self.resource
      end
    
      protected
    
      def sign_up_params
          params.require(:user).permit(:email, :password, :password_confirmation, roles_attributes: [ company_attributes: [ :id, :name ] ] )
      end
    
    end
    

    HTML

    <%= form_for(resource, :html => {:class => "form-signin" }, as: resource_name, url: registration_path(resource_name)) do |f| %>
        <%= render partial: "shared/flash" %>
        <%= devise_error_messages! %>
        <h1 class="form-signin-heading text-muted">Register</h1>
        <%= f.email_field :email, class: "form-control", placeholder: "Email", autofocus: true %>
        <%= f.password_field :password, class: "form-control", placeholder: "Password", autocomplete: "off" %>
        <%= f.password_field :password_confirmation, class: "form-control", placeholder: "Password Confirmation", autocomplete: "off" %>
    
        <%= f.fields_for :roles, resource.roles.build do |r| %>
        <%= r.fields_for :company, resource.roles.build.build_company do |c| %>
              <%= c.text_field :name, class: "form-control", placeholder: "Company", autocomplete: "off" %>
        <% end %>
        <% end %>
    
        <button class="btn btn-lg btn-primary btn-block" type="submit">
            Register
        </button>
    <% end %>
    

    我认为我把模型和关联搞砸了。现在form_for 工作起来很神奇。

    我将发布另一个单独的问题,但我仍然无法弄清楚是:

    • 为什么我在控制器中设置的@role 和@company 在视图HTML 中起作用?
    • 如何设置其他角色属性?我在控制器和视图的构建阶段都尝试过,但没有成功。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-25
      • 1970-01-01
      • 1970-01-01
      • 2018-02-28
      • 1970-01-01
      • 2018-04-23
      • 1970-01-01
      相关资源
      最近更新 更多