简体   繁体   中英

how to assign in ruby without checking each step if the values you assign exist

Unfortunately I couldn't think of a really good way to write this question, we have a lot of code that ends up looking like this:

@annotation.note = params[:annotation][:note] if params[:annotation][:note]
@annotation.style = params[:annotation][:style] if params[:annotation][:style]

I find that if params at the end check annoying.

So is there a way to write this more succinctly, so that it is understood that the value only gets copied over if it exists without having to ask that explicit if at the end each time?

x = params[:annotation][:note] and @annotation.note = x
x = params[:annotation][:style] and @annotation.style = x

You could easily extract the checks into a method, so that your code is more DRY. Like this, for example:

def copy obj, prop, params
  val = params[prop]
  obj.send "#{prop}=", val if val
end

ann = params[:annotation]
copy @annotation, :node, ann
copy @annotation, :style, ann

you can also try this:

params[:annotation].each_pair {|k,v| v && @annotation.send("#{k}=", v) }

some tests:

require 'ostruct'

@annotation = OpenStruct.new
params = {:annotation => {:note => 'note', :style => 'style'}}

params[:annotation].each_pair {|k,v| v && @annotation.send("#{k}=", v) }

p @annotation
#<OpenStruct note="note", style="style">

@annotation = OpenStruct.new
params = {:annotation => {:note => nil, :style => 'style'}}

params[:annotation].each_pair {|k,v| v && @annotation.send("#{k}=", v) }

p @annotation
#<OpenStruct style="style">

@annotation = OpenStruct.new
params = {:annotation => {:note => 'note'}}

params[:annotation].each_pair {|k,v| v && @annotation.send("#{k}=", v) }

p @annotation
#<OpenStruct note="note">
params[:annotation][:note].tap{|v| @annotation.note = v if v} 
params[:annotation][:style].tap{|v| @annotation.style = v if v}

Here's another method as well:

@annotation.note = params[:annotation][:note] || @annotation.note

I'll admit, you do repeat @annotation.note but the statement length is still reduced.

Here's another attempt:

@annotation.note = params[:annotation][:note] rescue nil

@annotation.note will remain nil if params[:annotation][:note] does not exist.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM