Tintin81
Tintin81

Reputation: 10207

How to use update_all on has_one relation in Rails 4?

In my Rails app I have a User class:

class User < ActiveRecord::Base

  has_one :profile
  has_one :sorting

  has_many :people
  has_many :companies
  has_many :projects
  has_many :invoices
  has_many :payments

  ...

  def move_to(user)
    associations = %w(companies people projects invoices payments)
    associations.each do |a|      
      send(a).update_all(:user_id => user.id)
    end
    %w(profile sorting).each do |a|
      send(a).update_column(:user_id, user.id) # would like to use update_all here but not working
    end
  end

end

Is there a way to clean up my move_to method, so that I can run update_all on has_one relations as well?

Upvotes: 0

Views: 1997

Answers (3)

khiav reoy
khiav reoy

Reputation: 1403

You could use association_scope to get the ActiveRecord::Relation object on has_one relation:

%i[profile sorting].each do |a|
  association(a).association_scope.update_all(:user_id => user.id)
end

Upvotes: 0

AndyV
AndyV

Reputation: 3741

You can pass a block when declaring an association.

class User < ActiveRecord::Base
  has_one :profile do
    def update_all(attributes={})
      update_column(attributes) unless attributes.empty?
    end
  end
end

You may be able to reduce this with a concern so that you only need to write it once. However, this seems like a very long way to go simply to reduce two loops to one.

Upvotes: 0

spas
spas

Reputation: 1934

You could use the relations instead of associations:

def move_to(user)
  relations = [Profile, Sorting, Invoice, ...]
  relations.each do |relation|      
    relation.where(user_id: self.id).update_all(:user_id => user.id)
  end
end

But this would be dangerous if you have additional conditions on your associations.

Upvotes: 2

Related Questions