1

In my rails app I am using carrierwave for images. Carrierwave creates different versions of an image and the url can be obtained like this: picture.large.url, picture.small.url, picture.thumb.url, etc.

I would like to create a method that can accept a string argument that can then be used for the image url. Something like this:

def profile_url (version)
  picture.version.url
end

So then I can write @user.profile_url('thumb') and it should give me the url in thumb size.

I get an undefined method 'version' error. Is this possible?

3
  • 2
    You can pass the version as an argument to url, i.e. picture.url('thumb') Commented May 22, 2016 at 8:22
  • 1
    @Stefan If you are certain of this, then I think you should offer it as an answer. Although the proposed answer works, yours removes the verbosity and complexity of an additional layer over the library and is therefore better IMO. PS, to the OP, although you wanted to specify a string, I suggest you reconsider and use a symbol instead. It's more idiomatic, easier to type, and simpler (no case or encoding). Commented May 22, 2016 at 9:25
  • @KeithBennett thank you for the advice! Commented May 22, 2016 at 12:47

2 Answers 2

6

Normally you can do it this way:

def profile_url(version)
  version = version.to_sym

  case version
  when :large, :small, :thumb
    picture.send(version).url
  end
end

The reason for the to_sym call here is so you can call this profile_url('thumb') or profile_url(:thumb) and both will work.

Sign up to request clarification or add additional context in comments.

5 Comments

Do you really want this to fail silently on a bad arg? I think raising an exception would be appropriate. This would also simplify the method tremendously: picture.send(version.to_sym).url.
@KeithBennett Depends on how important this is. Sometimes failing silently is good enough. It can be made more robust by triggering an exception.
True, but the 1-liner I provided does what your method does but will raise an exception if an unsupported name is used (if there is no method by that name).
@KeithBennett I mean this could be made to trigger a custom exception rather than a generic method not found version.
Could be a custom exception, or maybe in IllegalArgumentError? I wrote some code in a gem to handle this exact case, check out gist.github.com/keithrbennett/81bcfc12d913c05c7f299bd6e6fb351b and github.com/keithrbennett/trick_bag/blob/master/lib/trick_bag/…. I use a custom InvalidValueError but should probably just change that to IllegalArgumentError.
1

According to the documentation for CarrierWave's url, you can pass the version as an argument:

When given a version name as a parameter, will return the url for that version [...]

my_uploader.url           #=> /path/to/my/uploader.gif
my_uploader.url(:thumb)   #=> /path/to/my/thumb_uploader.gif

Your code can be written as:

class User < ActiveRecord::Base
  mount_uploader :picture, PictureUploader

  def profile_url(version)
    picture.url(version)
  end
end

And called via:

@user.profile_url('thumb')
# or
@user.profile_url(:thumb)

You could also invoke the method directly:

@user.picture.url('thumb')
# or
@user.picture.url(:thumb)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.