Reputation: 6153
let's say I have this object:
class Post
def initialize(title: 'title', content: 'content')
@title = title
@content = content
end
end
but I would like to add logic like:
class Post
def initialize(title: 'title', content: 'content')
@title = title unless title.empty? # if it's empty I'd like to use the default value
@content = content unless content.empty?
end
end
In the above example, how do I assign a keyword argument conditionally?
Upvotes: 1
Views: 2566
Reputation: 3937
Revisiting this with a better answer...this is exactly what fetch
is used for:
class Post
def initialize(options)
@title = options.fetch(:title, 'title')
@content = options.fetch(:content, 'content')
end
end
Here's how one would use this logic:
irb(main):007:0> post = Post.new(title: 'A Very Short Story', content: 'Hello World!')
=> #<Post:0x00007fadc6829878 @title="A Very Short Story", @content="Hello World!">
irb(main):008:0> post = Post.new(title: 'A Nonexistent Story')
=> #<Post:0x00007fadc6820138 @title="A Nonexistent Story", @content="content"> # Notice how 'content' was set using the default option
Old (Valid But Uses More Code) Answer
Why not set defaults in a separate method and then merge in the arguments passed at initialization? If arguments aren't passed, then the defaults kick in. Otherwise, the defaults are overwritten by the arguments passed in at initialization.
For example:
class Post
def initialize(options)
options = defaults.merge(options)
@title = options[:title]
@content = options[:content]
end
## Code omitted ##
private def defaults
{
title: "Your Default Title"
content: "Your Default Content"
}
end
...
end
Upvotes: 2
Reputation: 168071
I feel a code smell here. You are trying to assign the default value to the variables under two separated conditions: when the argument is not given, and when the argument is empty. That is not a good design. It is a potential cause of bugs, and makes maintenance difficult. I suggest you should take one of the two ways:
(i) Make the arguments obilgatory (i.e., pass nil
or an empty value rather than not passing an argument), and do the validation in the method body:
class Post
def initialize(title, content)
@title = title.nil? || title.empty? ? "title" : title
@content = content.nil? || content.empty? ? "content" : content
end
end
(ii) Rather than passing an empty value as an argument, do not pass it:
class Post
def initialize(title: "title", content: "content")
@title, @content = title, content
end
end
Upvotes: 1