Search code examples
ruby-on-railsruby

RAILS - CHANGE FIELD OF ANOTHER TABLE - BOOLEAN


Good afternoon. I'm new to rails and I'm using google translate to post in English here, so sorry if it's not very readable.

My question is, I have a User table, and a Setting table.

They are related (but I don't know if the relationship is correct), they can even confirm me, and I would like to know if: when creating a user, I would like to automatically change the "email" and "push" fields of that user's settings table to true. Would it be possible via a method that in the user model called: "setting_default"?

  • User model.
class User < ApplicationRecord
   has_one :setting

   before_save :setting_default

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

The Controller is normal, if you need it, I can put it in the post

My migration:

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

database-setting-user


Solution

  • Google translate has worked well for you here.

    First off you'll want to change your Setting model to belong to the User:

    class Setting < ApplicationRecord
       belongs_to :user
    end
    

    Your settings DB table is missing a user_id field to tie the setting back to the user. I'm not used to the add_reference technique so I just do things myself in the migrations. This would work:

    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
    

    (Make note that your users DB table has a field setting_id that it does not need. I don't think it should be there. I would remove it. Unless it's a Rails 6 thing I'm not used to.)

    Next it would probably be better to assign the values if the save succeeds (and not if it fails) so you'll want an after_save instead. And I'm simplifying your value assignment just in case you're having an issue there:

    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
    

    And to answer what seems to be your question, yes, what you're trying to do should be easily possible. This is a very common thing to do. It should work.