Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I handle edit and update action when I use Form Object?

I have following form object to managing complicated nested form.

Form

= simple_form_for(@profile_form, :url => profiles_path) do |f|
  ...

Routes

resources :profiles

Controller

class ProfilesController < ApplicationController
  def new
    @profile_form = ProfileForm.new
  end

  def edit
    @profile_form = ProfileForm.new(params[:id])
  end

  def create
    @profile_form = ProfileForm.new
    if @profile_form.submit(params[:profile_form])
      redirect_to @profile_form.profile, notice: 'Profile was successfully created.'
    else
      render action: "new"
    end
  end

  def update
    @profile_form = ProfileForm.new(params[:id])
    if @profile_form.submit(params[:profile_form])
      redirect_to @profile_form.profile, notice: 'Profile was successfully updated.'
    else
      render action: "edit"
    end
  end
end

Form Object

class ProfileForm
  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming

  def initialize(profile_id = nil)
    if profile_id
      @profile = Profile.find(profile_id)
      @person = profile.person
    end
  end
  ...
  def submit(params)
    profile.attributes = params.slice(:available_at)
    person.attributes = params.slice(:first_name, :last_name)

    if valid?
      profile.save!
      person.save!
      true
    else
      false
    end
  end
  def self.model_name
    ActiveModel::Name.new(self, nil, "Profile")
  end

  def persisted?
    false
  end
end

But right now when I'm editing object using this form create action is called. How should then I refactor this form? Code below on update creates another Profile object.

like image 336
tomekfranek Avatar asked Jun 12 '13 11:06

tomekfranek


1 Answers

simple_form_for uses form_for internally to do its job. form_for uses the method persisted? to decide if the object is already persisted on the database or not. If it is already persisted form_for will generate a form with method PUT to update the object, otherwise it will generate a form with method POST to create the new object. Therefore you have to implement the persisted? method for you form object. You could implement it like this:

class ProfileForm
  # ...
  def persisted?
    @person.persisted? && @profile.persisted?
  end
  # ...
end

Update In the case @person is nil, i.e. there's no Person associated to the Profile, I suppose you would create a new Person to associate to the @profile. In this case it is safe to assume that a ProfileForm is persisted? as long as at least the @profile is persisted?, thus:

class ProfileForm
  # ...
  def persisted?
    @profile.persisted?
  end
  # ...
end

Update To avoid the error undefined local variable or method `id' you have to define the id method for ProfileForm, like this:

class ProfileForm
  # ...
  def id
    @profile.id
  end
  # ...
end
like image 125
toro2k Avatar answered Oct 16 '22 05:10

toro2k