Tintin81
Tintin81

Reputation: 10225

How to chain class methods together in Ruby on Rails?

I've got this in my Rails 5 model:

def self.payable
  open.where.not(:delivery_status => "draft")
end

def self.draft
  where(:delivery_status => "draft")
end

def self.open
  where(:payment_status => "open")
end

Is there a more elegant way to write the first method?

It would be great to chain the open and draft methods together like this:

def self.payable
  open.not(:draft)
end

Unfortunately, this doesn't work.

Upvotes: 2

Views: 989

Answers (2)

To chain negated queries you can use this trick:

def self.payable
  open.where.not(id: draft)
end

Another alternative if you don't care if an ActiveRecord::Relation object is returned is using -, which returns an Array:

def self.payable
  open - draft
end

I would personally use scopes instead of class methods for queries: https://guides.rubyonrails.org/active_record_querying.html#scopes. So:

scope :draft, -> { where(:delivery_status => "draft") }
scope :open, -> { where(:payment_status => "open") }
scope :payable, -> { open.where.not(id: draft) }

Upvotes: 2

KosBlo
KosBlo

Reputation: 19

Maybe you can use scopes?

scope :payable, -> { open.where.not(:delivery_status => "draft") }

You can use this like that

YouModel.payable

Upvotes: 1

Related Questions