【问题标题】:Rails 5.1 add a specific column as foreign keyRails 5.1 添加特定列作为外键
【发布时间】:2018-01-31 15:05:17
【问题描述】:

我的外键有问题。
我有 3 个表:用户、成员和组。
基本上我希望用户能够创建组。用户提供名称、描述并在创建时生成令牌。然后其他用户可以通过成员表加入这个组。 members 表有 user_id 和 group_id。用户可以加入提供 group_id 的组,这不是很酷,我希望用户加入提供令牌的组。
除了他们可以加入令牌之外,一切正常。我的问题是如何使用令牌而不是 group_id ?

我已经尝试过像这样添加外键,但架构中没有发生任何事情:

add_foreign_key :members, :groups, column: :group_id, primary_key: :auth_token

add_foreign_key :members, :groups, column: :auth_token, primary_key: :auth_token

我也尝试在我的模型中添加外键:

belongs_to :group, foreign_key: "group_auth_token"

has_many :members, foreign_key: "group_auth_token", class_name: "Group"

这是我的实际模型以防万一:

组.rb

class Group < ApplicationRecord
has_secure_token :auth_token

    has_many :members, :dependent => :destroy
    has_many :users, :through => :members

end

用户.rb

class User < ApplicationRecord

    has_secure_password

  has_many :members, :dependent => :destroy
  has_many :groups, :through => :members
end

会员.rb

class Member < ApplicationRecord

  belongs_to :user
  belongs_to :group

  validates :user_id, :presence => true
  validates :group_id, :presence => true
  validates :user_id, :uniqueness => {:scope => [:user_id, :group_id]}

end

我真的对这一切感到困惑,我很确定答案很明显,但我只是迷路了,有人可以帮助我吗?
谢谢

编辑:看起来还不够清楚,所以我要添加一些内容。当用户创建组时,这就是我的控制器中发生的事情:

def create
    @group = Group.new group_params
    @group.owner_id = current_user.id if current_user
    if @group.save
      @user = current_user.id if current_user
      Member.create(group_id: "#{@group.id}", user_id: "#{@user}")
      flash[:success] = "The Group has been created."
      redirect_to group_path(@group)
    else
      render 'new'
    end
  end

Member.create 是在组中自动添加用户。如果有人想加入一个组,这就是我的成员控制器中发生的事情:

def create
        @member = Member.new member_params
        @member.user_id = current_user.id if current_user
        if @member.save
            flash[:success] = "You Joined the Group."
            redirect_to mygroups_path
        else
            flash.now[:error] = "Something went wrong. Are you in the group already ?"
            render 'new'
        end
    end

当然还有一个表单来创建一个新成员(加入组),用户在控制器中提供 group_id (member_params)。

我希望能够使用令牌而不是 group_id。

编辑 2:

所以我对你的代码 jvillian 有一个错误。我将它粘贴到 MembersController 中。在我的表单中,我将 :group_id 更改为 :auth_token ,这是我的表单:

<%= form_for @member do |f| %>
    <%= f.label :auth_token %>
    <%= f.text_field :auth_token %>
    <%= f.submit "Join the Group" %>
<% end %>

【问题讨论】:

  • 你是什么意思'加入提供令牌的组'?你的意思是在用户界面中?如果是这样,则 UI 和记录关联的机制在很大程度上是不相关的。按令牌查找组,然后正常关联。还是我误会了?
  • 在 UI 中是。创建组后,其他用户可以通过在成员表中创建记录来加入组。我做了一个表单,用户提供 group_id 和 user_id 来自控制器中的当前用户,因此他们不必在表单中提供它。而不是这个 group_id 我希望用户能够使用令牌。基本上不相关是什么意思?
  • 如果您在问题中添加将用户与组关联的(可能是控制器)代码,那么我可以告诉您我的意思。
  • 我刚刚编辑了帖子
  • 已发布答案。如果您有任何问题,请告诉我。

标签: ruby-on-rails database model foreign-keys ruby-on-rails-5


【解决方案1】:

这段代码可能完全不正确,但它应该是正确的方向。

def create
  if @group = Group.find_by(auth_token: params[:auth_token]) && current_user
    if @group.users << current_user
      flash[:success] = "You Joined the Group."
      redirect_to mygroups_path
    else
      flash.now[:error] = "Something went wrong. Are you in the group already ?"
      render 'new'
    end
  end
end

我输入:

params[:token]

当然,这可能不太正确。调整以适合您自己的参数。

这一点:

if @group.users << current_user

可能不正确,因为我忘记了铲子运算符返回的内容。但是,您可以在 the guide 中查找。

更正您的表格

大概,你正在做类似的事情:

class MembersController < ApplicationController

  def new
    @member = Member.new
  end

  ...

end

所以,当你这样做时:

<%= form_for @member do |f| %>
  <%= f.label :auth_token %>
  <%= f.text_field :auth_token %>
  <%= f.submit "Join the Group" %>
<% end %>

form_for 可以访问您的@member 实例。

但是,当你这样做时:

<%= f.text_field :auth_token %>

您收到错误是因为form_for 试图访问@member 上的.auth_token 属性,该属性自然不存在。但请记住,您在这里要做的只是提交一个带有令牌的表单。因此,请改为:

<%= form_for @member do |f| %>
  <%= label_tag 'auth_token', 'Token' %>
  <%= text_field_tag 'auth_token' %>
  <%= f.submit "Join the Group" %>
<% end %>

通过这种方式,auth_token 字段不再直接派生自 @member,并且您不再尝试访问 @member 上不存在的方法。

你的参数看起来像:

Parameters: {"auth_token"=>"whatever the user entered"}

如果您希望 auth_token 嵌套在 group 中,如下所示:

Parameters: {"group"=>{"auth_token"=>"whatever the user entered"}}

然后做:

<%= form_for @member do |f| %>
  <%= label_tag 'group[auth_token]', 'Token' %>
  <%= text_field_tag 'group[auth_token]' %>
  <%= f.submit "Join the Group" %>
<% end %>

【讨论】:

  • 我有undefined method auth_token' 用于#<0xf457860>
  • &amp;&amp;
【解决方案2】:

您的文字有点混乱,但也许这种参考设置正是您要寻找的?

add_reference :members, :group_auth_token, foreign_key: { to_table: :groups }, references: :auth_token 

【讨论】:

  • 可以,我测试一下,我回来了
  • 我测试了我现在的架构中有这个:t.integer "group_auth_token_id"t.index ["group_auth_token_id"], name: "index_members_on_group_auth_token_id"。我是否必须像我在主题中所写的那样更改模型?谢谢你的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 2018-03-31
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
相关资源
最近更新 更多