Generate URL for file in /public in Rails 2 ERB view - ruby-on-rails-2

In my rails (v2.3.8) app I have a static resource file which I've put at /public/myfile.kml No need for any special routes.rb setting right?
It serves up just fine at http://localhost:3000/myfile.kml
When I deploy (to passenger) it appears at http://myserver/myappname/myfile.kml
All is well so far...
I have a view (an erb file) which spews out javascript which needs to reference this file. The output needs to be '/myfile.kml' on localhost, and '/myappname/myfile.kml' in production, or maybe the full URLs as above, or maybe a relative url involving a bit of '../../../' (awkward with RESTful URLs).
Should I be able to do something like <%=url_for 'myfile.kml'%> ?
or '<%=ROOT_URL%>/myfile.kml'
I know there's an insanely easy answer to this question, but honestly I've had no luck finding it. Quite a few people talking about 'root_url' but what is that? A variable I can reference in a view? It's undefined.

I'm not sure about Rails 2.3.8, but in Rails 3 this value defaults to false.
edit config/environments/production.rb and set:
config.serve_static_assets = true
Also, here's a blog post that shows a helper for linking to a static resource (favicon)
http://ilconnettivo.wordpress.com/2008/07/28/favicon-on-rails/

'<%= ENV["RAILS_RELATIVE_URL_ROOT"] %>/myfile.kml'

<%= RAILS_ROOT + "/public/myfile.kml" %>

Inspection of rake routes reveals the helper root_path for use in views. For example <%= root_path + 'myfile.kml' %> By default will map to files under public/ in a rails application.

The latest (>2.3.6) is Rails.root, see:
http://joneslee85.wordpress.com/2010/05/27/the-dilemma-of-rails-root-vs-rails_root-complex/

Why not just replicate your production environment locally? A webserver is not very resource hungry and it can help resolve some ecosystem configuration issues like you're seeing here.

Related

Rails 5 app. Asset pipelining and precompilation with heroku not showing up images from js.jsx files

I am almost done with upgrading my Rails3 app to Rails5; But I am facing a problem with assets pipelining and precompiling. We're using cdn as asset host.Now, What happens is that when I set config.assets.precompile to false in staging environment, the app doesn't load images from js.jsx files. At other places, the app is fetching the static assets (js,css,images) from the asset_host link that I've provided. But in some specific javascript files, The images is being pointed out to my app's domain like app.my_domain.com/assets/my_image.png,And it is giving 404 not found error.
In javascript, the code is something like
return (
<img src="/assets/my_image.png"></img>
)
Since this is a js file, I cannot use asset_path helper method here.
How to resolve this issue ?
PS: setting config.assets.precompile to true loads the image from app.my_domain.com/assets/my_image.png, but that's not what I want because of this. config.assets.compile=true in Rails production, why not?
Any help with this is highly appreciated. Thanks in advance.
I found an answer after some research. I changed the name of the file to js.jsx.erb and accordingly used asset_path helper method which rails provide.
return (
<img src = "asset_path 'my_image.png'"/>
)
It works.

What does this do in my routes.rb file?

I am looking at a gist showing me how to handle CORS request in a Rails app. My routes.rb needs to have this bit of code in it.
Rails.application.routes.draw do
controller :whatever, path: '/whatever' do
match 'post_action', via: [ :post, :options]
end
end
If I was looking at a post resource, could someone show me how to set this up? I mainly do not understand the match function.
It will match the /whatever/post_action with the Controller/Action whatever#post_action. One useful tool you could use to see what your routes.rb are doing is to run the command:
rake routes
That will display all the routing table of your Rails app.
You can find more info in the Rails guide http://guides.rubyonrails.org/routing.html
Take care!
Actually match is not the good way to handle routes.
In rails 4 also it removed.
You can use the following code to use it:-
resource :whatever do
post 'post_action'
end
To test your routes
rake routes

AWS to serve CSS images Sinatra

