Rails/Gollum: Gollum does not use path prefix to load assets - ruby-on-rails

I mount gollum inside my Rails app like provided this answer.
It works, however the CSS and Javascript assets do not load properly.
routes.rb:
authenticate :user do
mount Precious::App, at: 'wiki'
end
So I can access the wiki at /wiki. This works, but gollum tries to load the css files from eg. http://localhost:3000/css/gollum.css which does not work, instead of http://localhost:3000/wiki/css/gollum.css. How do I tell gollum to use the correct prefix?

This is almost certainly a bug in either Rails or Gollum. I know that Gollum does have the ability to map its assets to a subpath, because I do it in my apps (via Rack, though, not Rails routes), like this:
map "/wiki" do
run Precious::App
end
Reporting a bug would probably be your best bet.

Related

API-only doesn't load JS/CSS assets properly?

I created an app using api-only flag, and I ran into a problem.
I wanted to install a gem that includes a mountable engine, in which there are JS/CSS assets. When I mounted the engine, I got an error complaining that the JS/CSS files don't exist.
Rails.application.routes.draw do
if Rails.env.development?
mount SomeGem::Rails::Engine, at: "/some-gem"
end
end
When I tried the same on a new app without the api-only flag, it worked great without any hassle. So I am assuming that the api-only flag is affecting the bundle process (maybe excluding all JS and CSS assets?) but I can't find the relevant information in the doc.
What am I missing?
Well I haven't tried Rails 5 yet but, my general understanding is that API only will allow developers write business logic and won't work well with the view layer. Hence, I think you have chosen the wrong development mode. I suggest if you need to do view related development then, you should remove the flag and try to use it.

How do I customize the URL path to 'subpaths' for the assets pipeline?

I notice that everything regarding Rails and Sprockets falls into the 'domain/assets/' URL, but I have this issue with certain files that are trying to get CSS and image files from:
somedomain/assets/css/{filename}
somedomain/assets/images/{img_name}
I'm trying to find some way to split up the paths of those assets so they don't all go into the same /assets path so that the URLs work. I thought maybe I could either do that in the configuration, but I didn't find anything other than renaming config.assets.prefix, or the routes.rb, because I thought something like "get /assets/css" would work but I don't know where to point it to.
In any case, at this point I'm stuck (btw, this has been in development. in production, I'm running into somewhat of a different issue where the javascript_include_tag is trying to go to /javascripts path).
I did this in my application.rb in config:
config.assets.enabled = true
config.assets.paths << "#{Rails.root}/app/assets/css"
Got the answer. Sorry if my question and examples weren't clear enough... I'm always terrible at it...
Anyways I took a look at the sprockets documentation (not the sprockets-rails docs) and this is what I did (modified config.ru):
map '/assets/images' do
environment = Sprockets::Environment.new
environment.append_path 'app/assets/images'
run environment
end
map '/' do
run Rails.application
end
Unfortunately, I don't fully understand what's going on in the config.ru other than the fact that the entire application starts here but it looks like that mapping lets me serve it up in this way (Surely, on something like AWS I can use nginx but for Heroku and overall, this seems to make things easier).

How do I add asset search paths to Sprockets based on a wildcard subdomain in rails 3.1?

