Rails 5.1将特定列添加为外键

时间:2018-01-31 15:05:18

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

我的外键有问题 我有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"

以下是我的实际模型:

Group.rb

class Group < ApplicationRecord
has_secure_token :auth_token

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

end

User.rb

class User < ApplicationRecord

    has_secure_password

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

Member.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 %>

2 个答案:

答案 0 :(得分:2)

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

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正试图访问.auth_token@member的{​​{1}}属性,当然,该<%= 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 %>

然后做:

{{1}}

答案 1 :(得分:0)

您的文字令人困惑,但也许这些参考设置是您正在寻找的?

// Return the value in the array which starts with
// `e2etest` then extract the string after the colon `:`
const argument = process.argv.filter(arg => {
  return arg.match(/^e2etest:.*/);
}).toString().split(':').pop();

if (argument === 'user') {
  // Run `user` specific tests here...
} else if (argument === 'session') {
  // Run `session` specific tests here...
}