y.bregey
y.bregey

Reputation: 1499

How to refactor ActiveRecord query?

I have a code in controller:

def latest
  @latest_articles = user_signed_in? ? Article.limit(10).order(id: :desc).pluck(:id, :title) : Article.where("status = ?", Article.statuses[:public_article]).limit(10).order(id: :desc).pluck(:id, :title)
  render json: @latest_articles
end

How to refactor it to looks elegant? I tried using lambda:

extract = lambda {|a| a.order(id: :desc).pluck(:id, :title)}
Article.limit(10) {|a| a.extract}

but it returns only Article.limit(10)

UPD: I need to get last 10 of all articles if user is signed in, and last 10 of only public ones if not.

Upvotes: 3

Views: 242

Answers (3)

y.bregey
y.bregey

Reputation: 1499

final version:

def latest
  scope = Article.order(id: :desc)
  scope = scope.shared unless user_signed_in?
  render json: scope.limit(10), except: [:body, :created_at, :updated_at]
end

Upvotes: 0

Yury Lebedev
Yury Lebedev

Reputation: 4005

I would create an initial scope, and modify it based on some conditions:

def latest
  scope = Article.order(id: :desc)
  scope = scope.where(status: Article.statuses[:public_article]) if user_signed_in?

  render json: scope.limit(10).pluck(:id, :title)
end

Upvotes: 7

Nermin
Nermin

Reputation: 6100

You could refactor as

@lates_articles = Article.all
@lates_articles = @latest_articles.where("status = ?", Article.statuses[:public_article]) unless user_signed_in?
render json: @latest_articles.limit(10).order(id: :desc).pluck(:id, :title)

But it would be better to create model method

class Article < ActiveRecord::Base
  ...
  scope :latest, -> {last(10).order(id: :desc)}

  def self.public user_signed
    if user_signed
      all
    else
      where("status = ?", statuses[:public_article])
    end
  end
  ...
end

Then you would use it like

def latest
  render json: Article.public(user_signed_in?).latest.pluck(:id, :title)
end

Upvotes: 2

Related Questions