I am using the asset_sync gem to sync my assets to a S3 bucket. In production i want to use S3 and in development i want to use my local files. So i have setup the following along with a helper
environments/development.rb
configure :development do
set :asset_host, "/"
end
environments/production.rb
configure :production do
set :asset_host, "https://s3-eu-west-1.amazonaws.com/#{ENV['FOG_DIRECTORY']}"
end
helper
helpers do
def aws_asset( path )
File.join settings.asset_host, path
end
end
So in my views i can do this
<%= image_tag( aws_asset "/assets/images/wd.png") %>
Which will result in rendering that image from my local assets if in development or from my bucket when in production
So what if i want to render an image from within my main.css file, such as a background image? I cant do the below for example as its not an erb file
main.css
header{
background: #ffffff url('<%= aws_asset("/assets/images/bgwRpeat.png") %>') repeat-x;
}
So what can I do? Has anyone done this before
Thanks for any help anyone can offer
3 ways come to mind.
Precompile the assets
Before you deploy, precompile the assets and CSS. If you create a file called main.css.erb and then run it through ERB to produce main.css it'll have the right stuff inside. This would be my preference. There are lots of ways to precompile, I prefer Guard but YMMV.
Edit:
Lifted and twisted from the Guard::Erb docs
guard 'erb', :input => 'app/views/stylesheets/main.css.erb', :output => "public/assets/stylesheets/main.css" do
watch (%r{app/views/stylesheets/main.css.erb})
end
Something like that.
Create a route that then compiles the assets
This is similar to how you might use SASS templates with Sinatra (if you don't precompile them). Just do the same as above, set up a route for main.css, run the main.css.erb template through ERB and serve it. Add lots of caching.
Edit:
get "/assets/stylesheets/main.css" do
# remember to look at caching
erb :"stylesheets/main.css"
end
I started writing and I can't remember the 3rd :) In my defence, I've a terrible headache. Perhaps someone else will remember for me.

How to set HTTP response (cache) headers in a Sinatra app hosted on Heroku

I have a fairly simple app (just one index.html file and a css file - it really is just a static page) hosted on Heroku.
I use Sinatra to host it on Heroku. The 'app' itself is fairly simple:
require 'rubygems'
require 'sinatra'
get "/" do
File.read(File.join('public', 'index.html'))
end
The question is, how do I set the HTTP response header for the static assets? In particular, I wanted to set the Expires header for caching purposes.
EDIT: I'm looking to add the said header to the static assets (ie, the one that resides under /public, like background images, icons, etc)
Apart from the fact that I wouldn't get through the Sinatra stack just to serve static files, you'd call
cache_control :public, max_age: 60
to cache for a minute. cache_control is a helper that comes with Sinatra.
Otherwise, I'd suggest you have a look at http://www.sinatrarb.com/configuration.html to see how Sinatra is set up so you don't have do deal with serving static files.
Hope this helps.
edit: I just saw you were explicitly asking for the Expires header. I'm not sure, but that should be fairly the same way as Cache-Control. Sorry for the confusion
As an expansion to #awendt's answer, Sinatra can actually handle static files with out needing to explicitly define the route and print the file.
By adding:
set :static, true
..you can add your index.html and stylesheet.css to a public/ folder. Then when you visit http://localhost:9292/stylesheet.css you'll be provided with the static file.
If you want to use another folder name, instead of the default public/, then try:
set :public, "your_folder_name"
If we want to be less explicit we can just create the public/ folder in the knowledge that Sinatra will enable :static for us anyway :)
Source: http://www.sinatrarb.com/configuration.html#__enabledisable_static_file_routes

Static page routing in Sinatra (Ruby)

You can serve static files with Sinatra by placing them in public/ (by default) -- I have an index.html in there at the moment, but how can I make the root point to that file without having to parse it as a template?
To be clear, I can access /index.html successfully, and I'd like to route / to be the same static file, but without redirecting. Any idea how to do this?
Probably a better answer will eventually come, until then this is my shot at it.
If this is not what you want:
get '/' do
redirect '/index.html'
end
You might do something like this:
get '/' do
File.new('public/index.html').readlines
end
I'd go with the first one though, Not sure why you want to avoid that redirect
Just set enable :static inside of your app class. Like so:
class App < Sinatra::Base
# Set the app root; this is where the 'public' and 'views'
# directories are found (by default).
set :root, File.expand_path("#{File.dirname(__FILE__)}/../app")
# Allow the app to serve static files from the 'public' directory in :root
enable :static
end
require 'sinatra'
get '/' do
send_file File.join(settings.public_folder, 'index.html')
end
As described at Serving static files with Sinatra
using passenger this seems to work right out of the box. having an index.html file in the public directory and no routing brings up the index.html when accessing the root url.
I think this is only an issue because Sinatra/Rack doesn't have the concept of a default file to serve if you just go to /. In a webserver like Apache or Nginx this is taken care of for you and usually defaults to index.html index.htm (if either exists it will get served when going to a directory with no actual filename on the end).
When everyone says this is built into Passenger, I think they really mean that it's built into Apache/Nginx. Apache/Nginx will check if the static file exists and serve it if it does, the request will never get to Rack, which is awesome for performance.
I wouldn't want to set up a redirect to the 404 page as this sort of violates the whole idea of HTTP: there should be one endpoint for everything that end point should return the true state of that endpoint. Meaning that if you go to /asdf you want the webserver to report a 404 because that's what is actually going on. If you do a redirect, now your site is saying "I used to have something here, but it moved" and then the page it redirects you to, even though it says 404 in the text on the page, is actually reported by the web server as a 200, meaning "everything is fine with this page!"
There is a gem "sinatra-index" to solve this problem.
https://github.com/elitheeli/sinatra-index

Resources