ruby-on-rails - 无法修改关联 'User#roles',因为源反射类 'Role' 通过 :has_many 关联到 'Profile'

标签 ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-4

我有三个模型,一个用户,一个个人资料和一个角色,我试图通过个人资料角色附加到用户强>.

# user.rb
class User < ActiveRecord::Base
  has_one :profile, dependent: :destroy
  has_many :roles, through: :profile
  has_many :interests, through: :profile
  has_many :industries, through: :profile
end

# profile.rb
class Profile < ActiveRecord::Base
  has_one :user, dependent: :destroy
  has_many :roles
  has_many :interests
  has_many :industries
end

# role.rb
class Role < ActiveRecord::Base
  has_many :profiles
  has_many :users, :through => :profiles
  has_many :users
end

我正在尝试在 edit.html.erb (simple_form_for)

中使用以下内容
<%= f.association :roles,
                   as: :check_boxes,
                   label_method: :name,
                   value_method: :id,
                   label: 'Roles' %>

使用以下参数

params.require(:user).permit([:email, :first_name, :last_name, :admin, :password, role_ids: [] ])

我的编辑/更新方法:

  # GET /users/1/edit
  def edit
    @user.build_profile if @user.profile.nil?
  end

  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

给我以下错误信息

Cannot modify association 'User#roles' because the source reflection class 'Role' is associated to 'Profile' via :has_many.

我已经研究了这个问题几个小时了,但我似乎找不到错误。

最佳答案

您定义关系的方式存在几个问题。

has_one 将外键放在关系的反面。因此,如果您在两端都声明了与 has_one 的关系,ActiveRecord 将无法加载该关联。相反,您需要在带有外键的一侧使用 belongs_to:

# user.rb
class User < ActiveRecord::Base
  has_one :profile, dependent: :destroy
end

# profile.rb
class Profile < ActiveRecord::Base
  belongs_to :user, dependent: :destroy
end

当涉及到用户和角色时,您在两边都声明了 has_many,但没有告诉 ActiveRecord 在哪里存储关系。在双向多对多关系中,您需要使用 has_many through: 和连接模型或 has_and_belongs_to_many

通常在构建基于角色的访问系统时,您希望定义关系,以便角色 belongs_to 单个用户而不是具有单个 Admin 角色,例如许多用户。这允许您将角色限定在资源范围内,并使添加/删除角色的逻辑变得更加简单(您是在用户中添加(或删除)角色,而不是在角色中添加或删除用户。)

如果您正在验证/授权您不想使用 has_many :roles, through: :profiles 的 User 模型 - 三方连接会慢得多并增加不必要的复杂性和间接。

如果您真的需要一个“配置文件”表,那么将它用于有关用户的辅助信息,并在需要时加入它。

class User < ActiveRecord::Base
  has_many :roles, 
  has_one :profile, dependent: :destroy
end

# Columns:
# - user_id [integer, index, foreign key]
# - resource_id [integer, index]
# - resource_type [string, index]
class Role < ActiveRecord::Base
  belongs_to :user, dependent: :destroy
  belongs_to :resource, polymorphic: true, 
                        dependent: :destroy
end

# Columns:
# - user_id [integer, index, foreign key]
class Profile < ActiveRecord::Base
  belongs_to :user
  # this is option but can be useful
  has_many :roles, through: :user
end

我真的建议您先阅读官方 rails guides article on associations .

关于ruby-on-rails - 无法修改关联 'User#roles',因为源反射类 'Role' 通过 :has_many 关联到 'Profile',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35534490/

相关文章:

ruby-on-rails - 来自数据库和 image_tag 的 Erb

ruby-on-rails - 如何在生产模式下修复 Rails 的布线错误?

ruby-on-rails - 发布到创建方法会导致 session Controller 测试 (RSpec) 出错

ruby-on-rails - 运行 "bundle install"失败,让我运行 "bundle install"

ruby-on-rails - Rails/Postgresql SQL 与日期的差异

ruby - Rails 中的类变量在浏览器刷新时持续存在

ruby-on-rails - Rails 3.2 - #<Array :. 的未定义方法 `where' .. - Model.where() 的查询

ruby-on-rails - 今天 ruby 约会? - 意外行为

javascript - 根据条件从 Rails Controller 调用 jquery 函数

Ruby VM 并发性和并行性