Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Delegate Set Value

I have a User.rb model and a UserSetting.rb model that i would like to delegate to (both getter and setter methods).

in user.rb

delegate :email_opt_in, :email_opt_in=, :to => :user_setting

At first glance this works great.

user = User.find(1)
user.email_opt_in #=> false
user.email_opt_in = true
user.save
user.email_opt_in #=> true

But looking closer the, user.save doesn't propagate to the UserSetting model.

User.find(1).email_opt_in #=> false

(So the value didn't get saved to the database).

This is my question: How can I get UserSetting to save automatically when one of its attributes are changed and then saved by its user?

This should only happen when a UserSetting attribute is changed otherwise every time a user is saved to the database it will trigger an additional un-needed & unwanted write to the database.

like image 485
Schneems Avatar asked Sep 16 '11 20:09

Schneems


People also ask

How does delegate work in Rails?

On the Profile side we use the delegate method to pass any class methods to the User model that we want access from our User model inside our Profile model. The delegate method allows you to optionally pass allow_nil and a prefix as well. Ultimately this allows us to query for data in custom ways.

How does delegate work in Ruby?

Delegation can be done explicitly, by passing the sending object to the receiving object, which can be done in any object-oriented language; or implicitly, by the member lookup rules of the language, which requires language support for the feature.

What is Simpledelegator?

A concrete implementation of Delegator , this class provides the means to delegate all supported method calls to the object passed into the constructor and even to change the object being delegated to at a later time with #__setobj__. class User def born_on Date.


2 Answers

In your User model for user_setting association use autosave: true

class User < ActiveRecord::Base
  has_one :user_setting, autosave: true

  delegate :email_opt_in, :email_opt_in=, :to => :user_setting
end
like image 116
Edgars Kaukis Avatar answered Oct 15 '22 15:10

Edgars Kaukis


I would explore using an ActiveRecord callback for this. I'm not sure which would make the most sense in your case, but before_update or after_update seem logical. In your callback, you would need to manually trigger a save call on the UserSetting object associated with the User. There's probably dozens of ways to accomplish this, but something along these lines should work:

class User < ActiveRecord::Base
  after_update do |user|
    user.user_setting.save if user.user_setting.changed?
  end
end
like image 22
Peter Brown Avatar answered Oct 15 '22 17:10

Peter Brown