Serving static files in Sinatra... with beautiful routes? - ruby

Assuming I have a directory structure similar to:
path_to_file/one/index.html
How can I set my sinatra app to be routed to
mysite.com/path_to_file/one/
and have the previously mentioned file to render? path_to_file will always stay the same, but there will be different folders (two, three, etc.) inside it.
I've tried the following:
get '/path_to_file/:number' do
File.read(File.join('path_to_file', "#{params[:number]}", "index.html"))
end
but then the e.g. javascript file linked from index.html doesn't render correctly.

Got it!
get '/path_to_file/:number/:file' do
File.read(File.join('path_to_file', "#{params[:number]}", "#{params[:file]}"))
end
get '/path_to_file/:number' do
File.read(File.join('path_to_file', "#{params[:number]}", "index.html"))
end
Order is important, since if these two methods are reversed, get '/path_to_file/:number' becomes a superset of get '/path_to_file/:number/:file'.

Just a thought, but you could setup your server software, Apache, nginx, whatever it is you're using, to serve .css and .js and image files from a different location.

Related

Laravel 8: Unable to locate a class or view for component [dashboardHeader]

Everything was fine in my localhost. But after putting in online server I am facing many errors. I got this error and there is not case sensitivity issue in name.
Here is my class name in app->http->view/component
class dashboardHeader extends Component
And here is my calling tag of component in view file.
<x-dashboardHeader />
I also tried this way
<x-dashboardHeader> </x-dashboardHeader>
But still it is not working!
I will put this as an answer since it's too big for the comment.
When you put x-dashboardHeader tag in your template - Laravel is actually trying to load your DashboardHeader class (notice the uppercase D) from the View\Components namespace (read it as LARAVEL_ROOT\App\View\Components\DashboardHeader.php).
It does it using the autoloader which is generated by the composer.
While developing using Windows/MacOS - case sensitivity for the file name isn't a problem, since in those systems you can't have two files with the same name (independent of the name casing). So if you have a file named "myCoolFile" - you can access it using "mycoolfile", "MyCoolFile", etc....
But this isn't the case for unix systems. In those systems file names are case-sensitive. You can have 3 files named "myCoolFile", "mycoolFile", "MyCoolFile" and this won't be a problem. You can test it yourself using:
touch myCoolFile
touch MyCoolFile
touch mycoolfile
ls -l
So going back to Laravel trying to load your LARAVEL_ROOT\App\View\Components\DashboardHeader.php file, the file is named differently in your case dashboardHeader.php. And since DashboardHeader.php and dashboardHeader.php are different files in unix systems - you get the error.
I really hope that I could describe the problem.
This is why I suggest that you might want to read the PHP-PSR docs (which, again, Laravel follows) where it says that classes MUST be named using StudlyCaps. So no "dashboardHeader", no "dashboard_Header" and stuff like that, only "DashboardHeader", "MyCoolClass" and so on.

intersphinx link creation issues for local files across multiple projects

I have a few different Sphinx projects that I would like to refer to each other locally (no web server). I have separate code + build directories setup for the projects and was trying out intersphinx to solve this requirement.
My questions are:
Is there a better way of referring to two or more local projects within Sphinx?
Is there a way to strip out the second build in the path?
In my configuration file I have:
intersphinx_mapping = {
'doc1': ('../build/doc1',None)
}
so I get no issues in doing a make HTML, however when I look at the reference I've created with :ref:'doc1 info <doc1:label1>' I have in the HTML document:
file:///<root path>/build/**build**/doc1/html/doc.html#label1
So the issue is I get two "build" directory listings - it should of been:
file:///<root path>/build/doc1/html/doc.html#label1.
If I manually do this, it correctly pulls in the document.
I've also tried replacing None with '../build/doc1'. If I drop the build from the mapping I do get an error in finding the objects.inv file for doc1.
I do not want to use absolute path since the end user getting this documentation may see it in another location and I want this to be cross platform...
My directory tree is essentially as follows:
Makefile
build/doc1/html
build/doc2/html
doc1
doc2
As a background, I'm trying this under Cygwin with Sphinx 1.7.5... I haven't tried Linux yet to see if I get the same behavior...
You can set a different path for your target and for your inventory.
Maybe you can try something like:
intersphinx_mapping = {
'doc1': ('../doc1', '../build/doc1/objects.inv')
}
If you want to keep the None, it is also possible to have both:
intersphinx_mapping = {
'doc1': ('../doc1', (None, '../build/doc1/objects.inv'))
}

