3

I have the following method:

def download_link_for(site,title=nil)
  template = proc {|word|(title ?  "%s_#{title}_csv": "%s_csv") % word}

  if site.send(template.call("update")) == false
    x.a "Generate", :href => "/#{template.call("generate")}/#{site.id}"
  else
    xpr "Generating.."
  end
  if site.send(template.call("latest")) > 0 && site.send(template.call("update")) == false
    %|

  <a href="/#{template.call("download")}/#{site.id}" class="tooltip-left" title="Download the #{title} as a .csv file" id="download_pdf">
    <img src="/images/csv_download.png" alt="Download"/>
  </a>
  (#{timedate(site.send(template.call("latest")))})
    |

  end
end

The issue is the proc. I want to know if memoization works inside of a proc? specifically for:

title ?  "%s_#{title}_csv": "%s_csv"

Bearing in mind I'm working with ruby 1.8.7 though information on 1.9+ would be also be welcomed.

The main issue is that the ternary inside of the proc only ever needs to be worked out the first time so I don't want it to calculate it every time the proc get's called.

EDIT: My idea was to use currying like so:

template = proc {|tem,word|tem % word}.curry(type ?  "%s_#{type}_csv" : "%s_csv")

but for some reason it keeps responding with no implicit conversion of String into Integer I think ruby is interpreting % as modulus rather than as a string template. Even wrapping tem like so "#{tem}" didn't really work.

Also, curry wouldn't really work for me as it's not available in 1.8.7, but it was worth a shot.

Thermatix
  • 2,224
  • 13
  • 36
  • I'd think, if the title is always the same (which it must be given your statement, that it'd be best to compute it in the scope outside that block (as the first statement in 'download_link_for()'). So: ```saved_title = title ? "%s_#{title}_csv": "%s_csv"``` ```template = proc {|word| saved_title% word }``` (No code formatting in comments, I guess. That's two separate lines above.) – Derrell Durrett Jun 10 '16 at 15:00
  • I just tried the following `template = proc {|word|b||= 0;b+=1; puts b;(type ? "%s_#{type}_csv": "%s_csv") % word}` and it printed `1` every time, which I guess answers the question since it means b is re-calculated every time the proc is called. I was thinking I'd probably have to calculate it first at the beginning... wait what If I tried... I have an idea. – Thermatix Jun 10 '16 at 15:02
  • Is this an actual performance issue? The proc doesn't seem to do much ... – Stefan Jun 10 '16 at 15:39
  • It's becuase I like to be as dry as possible and like this I only write the code to do the templating once, but I also want the ternary to be done once as well. – Thermatix Jun 10 '16 at 16:04

1 Answers1

2

Not sure why you need to curry. Can't you just use an instance variable to store/memoize the results of the ternary operation?

template = proc { |word| @title ||= (title ? "%s_#{title}_csv" : "%s_csv"); @title % word }

In irb:

template = proc { |word| @title ||= word }

template.call "hello"
 => "hello" 

template.call "goodbye"
 => "hello" 
seph
  • 5,778
  • 2
  • 19
  • 19