Mejor manera de construir la asociación has_one o actualizar si existe

My discount class has a sales_period. I want to write a method which can build this association when it does not exist, or updates it when it does exist. Currently I am writing the following if condition.

class Discount < ActiveRecord::Base
  has_one :sales_period

  def fetch_period
    end_date = ...
    if sales_period.nil?
      build_sales_period( end: end_date )
    else
      sales_period.end = end_date
    end
  end
end

Is there a better way to do this, similar to find_or_create?

preguntado el 01 de febrero de 12 a las 03:02

2 Respuestas

Not quite what you're looking for but you can shorten it slightly.

def fetch_period
  end_date = ...
  period = sales_period || build_sales_period
  period.end = end_date
end

Respondido 01 Feb 12, 07:02

thanks, it is marginally better and I think that's the best one can do. - lulalala

Yeah, it depends what the fetch_period method actually does but I'd consider moving that one line of logic to it's own method if you're using it in multiple places - Sacerdote Bradley

find_or_initialize es parecido a first_or_initialize. Ex:

def fetch_period
  end_date = ...
  sales_period.find_or_initialize_by_end(end_date)
end

Also, I'd rename end, it's a ruby keyword. You'll probably get some weird bug when something tries to eval the code or some such, and it'll be super confusing.

Respondido 01 Feb 12, 07:02

it seems that when end_date changes, if sales_period already exists, instead it will create a new record and leave an orphaned sales_period. i.e. it does not update existing sales period end date - lulalala

You're right, I mis-read what you're trying to do. I'd say something like Bradley's answer is correct. - Woahdae

Tal vez sales_period.find_or_create_by_discount_id(id).update_attributes(end: end_date) - Woahdae

I think only pitfall of this is that it will not work on unsaved discounts / I can't build a period. I will stick with my original answer. - lulalala

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.