Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

assigning and reusing variables in Rails - design pattern

I've been using the same pattern for returning json code (see example below). I'm getting a collection of photos and storing it in the variable. If tag param is present, I'm getting a more specific collection and reassigning it to the same variable. Then returning it as json. What would be a better design pattern to achieve the same thing?

photos = collection_of_photos
if params[:tag]
 photos = photos.find_all {|photo| some condition}
end
render json: photos
like image 498
Tammy Pop Avatar asked Jul 08 '16 19:07

Tammy Pop


1 Answers

If the photos are ActiveRecord objects you should use a scope to generate the appropriate query for the exact data you need. Otherwise, Rails will load all of the photos instead of the subset you need. Assuming your photos records have a single tag attribute, you can do something like the following:

class Photo < ApplicationRecord
  scope :with_tag, (tag) -> { where(tag: tag) }
end

In your controller you'd only need the call that scope since ActiveRecord scopes return an #all scope if no parameters are provided:

render json: Photo.with_tag(params[:tag])

# Equivalent when params[:tag] is nil
render json: Photo.all

Now say you're not dealing with ActiveRecord objects. Say you have an array of hashes:

photos = [{ name: '1.jpg', tag: 'flower'}, ... ]

You can create a helper method to perform the filtering:

class PhotosController < ApplicationController
  def index
    photos = [{ name: '1.jpg', tag: 'flower'}, ... ]
    render json: select_photos_by_tag(photos, params[:tag])
  end

  private

  def select_photos_by_tag(photos, tag)
    if tag
      photos.select { |photo| photo[:tag] == tag }
    else
      photos
    end
  end
end
like image 188
fny Avatar answered Sep 16 '22 13:09

fny