The Rails Asset Pipeline guide instructs you to use config.assets.paths in config/application.rb but I don't have access to the request's subdomain at this point.
I'd like to be able to prepend an extra path (for the current request only) based on the request's subdomain.
My application specific details
It's a basic CMS app. The root domain.com host handles the administrative part with standard controller/view rendering and default asset paths.
Requests to subdomain.domain.com renders the site based on subdomain. It calls prepend_view_path in a before_filter and adds Rails.root.join('vendor/sites/[subdomain]/templates') for the current request only.
I'd like to be able to prepend Rails.root.join('vendor/sites/[subdomain]/assets') to the Sprockets search paths when the request host is [subdomain].domain.com.
EDIT
I ended up just dropping in a mixin for Sprockets::Environment that overwrites the call method:
module SiteAssetsResolver
def call(env)
begin
# prepend path based on subdomain (from env)
super # Sprockets::Server#call
ensure
# remove path based on subdomain
end
end
end
MyApp::Application.assets.extend(SiteAssetsResolver)
Just as you did for your view path, add a before filter and append the new path to Rails.application.config.assets.paths
I got this idea while watching Railscasts #279 Understanding the Asset Pipeline
I agree with commenter on your question that said "The asset pipeline isn't really meant to be compiling your assets each request in production." -- making it not really possible to do exactly what you ask.
So how about an alternative to accomplish what you're really trying to accomplish here, which is different asset resolution for different subdomains. Put your sub-domain specific assets in sub-directories of your asset folders.
Now, in the view/helpers, when you call asset_path or any other helpers that take a relative asset path, ask it for "#{subdomain}/name_of_asset" instead of just "name_of_asset".
Now, because of the way the asset compiler works, it's possible this subdirectory method won't work, you may have to put the subdomain at the beginning of the actual filename instead. "#{subdomain}_name_of_asset". Not sure.
And this still wouldn't give you a sort of 'default fall through' where some assets in some subdomains don't have subdomain-specific assets, they just 'fall through' to the default. Which would be nice. It's possible a way can be figured out to do that too, not sure.
But at any rate, following this approach of asking for a different asset at display-time using logic in view/helper.... is going to get you further than your original suggested approach, which probably isn't possible.

Rails 3.1 and Image Assets

