Undefined AWS::S3 when define a method in helper - ruby-on-rails

I am following this tutorial http://net.tutsplus.com/tutorials/create-a-simple-music-streaming-app-with-ruby-on-rails/, but use the aws_sdk instead of aws_s3. I see basically they do the same thing. In the download part, I put the the download function into the model and it did show correctly the url to download, but from there I don't know how to trigger download so I moved the function to the helper and invoke it straight from view. From there rails keep complaining about undefined method `model_name' for URI::HTTPS:Class
This is the download method
def download song_key
bucket = AWS::S3.new.buckets['mybucket'] # error from this line because undefined AWS::S3
song = bucket.objects[song_key]
song.url_for(:read, expires: 10*60)
end
This is the views
<% #songs.each do |song| %>
<%= link_to "download", download(song.key) %>
<% end %>
Any idea how to fix it ? Thanks

You're reading the stack trace slighty wrong - it's not your helper method raising the exception, but something inside link_to.
The url_for method is returning a URI::HTTPS instance. When the second argument to link_to is something other than a string, it assumes that it's an activemodel class and tries to find the appropriate route from that. For example if you do
link_to 'Show', person
and person is an instance of Person, link_to will end up generating the url from person_path(person).
URIs aren't active model, so this process of finding the appropriate route fails. All you need to do is turn the URI into a string, for example
def download_url song_key
bucket = AWS::S3.new.buckets['mybucket'] # error from this line because undefined AWS::S3
song = bucket.objects[song_key]
song.url_for(:read, expires: 10*60).to_s
end
Apparently the equivalent method in aws_s3 returning strings rather than URI objects which is qhy the tutorial you are following doesn't do this.

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

What does a link_to helper expand to when passed an array with a symbol and object in Rails?

In Rails, (specifically in ActiveAdmin) what does a link_to helper with an array passed as the second parameter do? Where's the documentation for this?
I have this code:
index pagination_total: false do
column :name, :sortable => :first_name do |user|
link_to user.full_name, [:admin, user]
end
What does that do? What does [:admin, user] do here?
One confusing thing here is that my ActiveAdmin panel is defined as:
ActiveAdmin.register Promotions::User, as: "User" do
So the link actually comes out prepended with the module like so:
admin_promotions_users_path which I don't want. This causes an error since the as: overwrites the ActiveAdmin path_helper. What I want is:
admin_users_path.
In short, I think the error here is that I don't know what a link_helper expands to when passed an array with a symbol an object.
According to Ruby on Rails - link_to method, the method signature is link_to(body, url, html_options = {}). The url parameter can take:
A String like "/users/john-smith"
An Object like #user
An Array like [:admin, user]
A path like admin_user_path(user)
If the url parameter is a String, it just passes that to the href for the link. If the url parameter is an Object, an Array or a path, it passes the value to the url_for method behind the scenes.
url_for will take an Object, determine that the class type is User, and look for a corresponding user_path(#user) route method. With an array, it first takes any symbols and use it to construct the name of the url helper, then it will take any objects and pass it as values. This is how link_to user.full_name, [:admin, user] gets converted to admin_user_path(#user) which finally becomes John Smith
Update
According to this Stack Overflow answer (which links to url_for and polymorphic_url) url_for takes the input and passes it up to the parent method which for some reason adds the current scope. link_to uses url_for by default. polymorphic_path is the method you require if you want to "unscope" it. I tested this concept in a similar situation in my own app and got the same results as #Jwan622.
url_for([:admin, user]) # Does not exist
#=> admin_promotions_users_path
polymorphic_path([:admin, user]) # Exists
#=> admin_users_path
Therefore, you should either use this:
link_to user.full_name, admin_users_path
Or this (if you need to generate the link dynamically):
link_to user.full_name, polymorphic_path([:admin, user])

Rails undefined method in Controller

I have a Link resource (Link as in url's). I have a method in my Links controller to determine whether or not a link that a user enters has the "http://" prefix, and if not, to append that prefix to the URL. Although I defined the method in my Links controller, I am getting an undefined method error.
Here is the relevant portion of my links controller:
helper_method :link_formatter
def link_formatter(url)
prefix = "http://"
url.include?(prefix)? url : prefix + url
end
Here is my links view:
<%= link_to link.description, link_formatter(link.url), :target => '_blank' %>
The error:
undefined method `link_formatter' for #<#<Class:0x007fbd51e2ea08>:0x007fbd5250cfa0>
The link_formatter is a generic function that can be used by any view in your Rails application. To make it accessible by all your views add it to the ApplicationHelper as #Damien Roche said. The application helper is located in app/helpers/application_helper.rb. You can also generate a new helper by running rails generate helper HELPER_NAME on the command line.

How do rails extract an id from an instance variable?

I'm reading "Rails Routing from the Outside In" on RailsGuides.
In Section 1.2, it says
<%= link_to 'Patient Record', patient_path(#patient) %>
will generate the path /patients/17.
What I'd like to know is how rails extract the id from the instance variable.
I've been trying to find the corresponding line of the code on GitHub but can't find.
The ID comes from calling #to_param on the object. Here is a little documentation about it, http://guides.rubyonrails.org/active_support_core_extensions.html#to-param
It calls a to_param method which by default will produce the ID. You can override it to produce nice URLs like this
class Post < ActiveRecord::Base
def to_param
"#{id}-#{title}"
end
end
method responsible is to_param. link to line on
github

Rails returning full object instead of integer

Rails's pluralize method was not working like I wanted (words not in english) so I set out to try my own solution. I started out simple with this method in ApplicationController:
def inflect(number, word)
if number.to_i > 1
word = word + "s"
end
return "#{number} #{word}"
end
And called it as such in my view:
<% #articles.each do |article| %>
<%= inflect(article.word_count, "word") %>
<%= inflect(article.paragraph_count, "paragraph") %>
...
<% end %>
But this got me:
undefined method `inflect' for #<#<Class:0x3ea79f8>:0x3b07498>
I found it weird that it referenced a full-fledged object when I thought it was supposed to be just an integer, so I tested it on the console:
article = Article.first
=> (object hash)
article.word_count
=> 10
article.word_count.is_a?(Integer)
=> true
So I threw in a quick words = article.word_count.to_i, but it doesn't throw a TypeError, it actually doesn't do anything, and still returns the same error: undefined method ``inflect' for #<#<Class:0x3ea79f8>:0x3b07498> in reference to the `inflect(article.word_count, "word") line.
Then I thought maybe inflect was already a Rails method and it was some sort of naming conflict, but doesn't matter what I change the method's name to, it keeps giving me the same error: undefined method ``whatever' for #<#<Class:0x3ea79f8>:0x3b07498>
I then tested it on the console and it worked fine. What's going on?
Put your inflect method in ApplicationHelper, not ApplicationController
by default all code in your helpers are mixed into the views
the view is its own entity, it is not part of the controller, when a view instance gets created (automatically when your controller action executes) it gets passed any instance variables you define in your controller action, but does not have access to controller methods directly
NOTE: you can define methods in your controller to expose them to your views by using the helper_method macro - see this post for more info on that - Controller helper_method
but in general you would define the view helper methods in the helpers classes and not in the controller

Resources