【问题标题】:How to insert data into two tables in rails at the same time?如何将数据同时插入到rails中的两个表中?
【发布时间】:2017-12-08 11:27:35
【问题描述】:

我从过去 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">

【问题讨论】:

  • 你会先从任何控制器创建用户吗?

标签: ruby-on-rails ruby devise omniauth


【解决方案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

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

这很好并且可读,并且实际上与您当前正在做的事情相差不远。试一试,看看你的进展如何 - 希望对你有所帮助!

【讨论】:

  • 感谢您的回答。我已经注释掉了代码,因为我不确定它的语法,因为假设我有 10 个要插入的字段我想在用户中插入 5 个,在 auth_providers 中插入 5 个,但我不知道如何使用 users.auth_providers.create () 你能帮帮我吗?
  • 您是否有可以添加到答案中的auth 响应示例?把一些东西放在一起会很方便:)我现在会用更多信息更新我的答案!
  • 你的意思是omniauth回调控制器代码?实际上我想在一个电话中完成我的任务,这就是我对此很小心的原因。
  • 不——只是作为auth 传递给from_omniauth 方法的内容(即来自提供者的响应)。
  • 你在做两个单独的呼叫兄弟。我需要一个调用来保存数据库 user = create(user_attributes_from_auth(auth)) user.auth_providers.create(provider_attributes_from_auth(auth)) 此代码首先创建用户然后创建 auth_provider。这段代码有什么特别之处?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
  • 1970-01-01
  • 2017-11-13
  • 1970-01-01
  • 1970-01-01
  • 2013-07-21
相关资源
最近更新 更多