Rails 4 - 嵌套表单(多对多)

时间:2015-05-20 11:21:51

标签: ruby-on-rails ruby forms

我有以下架构:

attribute
----------
id
name

profile
----------
user_id
attribute_id
value

user
----------
id
name

我要做的是显示所有属性,然后对于用户在配置文件中填充的任何属性,可以执行更新。我的背景不是红宝石,但我可能会在迁移应用程序之前测试这个框架以获得概念验证。

我已经在rubyonrails.org(约会示例)上的指南中映射了这样的关联

class Attribute < ActiveRecord::Base
    has_many :profiles
    has_many :users, through: :profiles
end

class Profile < ActiveRecord::Base
    belongs_to :attribute
    belongs_to :user
end

class User < ActiveRecord::Base
    has_many :profiles
    has_many :attributes, through: :profiles

    accepts_nested_attributes_for :profiles
end

我采用了嵌套表单的方法,但即使设置了accepts_nested_attributes_for,也无法通过模型。

<%= form_for(@user) do |f| %>
     <% Attribute.all.each do |attribute| %>
            <div>
                <%= attribute.name %>
            </div>
            <div>
                <%= f.fields_for :profiles do |upp| %>
                    <%= upp.hidden_field :user_id, :value => @user.id %>
                    <%= upp.hidden_field :attribute_id, :value => @attribute.id %>
                    <%= upp.text_field :value %>
                <% end %>
            </div>
    <% end %>
    <div>
    <%= f.submit %>
    </div>
<% end %>

e.g

Attributes
A
B
C

用户具有属性A

A ["hello world"]
B [             ]
C [             ]

属性是动态的,因此如果添加2个新属性,也会显示D和E

A ["hello world"]
B [             ]
C [             ]
D [             ]
E [             ]

如何正确设置此表单以便将其作为保存模型传递?我认为json会像

profile_attributes { [user_id:1 attribute_id:1 value:'hello world'], [user_id:1 attribute_id:2 value:''] }

我知道上面的表单设置不太正确,但这只是我尝试查看它渲染内容的几次尝试之一。

我试过了:

<%= f.fields_for @user.profiles do |pp| %>
<% end %>

我甚至尝试手动将字段设置为数组(类似于asp.net mvc):

id=user[profiles][user_id]
id=user[profiles][attribute_id]

控制器(他们此刻是空壳,我只是想在控制台中看到json输出)

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end
end

class ProfileController < ApplicationController
    def edit
        @user = User.find(params[:id])
    end

    def update
        respond_to do |format|
         @user = User.find(params[:id])
    end

    private
        def user_params
            params.require(:user).permit(profiles_attributes: [:user_id, :attribute_id, :value])
        end
  end
end

我尝试了很多不同的方法但没有成功。有时表单显示具有相同值的重复字段,有时显示表单但值为空,提交时抱怨未允许的参数,但它已在控制器中设置。

当然以上所有都可以使用javascript完成,但我想看看是否可以使用模型方法并嵌套它。

1 个答案:

答案 0 :(得分:0)

你可以这样做:

将表单移至 users / edit.html.erb 并修改您的users_controller,如下所示

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  def edit
    @user.profiles.build
  end


  def update
     if @user.update(user_params)
       #redirect user where you want
     end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    def user_params
      #permit user attributes along with profile attributes
    end

 end