[CarrierWave] Conditional process?

613 views
Skip to first unread message

iwar...@gmail.com

unread,
May 4, 2010, 1:24:22 PM5/4/10
to carrierwave
I would like to be able to conditionally create versions and process
attachments. For example, an Upload may be any type, but if it is an
image, I would like to create a large/small/thumb version, and
appropriately resize them.

Has anyone done anything like this or have an idea what would be the
best way to do it?

Ian

--
You received this message because you are subscribed to the Google Groups "carrierwave" group.
To post to this group, send email to carri...@googlegroups.com.
To unsubscribe from this group, send email to carrierwave...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/carrierwave?hl=en.

Jonas Nicklas

unread,
May 4, 2010, 4:20:08 PM5/4/10
to carri...@googlegroups.com
There's a recent thread about this, with a nice proposed solution.
Haven't gotten around to implementing it yet though, and haven't
received a patch.

/Jonas

Ian Warshak

unread,
May 5, 2010, 11:52:40 AM5/5/10
to carri...@googlegroups.com
I spent a few hours hacking on this and here is what I came up with and it works for what I am using it for:


If there is a better approach, or you see something that can be done better let me know. I'd appreciate any feedback. I hope that this feature can get added to CarrierWave because I can see a lot of use cases for it. 

Ian

Jonas Nicklas

unread,
May 5, 2010, 6:16:20 PM5/5/10
to carri...@googlegroups.com
I dislike the use of lambdas, I'd prefer a callback, as in:

version :foo, :if => :bar? do

end

def bar?

end

this would mean we can add the image? method to the rmagick module
already, and have the (probably by far) most common use case covered
with nice syntax. Plus, I just don't like lambdas as an API ;)

/Jonas

Ian Warshak

unread,
May 6, 2010, 12:52:30 PM5/6/10
to carri...@googlegroups.com
What's wrong with using lambdas? By using a lambda in this case, it makes it much easier for someone to add their own conditions. 

My other thought would be that the block that is passed into version could be stored, then evaluated at a later time instead of immediately being evaluated immediately. For instance when the cache is set or when an object is pulled from storage. This way we can have the method :bar be an instance method on the uploader instead of being a class method or even a lambda.

Ian

Jonas Nicklas

unread,
May 9, 2010, 10:14:57 AM5/9/10
to carri...@googlegroups.com
I don't see how adding your own conditions is made easier with
lambdas? Can you give an example?

I think we are miusunderstanding each other, in my example bar? is an
*instance* method, I think you can achieve pretty much anything you
want with that callback syntax as with the lambda syntax. And I just
find lambdas ugly ;)

/Jonas

Ian Warshak

unread,
May 21, 2010, 12:35:45 PM5/21/10
to carri...@googlegroups.com
What do you think that would take to implement? 

My idea is to re-implement #version which would store the block as well as the name of the "conditional method" to call. The block would then be evaluated if it passes the conditional method when the object is stored/pulled from the cache/storage, 

So maybe something like this: https://gist.github.com/866520f2a85c4ccf7e26 (not sure if that code actually works, just an idea)

What do you think about that approach?

Ian

Jonas Nicklas

unread,
Jul 20, 2010, 3:41:48 PM7/20/10
to carri...@googlegroups.com
I know this is from ages ago, but this is the first time I've had time
to work on CarrierWave since forever. I tried out your branch and
fixed it up a little bit. See here:

http://github.com/jnicklas/carrierwave/commits/version_fix

But now there's some strange behaviour. I haven't added the version
check to retrieve_from_cache or retrieve_from_store, because of that
it might behave quite odd when actually used. The problem is that when
we're not using the File storage, that file we're checking again might
not be a CarrierWave::SanitizedFile and then it becomes very hard to
reason about how the whole thing works. Since we can't store which
versions were actually created, there is no way to check afterwards if
they were.

We'd need some much better integration tests for this, imho. I'm very
hesitant about merging this without that.

/Jonas

Ian Warshak

unread,
Jul 25, 2010, 3:14:30 PM7/25/10
to carri...@googlegroups.com
Hi Jonas,

I am not entirely convinced that this is the best way to have conditional versions, it was just the easiest to implement at the time (and it actually worked for me).

My previous email outlined a better way of handling this (I think). Basically, instead of creating the version class when #version is called, it is evaluated right before a file is saved. That way you have a handle on the actual file and you can do whatever kind of tests you want on the file. Do you think that's a better approach? 

Ian

Legato

unread,
Aug 20, 2010, 1:02:24 AM8/20/10
to carrierwave
I'm kind of in need this functionality but in the gem. Any tips on a
roundabout way of achieving this? Like the OP I have a situation
where the user might not necessarily upload an image, and only images
need to be thumbnailed. Any alternative way to ignore versions based
on conditions?

