Accesing to my carrierwave model object with an attribute name - ruby-on-rails-3

I'm trying to put a file link with a partial render, something like this:
#Main haml file
= render :partial => 'file_upload', :locals => {:f => f, :file_download => 'residence_cert'}
#Inside the partial
%a{:href => #postulant_info[file_download]}
But this is making a link just with the file name, not the full path to the file. Then realized that #postulant_info[file_download] is just giving me a String with the file name, not the carrierwave object
-logger.debug #postulant_info.residence_cert #this is returning my carrierwave object -> 'DocumentUploader'
-logger.debug #postulant_info['residence_cert'] #but this one is just returning a String, the DB record with the file name
One solution could be put the url in the render as a local like = render :partial => 'file_upload', :locals => {:f => f, :file_download => 'residence_cert', :url => #postulant_info.residence_cert.url} but I think "should" be unnecessary when you have the attribute name inside the partial template.
Any thought would be appreciated. Thanks in advance

I'm extremely uncertain about what your problem exactly is, and what you're trying to achieve, but if you want to output a link to a file, in your partial then
%a{:href => #postulant_info.residence_cert.url}
is enough. #postulant_info.residence_cert will give you an instance of the uploader (DocumentUploader), and the #url method returns the complete url of the uploaded file
By the way, you should avoid using instance var in your partials, the only variables a partial should use are the it's been given.

At last I could achieve it with:
%a{:href => #postulant_info.send(file_download)}

Related

What's the best way to get the full url to a resource in a Rails model?

I'm using as_json in a Rails model to customise the returned json accessed from the controller, like so:
def as_json(options={})
{
:id => self.uuid,
:href => full_url_to_resource,
:file => self.file.url,
:filename => self.filename,
:file_size => self.file_size,
:date => self.created_at
}
end
I want to provide the full url of the resource to the client as the href attribute. I'm wondering if there is a non-hardcoded way to do this.
I've include the Url Helpers in my model
include Rails.application.routes.url_helpers
Which allows me to do this:
:href => url_for_file(:host => "example.com") + '/files/' + self.uuid,
That works fine, but I obviously don't want to hardcode the url. Is there a built in way to do this in Rails based on the current URL being accessed or the url defined in default_url_options?
Or should I create a helper to do this instead?

customize kaminari pagination template

I'm having difficulty customizing the default kaminari template.
I've used the generator to create kaminari template files. In kaminari/paginator.html.haml:
= paginator.render do
%nav.pagination
All I want to do is access the actionview helpers within this, like link_to, or render. I've searched the source code and I can't find any incline of the helper being passed to this render method.
Essentially, being able to do this:
= paginator.render do
%nav.pagination
= render :partial => 'custom links'
= link_to "custom link", custom_path
..would solve my problems.
I didn't get a satisfactory answer, and so I'll submit my own solution.
Helpers cannot be used in the paginator.render block.
So, first I generate kaminari custom template files:
rails g kaminari:views default -e haml
Create a new file kaminari/custom.html.haml with the contents:
#pagination
= paginate custom
= render :partial => "kaminari/custom_view_file"
Replace kaminari paginator helper (paginate #results) in your view file with:
= render :partial => "kaminari/custom", :object => #results
You should be able to do something like this:
# /app/views/kaminari/_paginator.html.erb
= paginator.render do
%nav.pagination
= render :partial => 'shared/custom'
= link_to "custom link", custom_path
Basically, you need to provide the full path of the partial as it probably does not reside in the same directory.
EDIT:
I think Kaminari does not import rails view helpers in the paginate.render block in _paginator.html.erb.
To customize the output generated by paginator, you should instead
1. customize the _next_page.erb.html and so on where you can use rails helpers. I don't know why it is so though.
2. If you want to display some common html as a part of paginator, I suggest you put it in layout instead. Paginator is about navigation of pages.
For example, this is the _prev_page.html.erb:
<span class="prev">
<%= link_to "google", "www.google.com" %>
<%# link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote %>
</span>
I just commented out the old code and used a custom link.
Just met the same problem.
My solution:
= paginator.render do
%nav.pagination
= render :partial => 'custom links'
= #template.link_to "custom link", custom_path
As partial rendering occurs in scope of Paginator, there is possibility to use its instance variable, pointing to template (see https://github.com/amatsuda/kaminari/blob/master/lib/kaminari/helpers/paginator.rb)
Little hacky, but works.

Render #object and locals vs render :partial

I want to pass a local variable that contains the origin to come on a specific page, this variable contains just a symbol with the value.
When I use this code it works perfect, the origin variable is accessible in the partial :
render :partial => "products", :collection => #products, :locals => {:origin => :gallery}
But when I use this code, the origin is not set and not accessible in the partial :
render #products, :locals => {:origin => :gallery}
What is the difference here? Is the second line of code not render the partial like the first line?
<%= render #products %>
Is indeed the shorthand syntax for rendering a partial. But with the shorthand syntax, Rails will ignore the ":locals" variable. There's more on this in the Rails Guides.
So if you want to pass extra options to the render, you have to specify ":partial => ...". If you want to know why this happens, you can take a look at the Rails source.
There's a good explanation here: Rails: confused about syntax for passing locals to partials
The short version is that you can just omit :locals in the second example:
render #products, :origin => :gallery

Default_url in Paperclip Broke with Asset Pipeline Upgrade

I'm using Paperclip and have a default_url option like this for one of my attachments:
:default_url => '/images/missing_:style.png'
The asset pipeline obviously doesn't like this since the directories moved. What's the best way to handle this? I have two styles for this picture (:mini and :thumb).
:default_url => ActionController::Base.helpers.asset_path('missing_:style.png')
Then put the default images in app/assets/images/
Tested only on Rails 4.
To make it work in production, we have to pass the name of an existing file to the asset_path helper. Passing a string containing a placeholder like "missing_:style.png" therefore doesn't work. I used a custom interpolation as a workaround:
# config/initializers/paperclip.rb
Paperclip.interpolates(:placeholder) do |attachment, style|
ActionController::Base.helpers.asset_path("missing_#{style}.png")
end
Note that you must not prefix the path with images/ even if your image is located in app/assets/images. Then use it like:
# app/models/some_model.rb
has_attached_file(:thumbnail,
:default_url => ':placeholder',
:styles => { ... })
Now default urls with correct digest hashes are played out in production.
The default_url option also takes a lambda, but I could not find a way to determine the requested style since interpolations are only applied to the result of the lambda.
Just make sure that in your views all your paperclip images are rendered with image_tag.
<%= image_tag my_model.attachment.url(:icon) %>
That way, all of paperclip's :crazy :symbol :interpolation will have happened to the url string before Rails tries to resolve it to an asset in the pipeline.
Also, make sure your :default_url is asset compatible...if missing_icon.png is at app/assets/images/missing_icon.png, then :default_url should be simply "missing_:style.png"
<%= image_tag my_model.attachment.url(:icon) %>
# resolves to...
<%= image_tag "missing_icon.png" %>
# which in development resolves to...
<img src="/assets/missing_icon.png">
I got the error(even for a single style) at assets:precompile with
:default_url => ActionController::Base.helpers.asset_path('missing.png')
So I hooked with a method like this
# supposing this is for avatar in User model
has_attached_file :avatar,
:styles => {..},
:default_url => lambda { |avatar| avatar.instance.set_default_url}
def set_default_url
ActionController::Base.helpers.asset_path('missing.png')
end
I didn't try for multiple styles, but this works for my situation.
this works for me:
has_attached_file :avatar, :styles => { :small => "52x52",
:medium => "200x200>", :large=> "300x300", :thumb => "100x100>" },
:default_url => "missing_:style.png"
just place images in your assets/images folder named: missing_large.png, missing_medium.png, missing_small.png and missing_thumb.png
In rails 4.0.0 and paperclip 4.1.1 this worked for me:
has_attached_file :avatar,
styles: { medium: '300x300#', small: '100x100#', thumb: '25x25#' },
default_url: ->(attachment) { 'avatar/:style.gif' },
convert_options: { all: '-set colorspace sRGB -strip' }
I ended up having to use something like the following.
DEFAULT_URL = "#{Rails.configuration.action_controller.asset_host}#{Rails.configuration.assets.prefix}/:attachment/:style/missing.png"
has_attached_file :art, :styles => { :large => "398x398#", :medium => "200x200#", :small=>"100x100#", :smaller=>"50x50#", :smallest=>"25x25"}, :path=>"images/:attachment/:id/:style/:basename.:extension", :default_url => DEFAULT_URL
I statically compile the assets and was getting an error in production, this helped me.
In your model file, change this line:
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
by removing this:
/images/
Create a folder for each style, in this example medium and thumb, in assests/images and place an image called missing.png there (or whatever name you want it to have of course, as long as it matches the file name in the model)
Worked for me.
I've solved this problem by using a custom interpolator.
The problem from other solutions that suggest using
:default_url => ActionController::Base.helpers.asset_path('missing_:style.png')
is that you will get an error saying "missing_style.png" is not precompiled.
I created an initializer with the following code:
module Paperclip
module AssetPipeline
module Interpolator
def self.interpolate(pattern, *args)
ActionController::Base.helpers.asset_path Paperclip::Interpolations.interpolate(pattern, *args)
end
end
end
end
Then in my model I would do:
has_attached_file :image, interpolator: Paperclip::AssetPipeline::Interpolator, ...
Just remove the / from /images/pic.png: images/pic.png

Routing with id and handle in Rails

I'm trying to set up rails to use both the ID and the Handle (which is just an URL safe version of the title) of a blog post in the route.
match '/articles/:id/:handle', :to => 'articles#show'
resources :articles
This works, of course -- but I can't seem to set up the to_param method in the model os the longer URL -- with the handle attached, is the default.
This doesn't work (not that I really expected it to):
def to_param
"#{id}/#{handle}"
end
I get a No route matches {:action=>"edit", :controller=>"articles", error. I also tried just using the handle, but then Rails generates links to the resource just using the handle and not the ID. I know I can do it with a - in stead of a /, but I prefer the /. Any way to make this work? If I have to add some extra paremeters to my link_to helpers, that's okay.
Did you try to pass a Hash to link_to?
link_to "Link", {:id => #article.id, :handle => #article.handle}
Update
You have to modify your routes:
match '/articles/:id/:handle', :to => 'articles#show', :as => :article_with_handle
and use the following helper to generate the link:
link_to "Link", article_with_handle_path(:id => #article.id, :handle => #article.handle)
You can override the helper to simplify things:
def article_with_handle_path(article)
super(:id => article.id, :handle => article.handle)
end
and use it like this:
link_to "Link", article_with_handle_path(#article)
Okay, here's what I did to remove the query string problem from the answer above:
Changed the route to this:
match '/articles/:id/:handle' => 'articles#show', :as => :handle
Removed the to_param method from the model and then generated the link like this:
link_to 'Show', handle_path(:handle => article.handle, :id => article.id) %>
That works, but could be condensed, obviously, with the helper above. Just change the one line to: args[1] = handle_path(:id => args[1].id, :handle => args[1].handle)