views:

140

answers:

7

I find myself often writing statements equivalent to:

deleted_at = Time.at(data[:deleted_at]) if !data[:deleted_at].nil?

i'd like to be able to write this in a more concise way. Any suggestions?

Sometimes I write this as:

deleted_at = Time.at(i) if !(i = data[:deleted_at]).nil?

But I think this makes the code harder to read so I hope there is some nicer way to do this.

+4  A: 

I use 'unless' since I find it more readable:

deleted_at = Time.at(data[:deleted_at]) unless data[:deleted_at].nil?

or you could even use:

deleted_at = Time.at(data[:deleted_at]) if data[:deleted_at]
Yannis
i like using unless instead of negating if. i'll start doing that more. :)
Peder
+1  A: 

You could wrap that generically into a lambda block:

class Object
  def unless_nil?
    yield self unless self.nil?
  end
end

data[:deleted_at].unless_nil? {|i| deleted_at = i }

I'd recommend to not monkey patch the Object class but better create a module and include that in the classes you need this functionality for.

hurikhan77
interesting idea. if going down this path it think i would prefer something like: unless_nil?(data[:deleted_at]) { |i| deleted_at = Time.at( i ) } because then the "control structure" keyword is first.
Peder
Well actually it IS at the right place from OOP perspective. I'd suggest you learn to exploit ruby's extreme OOP more and write less C-ish/PHP-ish code. ;-)
hurikhan77
A: 

You can also do

data[:deleted_at] and deleted_at = Time.at(data[:deleted_at])

although whether that's better is a matter of taste.

glenn mcdonald
glenn jackman
i'd have written this as
Glenjamin
Right, should be `and` here.
glenn mcdonald
A: 

Not having deleted_at declared like that is not my cup of tea. It would at least be set to nil with something like this:

deleted_at = Time.at(data[:deleted_at]) rescue nil

or

deleted_at = data[:deleted_at].nil? ? nil : Time.at(data[:deleted_at])
Jonas Elfström
That was maybe a wanted side effect of the original implementation (not modifying it at all). I would use the (young) replacement `Time.try(:at, data[:deleted_at])` instead of the `rescue` construct.
hurikhan77
Indeed a nice little extension by ActiveSupport. http://api.rubyonrails.org/classes/Object.html#method-i-try
Jonas Elfström
i like the try solution. using rescue for this i think is really bad because of performance and that using rescue for flow control is (/should be) unexpected for the reader.
Peder
+1  A: 
data_deleted = data[:deleted_at]
deleted_at = Time.at(data_deleted) unless data_deleted.nil?

makes it more readable IMO.

Anonymous scholar
(unless x) is the same thing as (if !x) I would/do use this exact same syntax
Rabbott
A: 

You can take advantage of the nil version evaluating to false to do this:

deleted_at = data[:deleted_at] and Time.at(data[:deleted_at])

Although now having written this i think i prefer the if version.

Code is written far less than its read - concise doesn't always equate to readable.

Glenjamin
A: 

If it's only Time.at that's giving you problems, you could write

class Time
  def nil_friendly_at(time)
    return nil if time.nil? # Or "unless time"
    at(time)
  end
end

Or you could monkey-patch Time.at itself if you want (I'm not recommending this though!)

Andrew Grimm
Using Time.at was just to give an example of a more general problem for me.
Peder