Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActiveRecord find_or_build_by

I would like to perform:

    XXX.find_or_build_by_language_id(attributes)

I found

    XXX.find_or_initialize_by_language_id(attributes)

but that only set language_id and no other attributes. Even if I manually sets the attributes, the record is not saved when I perform XXX.save.

I just read Rails - find or create - is there a find or build?, which seems related to my problem but does not fit my needs.

Edit

Let's use this scenario

# db/migrations/create_models.rb
class CreateModels < ActiveRecord::Migration
  def self.up
    create_table :companies do |t|
      t.string :name
    end

    create_table :employees do |t|
      t.string :name
      t.string :city
      t.references :company
    end
  end
end

-

# app/models/employee.rb
class Employee < ActiveRecord::Base
  belongs_to :company
end

-

# app/models/company.rb
class Company < ActiveRecord::Base
  has_many :employees
end

-

# rails console
:001> c = Company.new
 => #<Company id: nil, name: nil> 
:002> c.employees
 => []
:003> e = c.employees.find_or_initialize_by_name(:name => 'foo', :city => 'bar')
 => #<Employee id: nil, name: "foo", city: "bar", company_id: nil>
:004> c.employees
 => []
:005> c.save
 => true
:006> c.employees
 => []
:007> e.save
 => true
:008> c = Company.first
 => #<Company id: 1, name: nil>
:009> c.employees
 => [#<Employee id: 1, name: "foo", city: "bar", company_id: 1>]
:010> e = c.employees.find_or_initialize_by_name(:name => 'foo', :city => 'baz')
 => #<Employee id: 1, name: "foo", city: "bar", company_id: 1> 
:011> e.city = 'baz'
 => "baz"
:012> c.employees
 => [#<Employee id: 1, name: "foo", city: "bar", company_id: 1>] 
:013 > c.save
 => true 
:014> c.employees
 => [#<Employee id: 1, name: "foo", city: "bar", company_id: 1>]

Problems

  1. :004 => The Employee from :003 is not added to c.employees
  2. :006 => The Employee from :003 is saved with c
  3. :010 => The city attribute of employee is not set
  4. :014 => THe city attribute of employee is not updated when saving company
like image 229
ybart Avatar asked Jul 26 '11 16:07

ybart


1 Answers

How about this?

employee_attrs = {:name => 'foo', :city => 'bar'}
e = c.employees.where(employee_attrs).first || c.employees.build(employee_attrs)
like image 109
Zubin Avatar answered Oct 19 '22 21:10

Zubin