On Jul 20, 3:41 pm, Jonas Nicklas <jonas.nick...@gmail.com> wrote:
> I know this is from ages ago, but this is the first time I've had time
> to work on CarrierWave since forever. I tried out your branch and
> fixed it up a little bit. See here:
>
> http://github.com/jnicklas/carrierwave/commits/version_fix
>
> But now there's some strange behaviour. I haven't added the version
> check to retrieve_from_cache or retrieve_from_store, because of that
> it might behave quite odd when actually used. The problem is that when
> we're not using the File storage, that file we're checking again might
> not be a CarrierWave::SanitizedFile and then it becomes very hard to
> reason about how the whole thing works. Since we can't store which
> versions were actually created, there is no way to check afterwards if
> they were.
>
> We'd need some much better integration tests for this, imho. I'm very
> hesitant about merging this without that.
>
> /Jonas
>
> On Fri, May 21, 2010 at 6:35 PM, Ian Warshak <iwars...@stripey.net> wrote:
> > What do you think that would take to implement?
> > My idea is to re-implement #version which would store the block as well as
> > the name of the "conditional method" to call. The block would then be
> > evaluated if it passes the conditional method when the object is
> > stored/pulled from the cache/storage,
> > So maybe something like this: https://gist.github.com/866520f2a85c4ccf7e26
> > (not sure if that code actually works, just an idea)
> > What do you think about that approach?
> > Ian
>
> > On Sun, May 9, 2010 at 9:14 AM, Jonas Nicklas <jonas.nick...@gmail.com>
> > wrote:
>
> >> I don't see how adding your own conditions is made easier with
> >> lambdas? Can you give an example?
>
> >> I think we are miusunderstanding each other, in my example bar? is an
> >> *instance* method, I think you can achieve pretty much anything you
> >> want with that callback syntax as with the lambda syntax. And I just
> >> find lambdas ugly ;)
>
> >> /Jonas
>
> >> On Thu, May 6, 2010 at 6:52 PM, Ian Warshak <iwars...@gmail.com> wrote:
> >> > What's wrong with using lambdas? By using a lambda in this case, it
> >> > makes it
> >> > much easier for someone to add their own conditions.
> >> > My other thought would be that the block that is passed into version
> >> > could
> >> > be stored, then evaluated at a later time instead of immediately being
> >> > evaluated immediately. For instance when the cache is set or when an
> >> > object
> >> > is pulled from storage. This way we can have the method :bar be an
> >> > instance
> >> > method on the uploader instead of being a class method or even a lambda.
> >> > Ian
>
> >> > On Wed, May 5, 2010 at 5:16 PM, Jonas Nicklas <jonas.nick...@gmail.com>
> >> > wrote:
>
> >> >> I dislike the use of lambdas, I'd prefer a callback, as in:
>
> >> >> version :foo, :if => :bar? do
>
> >> >> end
>
> >> >> def bar?
>
> >> >> end
>
> >> >> this would mean we can add the image? method to the rmagick module
> >> >> already, and have the (probably by far) most common use case covered
> >> >> with nice syntax. Plus, I just don't like lambdas as an API ;)
>
> >> >> /Jonas
>
> >> >> On Wed, May 5, 2010 at 5:52 PM, Ian Warshak <iwars...@gmail.com> wrote:
> >> >> > I spent a few hours hacking on this and here is what I came up with
> >> >> > and
> >> >> > it
> >> >> > works for what I am using it for:
>
> >> >> >http://github.com/iwarshak/carrierwave/commit/47a1ed8890bbf3064a8399e...
> >> >> > If there is a better approach, or you see something that can be done
> >> >> > better
> >> >> > let me know. I'd appreciate any feedback. I hope that this feature
> >> >> > can
> >> >> > get
> >> >> > added to CarrierWave because I can see a lot of use cases for it.
> >> >> > Ian
>
> >> >> > On Tue, May 4, 2010 at 3:20 PM, Jonas Nicklas
> >> >> > <jonas.nick...@gmail.com>
> >> >> > wrote:
>
> >> >> >> There's a recent thread about this, with a nice proposed solution.
> >> >> >> Haven't gotten around to implementing it yet though, and haven't
> >> >> >> received a patch.
>
> >> >> >> /Jonas
>
> >> >> >> On Tue, May 4, 2010 at 7:24 PM, iwars...@stripey.net
> >> >> >> <iwars...@gmail.com>

Christopher Sass

unread,
Aug 20, 2010, 3:03:25 PM8/20/10
to carri...@googlegroups.com
I was having the same issue in my app, this is how i solved it.

Class MyUploader

  process :check_content_type

  def check_content_type
    if @file.content_type.include?("image")
      MediaUploader.version :medium do  
        process :resize_to_fit => [400,400]
      end 
      MediaUploader.version :small do
        process :resize_to_fit => [250,250]
      end 
      MediaUploader.version :thumb do  
        process :resize_to_fit => [100,100]
      end 
    end 
  end 

end

Hope this helps

Legato

unread,
Sep 9, 2010, 12:33:58 AM9/9/10
to carrierwave
That works fine when creating the upload initially, however, since the
version is conditional based on a process, when I retrieve the object,
it doesn't have those versions. I would imagine process is only run
on new uploads, so instantiating an existing file means those versions
are stored but can't readily be accessed.