Sinatra: put some of my helpers in separate folder

I have a Sinatra app and I have some helpers and they have their folder (helpers) in which I have website_helpers.rb and so on. I want to move some of this helpers in their own folder inside the helpers folder: to have helpers/subhelpers, bacause the files I want to put in the subhelpers folder are different from the others and it makes sense to have a different folder for them.
I tried adding this to my config.ru
Dir.glob('./helpers/subhelpers/*.rb').each { |file| require file }
And then in the controller I have:
helpers MyHelperFromSubHelpers
but I get an error uninitialized constant (NameError).
Any ideas how to fix this so that to have a clear structure?
TBH, it sounds like you're overdoing it, there's always Rails if you want to go in for a more Java like every-namespace-must-be-a-directory layout. Aside from that, usually, helpers in separate files are placed in the Sinatra namespace - see http://www.sinatrarb.com/extensions.html#extending-the-request-context-with-sinatrahelpers
Personally, I put them in:
project-root/
lib/
sinatra/
name-of-extension.rb
Mainly because if the extension is really useful, I'll end up wanting to use it in another project, and this is the standard layout for a Sinatra gem, which makes it easy to extract it into one and with barely any change in the calling code.
Dir.glob will only return the file name and not the full path with each match, so you need to add the path:
Dir.glob('./helpers/subhelpers/*.rb').each do |file|
require File.expand_path File.join( File.dirname(__FILE__), "./helpers/subhelpers/", file)
end
will probably fix it.

No route matches [GET] "/"...Sometimes

So I'm a bit of a Rails n00b, so I'll apologize if this is really simple. When I access my server from another computer, I get this message:
No route matches [GET] "/"
And if I try to go to my subpages (Well, currently I only have one), I get something along these lines:
Unknown action
The action 'index' could not be found for AwebpageController
But here's the catch: this only happens sometimes. The rest of the time, the standard RoR homepage loads, and going to wwww.mydomain.com/awebpage serves up the page fine.
My Routes.rb looks like this:
Wobsite::Application.routes.draw do
resources :awebpage
end
And awebpage_controller.rb looks like this:
class AwebpageController < ApplicationController
end
And yes, index.html.erb for Awebpage does exist. It's all so simple that I don't understand what's going wrong. Oh, and my webserver is Thin (Not sure if that matters). Thanks in advance for any help!
You might want to add this to the top of your routes file to set the default controller and page for your site (i.e. http://www.mysite.com/):
root :to => "AwebpageController#index"
To remove the default Ruby on Rails webpage you'll also want to delete the index.html file in your /public/ directory.
Also, although not required, in your controller you're missing the function definition for index.
class AwebpageController < ApplicationController
def index
end
end
Normally you'd do application logic and serve up a view in this function; however if you do nothing RoR automatically loads the view associated with the page (index.html.erb).
If after all this you're still having a problem perhaps explicitly add index to the AwebpageController in your routes file; perhaps rails is only mapping www.mysite.com/Awebpage/ to Awebpage/index and not www.mysite.com/Awebpage/index.

Get absolute (base) url in sinatra

Right now, I do a
get '/' do
set :base_url, "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}"
# ...
haml :index
end
to be able to use options.base_url in the HAML index.haml.
But I am sure there is a far better, DRY, way of doing this. Yet I cannot see, nor find it. (I am new to Sinatra :))
Somehow, outside of get, I don't have request.env available, or so it seems. So putting it in an include did not work.
How do you get your base url?
You can get it using request.base_url too =D (take a look at rack/request.rb)
A couple things.
set is a class level method, which means you are modifying the whole app's state with each request
The above is a problem because potentially, the base url could be different on different requests eg http://foo.com and https://foo.com or if you have multiple domains pointed at the same app server using DNS
A better tactic might be to define a helper
helpers do
def base_url
#base_url ||= "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}"
end
end
If you need the base url outside of responding to queries(not in a get/post/put/delete block or a view), it would be better to set it manually somewhere.

Resources