2

I have following code ,

@checkedin=[]
@accepted=[]
@rejected=[]   
result.each do |parse_order|
  orderId = parse_order['orderID']
    if parse_order['status'] == -1
        @rejected << orderId
    elsif parse_order['status'] == 1
        @accepted << [orderId, parse_order['createdAt']]
    elsif parse_order['status'] == 2
       @checkedin << [orderId, parse_order['createdAt']]
    elsif parse_order['status'] == 3
        next       
   end   
end

is there a better way to concise it . Thanks.

5 Answers 5

5

You could use single line conditionals. Also, next is unnecessary at the end of a block.

@checkedin = []
@accepted  = []
@rejected  = []   

result.each do |parse_order|
  orderId = parse_order['orderID']
  status = parse_order['status']

  @rejected  << orderId if status == -1
  @accepted  << [orderId, parse_order['createdAt']] if status == 1
  @checkedin << [orderId, parse_order['createdAt']] if status == 2
end
Sign up to request clarification or add additional context in comments.

Comments

3
@checkedin=[]
@accepted=[]
@rejected=[]   
result.each do |parse_order|
  orderId = parse_order['orderID']
  case parse_order['status']
  when -1 then @rejected << orderId
  when 1 then @accepted << [orderId, parse_order['createdAt']]
  when 2 then @checked_in << [orderId, parse_order['createdAt']]
  end
end

You don't need the last case

I'd recommend pulling out each of those cases for readability

result.each do |parse_order|
  reject(parse_order) || accept(parse_order) || check_in(parse_order)
end

def reject(parse_order)
  @rejected << parse_order['orderId'] if parse_order['orderId'] == -1
end

def accept(parse_order)
  @accepted << [parse_order['orderId'], parse_order['createdAt']] if parse_order['orderId'] == 1
end

def check_in(parse_order)
  @checked_in << [parse_order['orderId'], parse_order['createdAt']] if parse_order['orderId'] == 2
end

I'd probably rename parse_order to order for brevity too

4 Comments

in above case does the arrays gets initialized at class level ?
No, you'd have to prefix everything with self. I think Pete's solution is syntactically best out of all the solutions posted
I much prefer what you have at the top. You said you revised it for readability, but I think it's much less readable. That's mainly because we have years of experience reading horizontally (top), and have got quite good at it. Reading vertically (bottom) is just inefficient. Also, the more compact the code (within limits, of course), the more the eye can take in at once. When I look at your code on the top I know what you're doing almost instantly. On the bottom I've got to hunt around before I understand the big picture. In writing code, "read-speed" is one of my most important criteria.
That's fair. Everyone is different. I personally like to have the business rules very clear so I can quickly understand how the cases branch from one another, so I like those to be clean and concise. I usually don't care about the implementation of a branch unless I'm dealing with it specifically. I also like isolating my branches with their logic/state if possible (e.g. each branch method contains both its boolean check for state and the logic keeping the top layer more generic). I feel this makes refactoring to an OO model later easier for me.
3

I'm going to throw my hat in the ring. IMHO it is more human readable and would be easier to maintain. While it has more lines of code (due to the Order class), the actual filtering of orders is more concise:

require 'order' 
orders = results.map{|result| Order.new(result['status'], result['createdAt'])}

@checked_in_orders = orders.select {|order| order.checked_in?}
@accepted_orders = orders.select {|order| order.accepted?}
@rejected_orders = orders.select {|order| order.rejected?}

The Order class is:

# orders.rb
class Order
  REJECTED_STATUS = -1
  ACCEPTED_STATUS = 1
  CHECKED_IN_STATUS = 2

  attr_reader :created_at

  def initialize(status, created_at)
    @status, @created_at = [status, created_at]
  end

  def rejected?
    @status == REJECTED_STATUS
  end

  def accepted?
    @status == ACCEPTED_STATUS
  end

  def checked_in?
    @status == CHECKED_IN_STATUS
  end     
end

Comments

2

I would use Enumerable#group_by:

REJECTED   = -1
ACCEPTED   =  1
CHECKED_IN =  2

h = result.group_by {|order| order['status']}
@rejected   = h[REJECTED  ].map {|order|  order['orderID']}
@accepted   = h[ACCEPTED  ].map {|order| [order['orderID'] order['createdAt']]}
@checked_in = h[CHECKED_IN].map {|order| [order['orderID'] order['createdAt']]}

Comments

0

You can use a case expression:

@checkedin=[]
@accepted=[]
@rejected=[]   
result.each do |parse_order|
  orderId = parse_order['orderID']

  case parse_order['status']
  when  -1
    @rejected << orderId
  when 1
    @accepted << [orderId, parse_order['createdAt']]
  when  2
    @checkedin << [orderId, parse_order['createdAt']]
  when 3
    next       
  end   
end

You can see more uses of case in this blog post and in the official documentation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.