Tintin81
Tintin81

Reputation: 10207

How to combine create and update actions in Rails?

In my Rails 4 app I have this controller:

class InvoicesController < ApplicationController

  ...

  def create
    @invoice = current_user.invoices.build(invoice_params)
    @invoice.build_sender(current_user.profile.sender_fields) # <= !
    if @invoice.save
      flash[:success] = "Invoice created."
      redirect_to invoices_path
    else
      render :new
    end
  end

  def update
    if @invoice.update_attributes(invoice_params)    
      @invoice.sender.update_attributes(current_user.profile.sender_fields) # <= !
      flash[:success] = "Invoice updated."     
      redirect_to invoices_path
    else
      render :edit
    end
  end

  ...

end

Basically, what it does it when an invoice gets created, it also creates an associated sender record containing essentially the invoice's letterhead data, such as company name, address, etc.

When an invoice gets updated, its associated sender record gets updated as well.

I just wonder if this can be combined inside the model using a filter or a function like create_or_update() or something similar?

Thanks for any help.

Upvotes: 3

Views: 2143

Answers (3)

MrYoshiji
MrYoshiji

Reputation: 54882

This kind of constraint:

Create/update an associated object B on each create/update of Model A

Should be held by the Model A. If tomorrow you need another page to create instances of Model A, you will not have to do the same logic in the two controller's actions because Model A is responsible for the creation of associated instance(s) of Model B.


So, in your case, you can combine an after_create and an after_save in your Invoice model:

after_create :create_or_update_sender
after_update :create_or_update_sender

def create_or_update_sender
  local_sender = (self.sender || self.build_sender)
  local_sender.update_attributes(self.user.profile.sender_fields)
  local_sender.save!
end

Upvotes: 3

errata
errata

Reputation: 26792

You are probably looking for first_or_create.update

Comment.where(user_id: 6).first_or_create.update(content: 'lorem ipsum')

Upvotes: 0

sansarp
sansarp

Reputation: 1466

Yes, one way is to try using action params like this:

def create_or_update()
  if params[:action].eql?('create')
    #code for save action
  elsif params[:action].eql?('update')
    #code for update action
  end
end

Upvotes: -1

Related Questions