I've adjusted my approach. In my app, there's an Upload class that
has methods for all uploaded files, and my FileUploader is mounted to
that class. There's additionally an Image class that inherits from
Upload; the idea is that Image does everything an Upload does and some
other things like get the dimensions of the image and validate based
on dimensions. (Later on I might want other subclasses for types of
uploads that require specific operations.) I create an Upload or
Image by checking the content_type of an uploaded file. In the Image
class I have additional versions specified:

class Image < Upload
FileUploader.version :thumbnail do
...
end
end

This way an Image object retrieved from the database will always have
its versions.

The only bummer is Uploader code being in the model instead of the
Uploader itself. If anyone knows a better way, please let me know.

On Aug 20, 3:03 pm, Christopher Sass <chris.sassafr...@gmail.com>
wrote:
> I was having the same issue in my app, this is how i solved it.
>
> Class MyUploader
>
>   process :check_content_type
>
>   def check_content_type
>     if @file.content_type.include?("image")
>       MediaUploader.version :medium do
>         process :resize_to_fit => [400,400]
>       end
>       MediaUploader.version :small do
>         process :resize_to_fit => [250,250]
>       end
>       MediaUploader.version :thumb do
>         process :resize_to_fit => [100,100]
>       end
>     end
>   end
>
> end
>
> Hope this helps
>
> > > >> >> >> > carrierwave...@googlegroups.com<carrierwave%2Bunsu...@googlegroups.com>
> > .
> > > >> >> >> > For more options, visit this group at
> > > >> >> >> >http://groups.google.com/group/carrierwave?hl=en.
>
> > > >> >> >> --
> > > >> >> >> You received this message because you are subscribed to the
> > Google
> > > >> >> >> Groups
> > > >> >> >> "carrierwave" group.
> > > >> >> >> To post to this group, send email to
> > carri...@googlegroups.com.
> > > >> >> >> To unsubscribe from this group, send email to
> > > >> >> >> carrierwave...@googlegroups.com<carrierwave%2Bunsu...@googlegroups.com>
> > .
> > > >> >> >> For more options, visit this group at
> > > >> >> >>http://groups.google.com/group/carrierwave?hl=en.
>
> > > >> >> > --
> > > >> >> > You received this message because you are subscribed to the
> > Google
> > > >> >> > Groups
> > > >> >> > "carrierwave" group.
> > > >> >> > To post to this group, send email to
> > carri...@googlegroups.com.
> > > >> >> > To unsubscribe from this group, send email to
> > > >> >> > carrierwave...@googlegroups.com<carrierwave%2Bunsu...@googlegroups.com>
> > .
> > > >> >> > For more options, visit this group at
> > > >> >> >http://groups.google.com/group/carrierwave?hl=en.
>
> > > >> >> --
> > > >> >> You received this message because you are subscribed to the Google
> > > >> >> Groups
> > > >> >> "carrierwave" group.
> > > >> >> To post to this group, send email to carri...@googlegroups.com.
> > > >> >> To unsubscribe from this group, send email to
> > > >> >> carrierwave...@googlegroups.com<carrierwave%2Bunsu...@googlegroups.com>
> > .
> > > >> >> For more options, visit this group at
> > > >> >>http://groups.google.com/group/carrierwave?hl=en.
>
> > > >> > --
> > > >> > You received this message because you are subscribed to the Google
> > > >> > Groups
> > > >> > "carrierwave" group.
> > > >> > To post to this group, send email to carri...@googlegroups.com.
> > > >> > To unsubscribe from this group, send email to
> > > >> > carrierwave...@googlegroups.com<carrierwave%2Bunsu...@googlegroups.com>
> > .
> > > >> > For more options, visit this group at
> > > >> >http://groups.google.com/group/carrierwave?hl=en.
>
> > > >> --
> > > >> You received this message because you are subscribed to the Google
> > Groups
> > > >> "carrierwave" group.
> > > >> To post to this group, send email to carri...@googlegroups.com.
> > > >> To unsubscribe from this group, send email to
> > > >> carrierwave...@googlegroups.com<carrierwave%2Bunsu...@googlegroups.com>
> > .
> > > >> For more options, visit this group at
> > > >>http://groups.google.com/group/carrierwave?hl=en.
>
> > > > --
> > > > You received this message because you are subscribed to the Google
> > Groups
> > > > "carrierwave" group.
> > > > To post to this group, send email to carri...@googlegroups.com.
> > > > To unsubscribe from this group, send email to
> > > > carrierwave...@googlegroups.com<carrierwave%2Bunsu...@googlegroups.com>
> > .
> > > > For more options, visit this group at
> > > >http://groups.google.com/group/carrierwave?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "carrierwave" group.
> > To post to this group, send email to carri...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > carrierwave...@googlegroups.com<carrierwave%2Bunsu...@googlegroups.com>
> > .
Reply all
Reply to author
Forward
0 new messages