如何同时在rails中的两个表中插入数据?

时间:2017-12-08 11:27:35

标签: ruby-on-rails ruby devise omniauth

我正在尝试从最近2天找出这个问题,但直到现在都无济于事。我正在使用rails中的omniauth,我已经在我的网站中集成了omniauth身份验证,但我想为所有提供者创建单独的表。我有两个表1:用户和其他是auth_provider 1:用户将包含用户数据 2:auth_provder将包含带有社交媒体提供商身份验证详细信息的user_id。

我已经创建了从用户到auth_providers的has_many关联。

现在我想在两个表中插入数据,以便首先在用户表中创建包含一些字段的条目,然后它应该采用新插入的记录条目并将此id与其他数据一起插入到auth_providers表中。我知道这件事是可能的,但我找不到任何示例或代码。我只是在过去2天搜索和尝试,但仍然没有成功。我想使用关联来做它,我也使用了nested_attributes,但仍然没有成功。

这是我的代码

用户模型:

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable,
    :omniauthable, :omniauth_providers => [:facebook,:twitter,:linkedin]
  has_many :organizations_users
  has_many :auth_providers
  has_many :organizations, through: :organizations_users
  accepts_nested_attributes_for :auth_providers
    def active_for_authentication?
    # Uncomment the below debug statement to view the properties of the returned self model values.
    super && self.active && self.exp_alert == false
  end

  def self.from_omniauth(auth)
    exist = where(email: auth.info.email).first
    if exist
      existing_user = exist["id"]
      Auth_provider.where(provider: auth.provider, social_uid: auth.uid).first_or_create do |auth_provider|
      auth_provider.provider =  auth.provider
      auth_provider.social_uid = auth.uid
      auth_provider.social_token = auth.credentials.token
      auth_provider.user_id = existing_user
      end
    else
      #@organization.users.create(first_name:params[:first_name])
      names = auth.info.name.strip.split(" ")
      first_name = names[0]
      last_name = names[1]

      params = { user: {
    email: 'abc@abc.com', auth_providers_attributes: [
    { provider: 'facebook' },
    { social_token: 'asfasf2342432' },
    { social_uid: 'asfdaf23242'} # this will be ignored
    ]
  }}
user = User.create(params[:user])    

              end
  end

  def self.new_with_session(params, session)
    super.tap do |user|
      if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
        user.email = data["email"] if user.email.blank?
      end
    end
  end

  def self.find_or_create_from_auth_hash(auth_hash)
    user = where(provider: auth_hash.provider, uid: auth_hash.uid).first_or_create do |user|
      user.first_name =  auth_hash.info.nickname
      user.active = 'true'
      user.admin=='false'
      user.exp_alert = 'false'
      user.password = Devise.friendly_token[0,20]
      user.token =  auth_hash.credentials.token
      user.email =  auth_hash.info.email
      user.secret =  auth_hash.credentials.secret
      user.skip_confirmation!
    end
    user
  end

  def self.linkedin_hash(auth_hash)
    user = where(provider: auth_hash.provider, uid: auth_hash.uid).first_or_create do |user|
      user.first_name =  auth_hash.info.first_name
      user.last_name =  auth_hash.info.last_name
      user.active = 'true'
      user.admin = 'false'
      user.exp_alert = 'false'
      user.password = Devise.friendly_token[0,20]
      user.token =  auth_hash.credentials.token
      user.email =  auth_hash.info.email
      user.skip_confirmation!
    end
    user
  end

  def inactive_message
    "Your Account has not been active yet."
  end

  def after_confirmation
    super
    self.update_attribute(:active, true)
  end
end

auth_providers模型

class Auth_provider < ApplicationRecord
devise :database_authenticatable
belongs_to :user

 accepts_nested_attributes_for :user
end

来自facebook的回复是

#<OmniAuth::AuthHash credentials=#<OmniAuth::AuthHash expires=true expires_at=1517924507 token="EAAdDsC4F0CCLq95eo81qfaMVVs0zeNgqtRqUF9ufZB3gK609NY3aiikJ9AvE8zSB63WFcG0E6NBFNIWf00DjgHNlsQHCd2D26uxJ1ongQ5YBJZCeuZAOas2SEYlRwPYhctfiEVVdbadOyA3QeL50JHIA5dKa3xdfK5Efw9Y"> extra=#<OmniAuth::AuthHash raw_info=#<OmniAuth::AuthHash email="testing@gmail.com" id="35232364989259" name="John">> info=#<OmniAuth::AuthHash::InfoHash email="testing@gmail.com" image="http://graph.facebook.com/v2.6/35489/picture" name="John"> provider="facebook" uid="354814524989259">

1 个答案:

答案 0 :(得分:1)

如果我理解你,你能做点什么:

...
user = User.create(the_user_attributes)
user.auth_providers.create(the_auth_provider_attributes)
...

这应该有效,创建一个用户,然后是属于他们的身份验证提供者。

如果您需要在保存之前稍微操作一下,也可以使用User.newuser.auth_providers.build,并且当您在用户上调用save时,它们将被保留。

<强>更新

要将代码拆分为可读块,我建议如下:

<强> user.rb

# update: you're in the user model, so no need to specify the model again in the line below
user = create(user_attributes_from_auth(auth))
user.auth_providers.create(provider_attributes_from_auth(auth))

private

def user_attributes_from_auth(auth)
  { first_name: auth.info.nickname,
    token: auth_hash.credentials.token,
    etc: etc }
end

def provider_attributes_from_auth(auth)
  { a_similar_approach_as: user_attributes_from_auth }
end

因此,简而言之,您使用^^中的前两行从属性哈希创建用户,然后为auth提供程序执行相同操作。

这很好看且可读,而且实际上并不是你现在所做的。快来看看你的成功 - 希望它有所帮助!