0

I have a model which has an image field managed by paperclip:

class Meal < ActiveRecord::Base
  has_attached_file :image, :default_url => "/images/normal/missing.png",
                :styles => { :medium => "612x612", :small => "300x300" },
                :path => ":rails_root/public/system/:attachment/:id/:style/:filename",
                :url => "/system/:attachment/:id/:style/:filename"

I can access the different sizes like this:

    meals.each do |n|
      n.image.url(:small) # gives url for small images
      puts n.image.url # returns url for original images, I want this to return small for this function
    end

I am rendering the meals in JSON using render :json.

My question is, how can I pass the small image URLs into my meals variable (in my controller below)? I want to be able to return small image URLs as I tried doing above, except return it when my response renders (see below).

UPDATE:

In my controller:

def view_patient
  response = Response.new
  this_doctor = Doctor.find_by_remember_token(Doctor.digest(auth_params["remember_token"]))
  if this_doctor
    this_patient = this_doctor.users.find_by_id(params[:id])
      if this_patient
        meals = this_patient.meals
        #
        # Here should be code on how to set the meals.image.url to small
        glucoses = this_patient.glucoses
        response.data = { :patient => this_patient,  :meals => meals }
        response.code = true
      else
        response.error = "Could not find patient"
        response.code = false
      end
  else
    response.error = "Please Login"
    response.code = false
  end
  render :json => response.json
end
achabacha322
  • 651
  • 10
  • 32

1 Answers1

1

TLDR

# inside meal.rb

def as_json(options=nil)
  super( (options || {}).merge({ 
    :methods => [:small_url]
  }))
end

def small_url
  self.image.url(:small)
end

You can then access the URL in your JSON structure

JSON.parse(meal.to_json)['small_url']

Explanation

When a ActiveModel is serialized through to_json the method as_json is first invoked on the object to separate the actual construction of the JSON data structure from the rendering. This data structure (a hash really) is then encoded as a JSON string through ActiveSupport.

So in orde to customize the object we wish to display as JSON we need to override the as_json method of that object - which is well documented. As per the documentation, the methods key for the options hash simply invokes the methods listed in the array passed as the value (in our case just small_url) and creates a key in the hash to be JSON encoded, with the value of the method invocation.

For an even more detailed explanation, please see this excellent answer.

Community
  • 1
  • 1
nicohvi
  • 2,270
  • 2
  • 28
  • 42
  • niceeee, sounds like this is exactly what I need. I'm a noob, and the explanation was on point. And nice link to the other question. Will accept when I get a chance to fire this up – achabacha322 Oct 01 '14 at 12:34
  • hey @nicohvi , I'm rendering my response with other variables as well, any idea how to store my response with the small urls as opposed to the original? See updated code. Thanks! – achabacha322 Oct 02 '14 at 21:18
  • 1
    I should think it already does. What do you see when you inspect the `response` JSON object's meals array? I believe the individual meals in that array should all have the attribute `small_url`. – nicohvi Oct 03 '14 at 06:49
  • Thanks you da man, I was missing something in my code, my fault – achabacha322 Oct 04 '14 at 00:58