RAILS - 更改另一个字段 TABLE - 布尔值

RAILS - CHANGE FIELD OF ANOTHER TABLE - BOOLEAN

下午好。我是 rails 的新手,我在这里使用 google 翻译成英语的 post,如果可读性不是很好,请见谅。

我的问题是,我有一个用户 table 和一个设置 table。

他们有关系(但我不知道关系是否正确),他们甚至可以确认我,我想知道是否: 创建用户时,我想自动将该用户设置 table 的“电子邮件”和“推送”字段更改为 true。 是否可以通过用户模型中称为“setting_default”的方法实现?

class User < ApplicationRecord
   has_one :setting

   before_save :setting_default

   def setting_default
     self.setting.update(:email, 'true')
     self.setting.update(:push, 'true')
   end
class Setting < ApplicationRecord
   has_one :user
end

Controller是正常的,如果你需要,我可以放在post

我的迁移:

class CreateSettings < ActiveRecord::Migration[6.0]
  def change
    create_table :settings do |t|
      t.boolean :email, default: true
      t.boolean :push, default: true

      t.timestamps
    end
  end
end


class AddSettingsToUser < ActiveRecord::Migration[6.0]
  def change
    add_reference :users, :setting, null: true, foreign_key: true
  end
end

Google 翻译在这里很适合你。

首先,您需要将 Setting 模型更改为属于 User:

class Setting < ApplicationRecord
   belongs_to :user
end

您的 settings 数据库 table 缺少一个 user_id 字段来将设置与用户联系起来。我不习惯 add_reference 技术,所以我只是在迁移中自己做一些事情。这会起作用:

class CreateSettings < ActiveRecord::Migration[6.0]
  def change
    create_table :settings do |t|
      t.integer :user_id

      t.boolean :email, default: true
      t.boolean :push, default: true

      t.timestamps
    end
  end
end

(请注意,您的 users 数据库 table 有一个不需要的字段 setting_id。我认为它不应该在那里。我会删除它。除非是 Rails6 我不习惯的东西。)

接下来,如果保存成功(而不是失败则不分配)可能会更好,因此您需要一个 after_save。我正在简化您的赋值,以防您遇到问题:

class User < ApplicationRecord
   has_one :setting

   after_save :setting_default

   def setting_default
     setting.email = true
     setting.push = true
     setting.save(validate: false)
   end
   private :setting_default

要回答您的问题,是的,您尝试做的事情应该很容易实现。这是一件很常见的事情。它应该有效。

当你使用one-to-one关联时,你需要在一个模型中选择has_one,在另一个模型中选择belongs_to

语义上用户有一个设置,但没有设置有一个用户

所以倒过来比较好

要更改架构,您需要编写新的迁移

class ChangeOneToOneDirection < ActiveRecord::Migration[6.0]
  def up
    change_table :settings do |t|
      t.belongs_to :user, foreign_key: true, null: false
    end

    User.where.not(setting_id: nil).find_each |user|
      Setting.find(user.setting_id).update_columns(user_id: user.id)
    end

    change_table :users do |t|
      t.remove :setting_id
    end
  end

  def down
    add_reference :users, :setting, null: true, foreign_key: true

    Setting.find_each do |setting|
      User.find(setting.user_id).update_columns(setting_id: setting.id)
    end

    change_table :settings do |t|
      t.remove :user_id
    end
  end
end

迁移后您可以更改用户模型

class User < ApplicationRecord
  has_one :setting

  after_commit :setting_default

  private

  def setting_default
    setting&.update(email: true, push: true)
  end
end

最好仅在数据库中保存时更新关联模型。并且用户可以没有设置。这就是为什么 after_commit 和 safe-navigator &