I'm trying to use if-else to render some default image (being a user's avatar) if the 'user' doesn't have an avatar. (This is to avoid the depressing missing.png image). But it's not working so far.
Here is my view (view.html.haml file):
...
.user_avatar
-img_path = defined?(#user.avatar.url) ? "#{user.avatar.default_url}" : "#user.avatar.url"
%img{:src => img_path}
...
Here is my model:
...
attr_accessible :name, :avatar
has_attached_file :avatar :default_url => "assets/images/default_icon.png"
...
Note that if I used #user.avatar.icon.url in the img tag, it will work.
The problem is you are just generating a string, not evaluating the code. When you do:
"#{user.avatar.default_url}"
You are getting just exactly that string. What you probably meant to do was:
#user.avatar.default_url
Not as a string. This way it actually gets evaluated. The same thing goes for "#user.avatar.url".
EDIT
Change:
-img_path = defined?(#user.avatar.url) ? #user.avatar.default_url : #user.avatar.url
To:
-img_path = defined?(#user.avatar.url) ? #user.avatar.url : #user.avatar.default_url
In other words, if the user has a defined avatar URL, then use it, else use the default URL.
Also, consider throwing this in to a method on user, like User#avatar_url, which can do this if/else logic itself.
I think what you're after is:
.user_avatar
-img_path = defined?(#user.avatar.url) ? #user.avatar.url : #user.avatar.default_url
%img{:src => img_path}
To begin with, please check that the url to you default image is correct, if the image is in the app/assets/images folder, default_icon.png should suffice as a url.
Secondly, instead of manually writing the %imgtag, consider using a helper:
= image_tag #user.avatar.url
Thirdly, although I can't test it right now I'm pretty sure that the point of defining a default_url in paperclip is to be able to just call #user.avatar.url and having it return the default url automagically if there is not avatar.
In other words: doing it like your proposal kinda defeats the purpose.
My five cents is that the image url you've provided is wrong and that once you have the correct url, my code above will suffice.
Related
I use Attachinray with Cloudinary, for direct upload. Everything works very well, except the fact that when I try to save files in my controller, I do not have the original filenames.
Here is a sample of my code:
class User
has_attachments :pictures
end
My form :
= simple_form_for #user do |f|
= f.attachinary_file_field :pictures, as: :attachinary
= f.submit t('.submit')
Once my files are uploaded, when I submit the form, I lost original filenames. Here is what I get for one file :
{"public_id"=>"ryfeummp2ikmzkss4cfy", "version"=>1427873505, "signature"=>"8475fccf9914dd05f6fg622ee39c1cb7ddd25f11", "width"=>78, "height"=>100, "format"=>"png", "resource_type"=>"image", "created_at"=>"2015-03-24T14:48:25Z", "tags"=>["development_env", "attachinary_tmp"], "bytes"=>19882, "type"=>"upload", "etag"=>"1fefdabba402263d18a92238ba4275c9", "url"=>"http://res.cloudinary.com/dd9blzv7x/image/upload/v1427873505/ryfeummp2ikmzkss4cfy.png", "secure_url"=>"https://res.cloudinary.com/dd9blzv7x/image/upload/v1427873505/ryfeummp2ikmzkss4cfy.png"}
Does anyone know if it's possible to keep track of the original filename ?
If you wish to have the original image's filename, you can use something like the following in your controller code:
params[:user][:pictures].each do |picture|
# Do whatever you need with picture.original_filename
end
If you need to store them in your DB, you'll probably need to permit it first and not access them directly.
Alternatively, you can tell Cloudinary to set the uploaded image's filename as the original filename:
f.attachinary_file_field :pictures, as: :attachinary, cloudinary: {use_filename: true}
Note that random characters are added in default. For more information:
http://support.cloudinary.com/hc/en-us/articles/202520762-How-to-upload-images-while-keeping-their-original-filenames-
I would like to create a helper or change the model.rb to behave like:
Post model has a text field, which contains urls, all separated with new lines.
On create or update, rails scans this field, when it finds url like:
http://i.imgur.com/imanimage.png
http://i.imgur.com/anotherimage.png
Then it leaves them as is, but in the show action it renders them as:
= image_tag('http://i.imgur.com/imanimage.png', class: 'my-image-class')
= image_tag('http://i.imgur.com/anotherimage.png', class: 'my-image-class')
Probably a helper method could do this.
Does the text field store anything else but the urls? If it does, you should consider creating helper using regex to get all urls and change these to <img src=''/>,
If not, you can use in haml/erb file.
Model.text.each_line do |m|
image_tag(m, class: 'my_img')
end
Reference: http://ruby-doc.org/core-2.1.0/String.html#method-i-lines
If you're saving these URLs in your database, you it should be quite a simple procedure:
#app/models/image_url.rb
Class ImageURL < ActiveRecord::Base
end
#app/controllers/image_urls_controller.rb
def show
#url = ImageURL.find(params[:id])
end
#app/views/image_urls/show.html.erb
<%= image_tag(#url, class: 'my-image-class')
If you add some more context to your question, I'll be able to give you a more refined answer!
I'm pretty new to Ruby on Rails.
I changed this thread, because i recognized that I was searching for my problems' solution at the wrong end.
Here's my Problem:
I got a Class ProfileProposal which I upload an Image with(Using CarrierWave).
Now I want to convert ProfileProposal to another class, called Profile.
So I pass all the Information to the NEW-Form of Profile.
Works fine with strings, but not with Images.
What I've already tried/done:
Pass the Image as GET Param to the Create Method:
<%= form_for #profile, :url => { :action => "create", :controller => "profiles", :image => #profile_proposal.image } do |f| %>
#
Which now works, so I DO have the image-url.
What's not working is the following:
#profile = Profile.new(params[:profile], :image => new_image_url)
# OR
#profile.image = new_image_url
#profile.image still has the default value given by Carrierwave.
Thanks in advance!
I'm coming from using paperclip, not carrierwave, so I'll try to keep this high level. But I have an idea for you. Maybe you can set the filename of the new attachment before it exists, then move the image to that path. With paperclip this would play out like:
#profile.image_file_name = "profile.jpg"
# creates the directory of the new path. There's probably a better way to do this:
FileUtils.mkdir_p #profile.image_file_path.gsub(/[^\/]*$/,'')
FileUtils.mv #profile_proposal.image_path #profile.image_path
You should embed a hidden field in that Profile form, referencing ProfileProposal by some ID. Then while handling the form server side, after everything is validated and ready for save, you should copy the image using some read/write methods, from ProfileProposal instance to Profile instance. I'm not sure how CarrierWave wants you to do this.
I finally fixed that problem, by using paperclip and creating a new Instance via
Profile.create(:name => #profile_proposal.name, :image => #profile_proposal.image)
In the comments to the solution for How do I find an image on a page with Cucumber/Capybara, somebody asked:
I can't seem to figure how to get this
to work with URLs generated by
Dragonfly. They look like this:
/media/BAh_some_long_string_AwIw/12_11_52_810_5x5.jpg?s=7e360000, where 5x5.jpg is my file name. I've
tried something like:
//img[#src="/media//#{image}?s=*"]
but it doesn't work. Got any tips? – Ramon Tayag Feb 25 at 4:18
I have a similar problem, only worse - in my case, the generated image paths don't even include a (jpg|png|gif) file name, they only have these really long ids:
<img src="/media/BAhbB1sHOgZmSSIdNGQ4MTEyOGU3ZjViZmQwZTQ4MDAwMDAyBjoGRVRbCDoGcDoKdGh1bWJJIg0yMDB4MjAwIwY7BlQ" />
(Using dragonfly with mongo/gridfs)
These paths get rendered alright, but I can't figure out how to find them in a Cucumber/Capybara step :P
Any ideas? I looked at the Dragonfly's features, but they only test the rendering of the image itself, without detecting it's existence within an html page.
Answering my own question, after talking to Dragonfly's author (he's working on making this easier):
#route
match '/media/:dragonfly/:file_name', :to => Dragonfly[:images]
#model
class Store
include MongoMapper::Document
key :photo_uid, String
key :photo_name, String
image_accessor :photo
end
#view
<%= image_tag #store.photo.thumb('274x207#').url(:suffix => "/#{#store.photo_name}") if #store.photo %>
#cucumber
Then I should see the image "my_photo.png"
Then /^I should see the image "(.+)"$/ do |image|
page.should have_xpath("//img[contains(#src, \"#{image}\")]")
end
The key is adding an [attachment]_name field to the model, which Dragonfly populates automatically, and then passing it on as a suffix to url(). And the routes needs to allow for a :file_name param besides the generated dragonfly identifier.
I have a model, Thing, that has a has_many with ThingPhoto, using Paperclip to manage everything. On the "show" view for Thing, I want to have a file upload, and have it relate to the Thing model.
For some reason, I'm totally glitching on how this should be done. I've tried doing this (Haml):
- form_for #thing.thing_photos, :html => {:multipart => true} do |f|
= f.file_field :photo
= f.submit
... and I get this error:
undefined method `array_path' for #<ActionView::Base:0x24d42b4>
Google is failing me. I'm sure this is super easy, but I just can't get my brain around it.
Edit: I should have mentioned that if I change the #thing.thing_photos to just #thing, it works fine, in that it displays the form, but of course it's not associated with the correct model.
try #thing.thing_photos.new
this should instance a new model of thing_photos. If you're not using nested routes you'll have to add the thing_id as a hidden field.
If you're not tied to Paperclip (and if you're just doing images), I've had a lot of luck with fleximage. It's got really good documentation for image upload, manipulation, and display (with all sorts of neat effects like watermarking and stuff).
It doesn't quite answer your question, but it might be a cool thing to look into.
But I bet your problem related to the fact you're creating a form for an array of objects (through an association). I bet something is finding the type of the object (should be "thing_photo" but is "array" in your example), and appending "path" to it to write the form post URL. Perhaps you should add a .first or create a partial?
The form should be for #thing_photo and should either pass in the thing_id or if it's a nested route you can get it from that
then in your thing_photos controller
#thing_photo = Photo.new(params[:thing_photo])
#if using nested route
#thing = Thing.find(params[:thing_id])
#if using hidden field
#thing = Thing.find(params[:thing_photo][:thing_id])
if #thing_photo.save
#this is what ties the thing photo to the thing
#thing.thing_photos << #thing_photo
end
If I understand the question correctly, this might help.