How do I find an image generated by Dragonfly with Cucumber/Capybara? - ruby-on-rails

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.

Related

Rendering an image from the Unsplash API in Rails

I have extensively researched this matter both on Stack Overflow and Google but found nothing conclusive. Since I'm completely new to the concept of API usage within Rails I have to ask for some advice.
I have followed the procedure from the github page
I have included the Unsplash helper in application_helper.rb as follows
def show_photo
Unsplash::Photo.find("tAKXap853rY")
end
and simply added
<%= image_tag show_photo %>
in my view.
This returns an object (So connectivity is good)
<img src="/images/#<Unsplash::Photo:0x007fc4b2f953c0>" alt="#
<unsplash::photo:0x007fc4b2f953c0>">
I'm aware that Rails is looking for a picture in the assets/images folder
How do I parse the inbound JSON and render it in my Rails view?
You can access to the urls key within the OpenStruct attributes in the Photo object that includes the raw, full, regular, small and thumb sizes, also as keys.
So, just to test you could use the raw one, like:
<%= image_tag Unsplash::Photo.find('tAKXap853rY')[:urls][:raw] %>
Or I think you could modify your method to accept one parameter which is the size key of the image, like:
module ApplicationHelper
def show_photo(size)
Unsplash::Photo.find("tAKXap853rY")[:urls][size.to_sym]
end
end
Then:
<%= show_photo('raw') %> # 'full', 'regular', etc ...
further to this solution I am trying to display the photographer's name by using the user.name method.
In the console I can get the following :
photo = Unsplash::Photo.find("tAKXap853rY")
photo.user.name
will return
=> "Alejandro Escamilla".
But in RAILS :
def show_photo(size)
#photo =Unsplash::Photo.find("tAKXap853rY")[:urls][size.to_sym]
end
just trying to display the name in my view like:
<%= #photo.user.name %> will return "user undefined method".
The .user.name is accessible in the console but not in rails! What have I missed? Thanks

Paperclip file processing in Rails [duplicate]

This question already has answers here:
How do you access the raw content of a file uploaded with Paperclip / Ruby on Rails?
(7 answers)
Closed 5 years ago.
I have paperclip running to upload and store files in a non-public directory on the server. Now I want to be able to read the files directly and or feed them into a gem such as axlsx. I'm struggling with even simply looping threw a text file and think I'm missing something basic (as is usually the case).
Here is my first attempt at opening the file:
Paperclip config in application.rb:
config.paperclip_defaults = {:storage => :fog, :fog_credentials => {:provider => "Local", :local_root => "#{Rails.root}/secured_storage"}, :fog_directory => "", :fog_host => "localhost"}
Model:
class Census < ActiveRecord::Base
has_attached_file :censusfile
validates_attachment_content_type :censusfile,
:content_type => ["application/octet-stream", "text/plain"]
end
In the Controller:
def processcensus
#census=Census.find(params[:id])
#file=#census.censusfile.path
end
In the View:
<% File.readlines(#file).read do |line| %>
<%= line %>
<% end %>
This fails because the 'path' returned by Paperclip is the path relative to its sotrage path, not the full path.
UPDATE: If I add the directory (in this case "secured_storage" in from of the path it work as expected. For example:
#file="secured_storage/" + #census.censusfile.path
Not sure if this is at all the way to address this. If it is, is there a way to ask Paperclip where it is storing the files??
I've read where I could use:
Paperclip.io_adapters.for(#census.censusfile).path
But that seems to read the file into an array unless I'm missing something completely. My goal is to be able to loop threw a text file as well as feed an Excel file to axlsx for processing. I would also like to be able to eventually feed these files directly to a user somehow to allow for secure downloads.
I have looked hard for some documentation on all this and haven't found anything that really explains it yet. I'm to that point of just randomly throwing code here or there and hoping something works, which rarely does. Any help/direction that could be provided would be GREATLY appreciated!!!
Mark
I think io adapter can support read
Paperclip.io_adapters.for(#census.censusfile).read
so
<% Paperclip.io_adapters.for(#census.censusfile).read %>
<%= line %>
<% end %>
Use the copy_to_local_file method. This returns a file object on which you can read like on a normal file`.

if-else in HAML (ruby on rails)

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.

Hard coding routes in Rails

Let's say I have this:
<%= link_to "My Big Link", page_path(:id => 4) %>
And in my page.rb I want to show urls by their permalink so I use the standard:
def to_param
"#{id}-#{title.parameterize}"
end
Now when I click "My Big Link" it takes me to the correct page, but the url in the address bar does not display the desired permalink. Instead it just shows the standard:
wwww.mysite.com/pages/4
Is this because I hard-coded an id into the page_path? It also does not work if I use straight html like..
My Big Link
I would appreciate it if anyone could verify this same behavior and let me know if this intended or not. I need the ability to hard code :id's to specify exact pages...
Just use page_path(page). I guess the path helpers don't access the database themself (which is good), but if they are being supplied with an object and that object has a to_param method this method is being used to generate an identifier.
<%= link_to "My Big Link", page_path(page) %>
It's because you are specifying the id:
page_path(:id => 4)
You could specify the path you want in this method:
page_path(:id => "#{id}-#{title.parameterize}")
Where have you defined the to_param method? In the model?
UPDATE TO MY QUESTION ---------------------->
Thanks all for the answers. This was kind of a one off situation. My solution was to simply go with html:
My Big Link
Which produced the desired:
wwww.mysite.com/pages/4-great-title-here
I didn't want to loop through page objects and waste a call to the database for this one link. Much appreciated for all the answers though!

Adding a photo to a model's has_many model from a view

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.

Resources