iwasrobbed
iwasrobbed

Reputation: 46703

Refactoring: How to efficiently render json in Rails update action

How can I refactor this code so I don't repeat the json objects over and over again when they use the same basic format? I'm still a bit uncomfortable with Ruby on Rails so I'm unsure of the best way to approach this.

  # PUT /users/:user_id/profile/:id
  def update
    if request.xhr?
      profile = current_user.profile

      if params[:profile].blank?
        render :json => { :error => "There was no profile data passed in so your profile could not be saved." }, 
               :status => :unprocessable_entity
      else
        if profile.update_attributes(params[:profile])
          render :json => { :interests => 
                              simple_format(h(profile.interests), :class => "pbs tl"),
                            :favorite_music =>
                              simple_format(h(profile.favorite_music), :class => "pbs tl"),
                            :favorite_movies =>
                              simple_format(h(profile.favorite_movies), :class => "pbs tl"),
                            :favorite_books =>
                              simple_format(h(profile.favorite_books), :class => "pbs tl"),
                            :favorite_foods =>
                              simple_format(h(profile.favorite_foods), :class => "pbs tl") },
                 :status => :ok
        else
          render :json => { :error => get_errors_for_class(profile).to_sentence }, 
                 :status => :unprocessable_entity
        end
      end
    end
  end

Update: I modified the original answer a little and it works for me. Here's my modification:

  # within profile.rb
  # create a hash of profile attributes
  def html_to_hash
    %w{interests favorite_music favorite_books favorite_foods}.inject({}) do |hash, property|
      hash[property] = simple_format(h(self.send(property)), :class => 'pbs tl')
      hash
    end    
  end

Upvotes: 1

Views: 4710

Answers (2)

lobati
lobati

Reputation: 10215

You can create an as_json method on your Profile class that returns the same hash and then just do render :json => profile. Another alternative is to plug in ActiveModel::Serializers and tell it which attributes you want to serialize and how.

Upvotes: 0

Jamie Wong
Jamie Wong

Reputation: 18350

Make the data in that huge hash a method of Profile.

class Profile
  def to_hash
    [:interests, :favorite_music, :favorite_books, :favorite_foods].inject({}) do |h, prop|
      h[prop] = simple_format(h(self.send(:prop)), :class => 'pbs tl')
      h
    end
  end
end

then

# PUT /users/:user_id/profile/:id
  def update
    if request.xhr?
      profile = current_user.profile

      if params[:profile].blank?
        render :json => { :error => "There was no profile data passed in so your profile could not be saved." }, 
               :status => :unprocessable_entity
      else
        if profile.update_attributes(params[:profile])
          render :json => profile.to_hash,
                 :status => :ok
        else
          render :json => { :error => get_errors_for_class(profile).to_sentence }, 
                 :status => :unprocessable_entity
        end
      end
    end
  end

Upvotes: 3

Related Questions