I have put all my images for my admin theme in the assets folder within a folder called admin. Then I link to it like normal ie.
# Ruby
image_tag "admin/file.jpg" .....
#CSS
.logo{ background:url('/assets/images/admin/logo.png');
FYI. Just for testing I am not using the asset_path tag just yet as I have not compiled my assets.
Ok all good so far until I decided to update an image. I replaced some colors but on reload the new styled image is not showing. If I view the image directly in the browser its still showing the old image. Going one step further I destroyed the admin images folder. But it has broken nothing all the images are still being displayed. And yes I have cleared my cache and have tried on multiple browsers.
Is there some sort of image caching going on? This is just local development using pow to serve the pages.
Even destroying the whole images folder the images are still being served.
Am I missing something?
In 3.1 you just get rid of the 'images' part of the path. So an image that lives in /assets/images/example.png will actually be accessible in a get request at this url - /assets/example.png
Because the assets/images folder gets generated along with a new 3.1 app, this is the convention that they probably want you to follow. I think that's where image_tag will look for it, but I haven't tested that yet.
Also, during the RailsConf keynote, I remember D2h saying the the public folder should not have much in it anymore, mostly just error pages and a favicon.
You'll want to change the extension of your css file from .css.scss to .css.scss.erb and do:
background-image:url(<%=asset_path "admin/logo.png"%>);
You may need to do a "hard refresh" to see changes. CMD+SHIFT+R on OSX browsers.
In production, make sure
rm -rf public/assets
bundle exec rake assets:precompile RAILS_ENV=production
happens upon deployment.
For what it's worth, when I did this I found that no folder should be include in the path in the css file. For instance if I have app/assets/images/example.png, and I put this in my css file...
div.example { background: url('example.png'); }
... then somehow it magically works. I figured this out by running the rake assets:precompile task, which just sucks everything out of all your load paths and dumps it in a junk drawer folder: public/assets. That's ironic, IMO...
In any case this means you don't need to put any folder paths, everything in your assets folders will all end up living in one huge directory. How this system resolves file name conflicts is unclear, you may need to be careful about that.
Kind of frustrating there aren't better docs out there for this big of a change.
In rails 4 you can now use a css and sass helper image-url:
div.logo {background-image: image-url("logo.png");}
If your background images aren't showing up consider looking at how you're referencing them in your stylesheets.
when referencing images in CSS or in an IMG tag, use image-name.jpg
while the image is really located under ./assets/images/image-name.jpg
http://railscasts.com/episodes/279-understanding-the-asset-pipeline
This railscast (Rails Tutorial video on asset pipeline) helps a lot to explain the paths in assets pipeline as well. I found it pretty useful, and actually watched it a few times.
The solution I chose is #Lee McAlilly's above, but this railscast helped me to understand why it works. Hope it helps!
The asset pipeline in rails offers a method for this exact thing.
You simply add image_path('image filename') to your css or scss file and rails takes care of everything. For example:
.logo{ background:url(image_path('admin/logo.png'));
(note that it works just like in a .erb view, and you don't use "/assets" or "/assets/images" in the path)
Rails also offers other helper methods, and there's another answer here: How do I use reference images in Sass when using Rails 3.1?

Static asset caching on Heroku with Jammit by changing ActionController::Base#page_cache_directory

I'm attempting to use Jammit for packaging CSS and JS for a Rails app deployed on Heroku, which doesn't work out of the box due to Heroku's read only file system. Every example I've seen of how to do this recommends building all the packaged asset files in advance. Because of Heroku's Git-based deployment, this means you need to make a separate commit to your repository every time these files change, which is not an acceptable solution to me. Instead, I want to change the path that Jammit uses to write the cached packages to #{Rails.root}/tmp/assets (by changing ActionController::Base#page_cache_directory), which is writable on Heroku.
What I don't understand is how the cached files will be used without hitting the Rails stack every time, even using the default path for cached packages. Let me explain what I mean:
When you include a package using Jammit's helper, it looks something like this:
<%= include_javascripts :application %>
which generates this script tag:
<script src="/assets/application.js" type="text/javascript"></script>
When the browser requests this URL, what actually happens is that it gets routed to Jammit::Controller#package, which renders the contents of the package to the browser and then writes a cached copy to #{page_cache_directory}/assets/application.js. The idea is that this cached file is built on the first request, and subsequent requests should serve the cached file directly without hitting the Rails stack. I looked through the Jammit code and I don't see how this is supposed to happen. What prevents subsequent requests to /assets/application.js from simply routing to Jammit::Controller again and never using the cached file?
My guess is that there's a Rack middleware somewhere I'm not seeing that serves the file if it exists and forwards the request on to the controller if it doesn't. If that's the case, where is that code? And how would it work when changing ActionController::Base#page_cache_directory (effectively changing where Jammit writes cached packages)? Since #{Rails.root}/tmp is above the public document root, there's no URL that maps to that path.
Great question! I haven't set this up myself, but it's something I've been meaning to look into, so you've prompted me to do so. Here's what I would try (I'll give a shot myself soon, but you are probably going to beat me to it).
config.action_controller.page_cache_directory = "#{Rails.root}/tmp/page_cache"
Now change your config.ru to:
require ::File.expand_path('../config/environment', __FILE__)
run Rack::URLMap.new(
"/" => Your::App.new,
"/assets" => Rack::Directory.new("tmp/page_cache/assets"))
Just make sure not to have anything in public/assets, since that won't ever be picked up.
Notes:
This is for Rails 3. Not sure of the solution under Rails 2.
It looks like Rack::Directory sets cache control headers to 12 hours so Heroku will cache your assets to Varnish. Not sure if Jammit sets this in its controller, but even if it doesn't, it will be cached quite quickly.
Heroku also sets ENV['TMPDIR'] now as well, so you can use that instead of Rails.root + '/tmp' if you wish.
This might be of use, it's for a different gem but the idea is similar and I'm trying to get it working with the plain asset helpers.
http://devcenter.heroku.com/articles/using-compass
Unfortunately it seems to be quite difficult to get rails to do this without patching/rewriting the asset helpers module (which resembles coupled spaghetti).

Resources