Rails 3.1: Dynamic linking to images in the asset pipeline? - image

I have ~ 500+ flag images that I previously kept in public/images/flags/ and public/images/flags_small/. For each country in my Country model, I store the :iso_code, which is the same as the name of the flag image that corresponds to it. For example, mx.png is the name of the Mexican flag because mx is the two-letter ISO code for Mexico.
I previously had a helper method that would return the html to display the image based on the iso code of the country and whether I wanted the large or small flag.
With Rails 3.1, to comply with the asset pipeline, I'm under the impression that those images should go into the app/assets/images folder. Following from this:
Can I maintain the subfolders therein?
How do I use image_tag to display the appropriate images?
Edit: solution
The answer below was correct, but I didn't want to type that much code each time,so I created two helper methods:
def flag(country)
image_tag('/assets/flags/' + country.iso_code.downcase + '.png')
end
def small_flag(country)
image_tag('/assets/flag_small/' + country.iso_code.downcase + '.png')
end

Yes, you can
For example: <%= image_tag 'flags/uk.gif' %>

As a quick solution to load images dynamically for Rails 5 (from a resource other than assets pipeline), imagine you have a controller called car.
add a new action (e.g. our action is called image) in your controller;
def image
path = "C:/pics/.../test.jpg" # just a sample path to test
send_file path, :content_type => 'image/jpg', :disposition => 'inline'
end
add the new route to your action in routes.rb;
get '/img', to: "car#image"
and finally in your ERB file, create an image tag with;
<div>
<%= image_tag url_for(:controller => "home", :action => "image") %>
</div>
This is just to test the basics and you can make it parametrized (to load the image based on id, name, etc.)

Related

Add default view for Rails Controller

I currently have no index views (app/views/mycontroller/index.html.erb), but would like to specify a default view if the user just types in: localhost:3000/mycontroller
Very new to RoR. My current config/routes.rb:
MyTestApp::Application.routes.draw do
get "team/thatguy"
get "home/about"
root :to => "home#about"
end
In my controller I've been playing around with redirects, but the desired solution is to only show the smaller uri localhost:3000/mycontroller.
app/controllers/home_controller.rb:
class HomeController < ApplicationController
def index
render "home/about"
end
def about
#title = "My Title"
end
end
Ok, assume you want to render a contact page when you access localhost:3000/mycontroller
What you want to do is:
Create a controller (C of MVC) with a contact action.
$ rails generate controller StaticPages contact
Excuting this code in your console creates some directories and files:
static_pages_contoller.rb with a contact action.
static_pages directory under the app/views directory with a view template called contact.html.erb
and you may have get 'static_pages/contact' in your config/routes.rb
Modify your routes:
Now you have access to the contact template with: localhost:3000/static_pages/contact
So to change the path, add a line to the routes.rb: match '/mycontroller', 'static_pages#contact', via: 'get'
Then you'll get your desired results.
I might be wrong, the whole process and details are here: http://ruby.railstutorial.org/ruby-on-rails-tutorial-book

Using MIddleman 3.0 - How do I set individual page titles on dynamic pages?

