I'm finding myself writing this bit of code in my controllers a lot:
params[:task][:completed_at] = Time.parse(params[:task][:completed_at]) if params[:task][:completed_at]
Don't get hung up on what I'm doing here specifically, because the reasons change every time; but there are many circumstances where I need to check for a value in params and change it before handing it off to create
or update_attributes
.
Repeating params[:task][:completed_at]
three times feels very bad. Is there a better way to do this?
One way to shorten this slightly is:
if c = params[:task][:completed_at]
params[:task][:completed_at] = Time.parse(c)
end
Or, you might prefer this:
params[:task][:completed_at] &&= Time.parse(params[:task][:completed_at])
In the second case, the assignment will only happen if the left side is "truthy".
I suppose you could consider doing something like this.
Implement #to_time
on String and NilClass, perhaps in a extensions.rb
(as recommended in Ruby Best Practices, e.g.
require 'time'
class String
def to_time
Time.parse(self) # add error/exception handling to taste
end
end
class NilClass
def to_time
nil
end
end
Then you can just call params[:task][:created_at].to_time
and the duplication is gone.
I'm not at all sure that this necessarily constitutes "best practice", but IMHO it meets the objective of the question...
I am not incredibly familiar with Ruby, but since it has Perl roots, there may be a construct that allows you to write it like this:
$_ = Time->parse($_) for params[:task][:completed_at] || ();
basically exploiting the for loop to create an alias to the variable, if it exists
maybe something like:
(params[:task][:completed_at] || ()).each { |i| i = Time.parse(i) }
edit:
I see that Ruby has an alias
keyword. I am not familiar enough with it to give a Ruby example, but in Perl, the above could also be written:
local *_ = \$params[$task][$completed_at];
$_ = Time->parse($_) if defined;
which specifies that $_
will be an alias for $params[$task][$completed_at]
I tried playing around with it breifly in Ruby, but didn't see a way to alias an identifier, just global variables.
来源:https://stackoverflow.com/questions/2068165/is-there-a-better-alternative-to-this-ruby-idiom