I'm putting together a simple portfolio site in middleman. I'm generate the 'work' pages dynamically based on local YAML data. This is in the config.rb:
data.work.projects.each do |project|
page "/work/#{project[0]}.html", :proxy => "project_template.html" do
#project = project
end
end
For SEO purposes, I would like each one of these dynamically generated pages to have a unique page title and description.
The title is currently set in the layout file like this
%title
= current_page.data.title
and I know I can use frontmatter to set current_page variables like this
---
title: "Recent Work - "
---
And I can stick that into my project_template.haml, but is there any way to get something like this to work?
---
title: "Recent Work - " + #project.title
---
Instead of setting the title in the frontmatter (like you are doing), you could use content_for.
E.g. in the layout:
%title= yield_content(:title)
And in the template of the dynamic page:
- content_for(:title, #project.title)
Here's the simplest, modular solution.
In your layout, throw in:
%title= 'Your Site Title | ' + #title
#title is a ruby instance variable that will be available to the current page.
In your current page, throw in (dont forget the dash):
- #title = 'Your Page Title'
Then you should be good to go!
I've found another way to work around that limitation. Instead of going for the page data, get the frontmatter data from the metadata:
%title = current_page.metadata[:page]['title']
It's not as nice and short as getting the data through current_page.data, but I've only managed to change the metadata:
proxy newpath, oldpath, :page => { 'title' => newtitle }
I'm not sure why but if I remember correct I had to also set the metadata resource afterwards on ready:
resource.add_metadata :page => { 'title' => newtitle }
I still think/hope that there must be a better solution. It's kind of totally weird that we can't set frontmatter data for proxy pages.

How to use Koala Facebook Graph API?

I am a Rails newbie. I want to use Koala's Graph API.
In my controller
#graph = Koala::Facebook::API.new('myFacebookAccessToken')
#hello = #graph.get_object("my.Name")
When I do this, I get something like this
{
"id"=>"123456",
"name"=>"First Middle Last",
"first_name"=>"First",
"middle_name"=>"Middle",
"last_name"=>"Last",
"link"=>"http://www.facebook.com/MyName",
"username"=>"my.name",
"birthday"=>"12/12/1212",
"hometown"=>{"id"=>"115200305133358163", "name"=>"City, State"}, "location"=>{"id"=>"1054648928202133335", "name"=>"City, State"},
"bio"=>"This is my awesome Bio.",
"quotes"=>"I am the master of my fate; I am the captain of my soul. - William Ernest Henley\r\n\r\n"Don't go around saying the world owes you a living. The world owes you nothing. It was here first.\" - Mark Twain",
"work"=>[{"employer"=>{"id"=>"100751133333", "name"=>"Company1"}, "position"=>{"id"=>"105763693332790962", "name"=>"Position1"}, "start_date"=>"2010-08", "end_date"=>"2011-07"}],
"sports"=>[{"id"=>"104019549633137", "name"=>"Sport1"}, {"id"=>"103992339636529", "name"=>"Sport2"}],
"favorite_teams"=>[{"id"=>"105467226133353743", "name"=>"Fav1"}, {"id"=>"19031343444432369133", "name"=>"Fav2"}, {"id"=>"98027790139333", "name"=>"Fav3"}, {"id"=>"104055132963393331", "name"=>"Fav4"}, {"id"=>"191744431437533310", "name"=>"Fav5"}],
"favorite_athletes"=>[{"id"=>"10836600585799922", "name"=>"Fava1"}, {"id"=>"18995689436787722", "name"=>"Fava2"}, {"id"=>"11156342219404022", "name"=>"Fava4"}, {"id"=>"11169998212279347", "name"=>"Fava5"}, {"id"=>"122326564475039", "name"=>"Fava6"}],
"inspirational_people"=>[{"id"=>"16383141733798", "name"=>"Fava7"}, {"id"=>"113529011990793335", "name"=>"fava8"}, {"id"=>"112032333138809855566", "name"=>"Fava9"}, {"id"=>"10810367588423324", "name"=>"Fava10"}],
"education"=>[{"school"=>{"id"=>"13478880321332322233663", "name"=>"School1"}, "type"=>"High School", "with"=>[{"id"=>"1401052755", "name"=>"Friend1"}]}, {"school"=>{"id"=>"11482777188037224", "name"=>"School2"}, "year"=>{"id"=>"138383069535219", "name"=>"2005"}, "type"=>"High School"}, {"school"=>{"id"=>"10604484633093514", "name"=>"School3"}, "year"=>{"id"=>"142963519060927", "name"=>"2010"}, "concentration"=>[{"id"=>"10407695629335773", "name"=>"c1"}], "type"=>"College"}, {"school"=>{"id"=>"22030497466330708", "name"=>"School4"}, "degree"=>{"id"=>"19233130157477979", "name"=>"c3"}, "year"=>{"id"=>"201638419856163", "name"=>"2011"}, "type"=>"Graduate School"}],
"gender"=>"male",
"interested_in"=>["female"],
"relationship_status"=>"Single",
"religion"=>"Religion1",
"political"=>"Political1",
"email"=>"somename#somecompany.com",
"timezone"=>-8,
"locale"=>"en_US",
"languages"=>[{"id"=>"10605952233759137", "name"=>"English"}, {"id"=>"10337617475934611", "name"=>"L2"}, {"id"=>"11296944428713061", "name"=>"L3"}],
"verified"=>true,
"updated_time"=>"2012-02-24T04:18:05+0000"
}
How do I show this entire hash in the view in a good format?
This is what I did from what ever I learnt..
In my view
<% #hello.each do |key, value| %>
<li><%=h "#{key.to_s} : #{value.to_s}" %></li>
<% end %>
This will get the entire thing converted to a list... It works awesome if its just one key.. but how to work with multiple keys and show only the information... something like
when it outputs hometown : City, State rather than something like
hometown : {"id"=>"115200305133358163", "name"=>"City, State"}
Also for education if I just say education[school][name] to display list of schools attended?
The error i get is can't convert String into Integer
I also tried to do this in my controller, but I get the same error..
#fav_teams = #hello["favorite_teams"]["name"]
Also, how can I save all these to the database.. something like just the list of all schools.. not their id no's?
Update:
The way I plan to save to my database is.. lets say for a user model, i want to save to database as :facebook_id, :facebook_name, :facebook_firstname, ...., :facebook_hometown .. here I only want to save name... when it comes to education.. I want to save.. school, concentration and type.. I have no idea on how to achieve this..
Looking forward for help! thanks!
To show the hash in a pretty-printed way, use the gem 'awesome_print'.
Add this to your Gemfile:
gem 'awesome_print'
And then run:
bundle install
And then, in your view, you can add:
<%= ap #hello %>
The question of how to store in the database requires a little more information on what you plan to do with it, but at minimum you could create a model, add a 'facebook_data' (type would be 'text') on that model, and then serialize it (add this line near the top of your model file: serialize :facebook_data). Then you could assign the hash (#hello in this case) to the model's 'facebook_data' property, and then save the model. But you won't be able to query your database for individual attributes of this facebook data very easily this way.
you can just do #hello["name"] then it will give you the value of the name
Your #hello object should be of the class Koala::Facebook::API::GraphCollection or something similar. You should be able to loop through this object, like your question demonstrates. As for what code to put inside your loop that will help you save records to the database, assuming your rails user model class name is User, try something like this:
#hello.each do |h|
u = User.where(:facebook_id => h["id"]).first_or_initialize
u.update_attributes(
:name => h["name"],
:first_name => h["first_name"],
:hometown_city => h["hometown"]["name"].split(",").first,
:hometown_state => h["hometown"]["name"].split(",").last.strip
# ETC, ETC
)
end
In the case of the hometown and education fields, you're just going to have to traverse the ruby hash the proper way. See the docs for more info.

Need Help DRYing things up - Rails 3.1

.row
.nine.columns.centered
%ul.bucketlist
- #buckets.each_with_index do |resource, index|
%a{:href => "#{bucket_path(resource)}"}
%li.bucket
%h4= index + 1
%h5= resouce.name
%a{:href => "#{new_bucket_path}"}
%li.bucket.empty
= image_tag "add.gif"
%h5 Add Bucket
I have the above code written in 3 different views, with only minor differences between them. This doesn't seem very DRY to me, so I'm looking for some help to clean this up.
Between the views only a few things vary:
#buckets.each - The #buckets collection needs to change between #notes, #units aswell.
#{bucket_path} - I'd like to be able to pass in a variable so that bucket_path becomes resource_path.
If anyone can offer any help, it'd be much appreciated.
My experience with haml is limited, but I think you should be able to put the common code into a partial (a file named _common.html.haml, for instance), and then in the view simply do:
= render 'common', :items => #buckets, :new_item_path => new_bucket_path
Then change the partial like this:
%ul.bucketlist
- items.each_with_index do |resource, index|
%a{:href => url_for(resource)}
%li.bucket
%h4= index + 1
%h5= resouce.name
%a{:href => "#{new_item_path}"}
%li.bucket.empty
= image_tag "add.gif"
%h5 Add Item
One solution could be writing a helper function to generate the html.
People typically don't like html in helpers, but in this case it
would be a good idea. Write a function where you pass in the resource
name and it generates this code for you
Another way is to check the controller you are in and generate the required code based on that. For instance
resource = #buckets if params[controller]=='bucket'
A more condensed way to remove if statements would be something like following, but i havnt tried it out.
exec "resource = ##{params[:controller]}s"
Let me know if you need more help.

Using Dir.glob to list assets in Rails 3.1?

I am trying to choose an image randomly from a sub directory inside my /app/assets/images directory using the Dir.glob() command, and then display it with an image_tag. Somehow I can't get it to work.
Here's my code:
- #badges = Dir.glob("app/assets/images/badges/*")
= image_tag #badges.sample
Which produces the following error:
ActionController::RoutingError (No route matches [GET] "/assets/app/assets/images/badges/produce.png"):
As you can see the asset pipeline is inserting an "/assets" in front of the directory. Alright Rails, I'll meet you halfway here. So next I try removing /app/assets from the query path to make it work and get the following result:
- #badges = Dir.glob("images/badges/*")
= image_tag #badges.sample
ActionController::RoutingError (No route matches [GET] "/assets"):
What am I doing wrong here? Thanks in advance for your help!
Dir.glob is going to return images with a relative path, so your produce.png file will be returned as:
`app/assets/images/badges/produce.png`
However, you need to pass only the badges/produce.png part to image_tag. You need to remove the stuff before this:
= image_tag #badges.sample.gsub("app/assets/images/", "")
You may want to stick this in a helper instead:
def random_badge
badges = Dir.glob("app/assets/images/badges/*")
image_tag badges.sample.gsub("app/assets/images/", "")
end
and then in your view:
= random_badge

Resources