I want to be able to follow a convention closer to what Rails does with resourceful routing. For example, I'm considering "signups" to be a resource, with it's own controller containing "new" and "create" actions.
In app/controllers/signup.rb I have:
MyApp.controllers :signups do
get :index do
# ...
end
post :index do
# ...
end
end
Is there any way I can use these route names, while actually responding on a path other than '/signups'? It feels like Padrino's route naming system is very tightly coupled with the URLs the routes map to.
I've tried:
MyApp.controllers :signups, :map => '/another-path' do
# ...
end
Among various other things without success. Perhaps I should just go back to using Rails... I was just getting frustrated with the startup overhead in TDD and I'm embarking on a new project at the moment (please don't refer me to Spork... that has it's own issues).
This is how I would do what you are asking
# in app/controller/signups.rb
MyApp.controllers :'another-path' do
get '/' do
# ...
end
end
Related
The gist
Is it possible to bake feature-toggle-like functionality into a Sinatra application?
A bit about feature toggles, just in-case ;)
Back story
I've set up a modular Sinatra project, and I tend to implement a GET/POST/PUT/DELETE endpoint for all my resources; it makes it easier to test the app and manipulate the data while in development.
Problem
When I go into production I don't want the unneeded endpoints to exist (e.g DELETE '/users').
Question
Can I annotate the methods with some kind of a :development flag, or maybe intercept the request in a before block? Would you do this using a helper? I'm not sure if I'm heading down the right path here, I'm probably over complicating it(?)
How would one go about this?
If you've done something like this it would be great if you can share your findings with the nation.
You can use the current environment to decide whether you define an action. For example:
class MyApp < Sinatra::Application
if settings.development?
get '/admin' do
'VIPs only'
end
end
end
If you have a lot to toggle, you might want to isolate them in one file that you can decide to require or not:
# routes/init.rb
require_relative 'main'
require_relative 'debug' if settings.development?
# routes/main.rb
class MyApp < Sinatra::Application
get '/' do
'Hello!'
end
end
# routes/debug.rb
class MyApp < Sinatra::Application
get '/admin' do
'VIPs only'
end
end
Or if you want to list your development-only paths in one place, here's a filter version:
class MyApp < Sinatra::Application
DEVELOPMENT_PATHS = %w[
/admin
]
before do
unless settings.development? || !DEVELOPMENT_PATHS.include?(request.path)
halt 404
end
end
end
Then you could also build some decorator-like methods that add to the list:
class MyApp < Sinatra::Application
def self.development_only(path)
DEVELOPMENT_PATHS << path
end
get '/admin' do
'VIPs only'
end
development_only '/admin
end
In general, I'd recommend caution when introducing significant differences between the code that runs in development vs. production. Inevitably, the dev code is either left untested or becomes cumbersome to maintain properly. In this case, there's the danger that you miss a route you intended to hide and it becomes available to everyone in production. I'd tend towards not having these routes at all and manipulating my dev environment from a console, or going all the way to the other end and building fully-tested and production-ready user permissions with something like sinatra-authentication.
I would like to customize my path helpers in Rails 4.
I have a Site5 website (which uses Apache server) with multiple subdomains. I have rewrite rules in my .htaccess file which adds the folder name to the url. For example
cs1337.mysite.com/login
is rewritten to
cs1337.mysite.com/cs1337/login
In routes.rb, I have added a scope in routes.rb:
scope '/cs1337' do
get '/login', to: 'sessions#new', as: :login
# etc.
end
which gives me the correct routing. Everything works, but the annoying thing is that all my path helpers have the '/cs1337' prefix, which is unnecessary since the .htaccess rewrite rules add it back in. For example,
login_path # => /cs1337/login
when only
login_path # => /login
is necessary.
I would like to override all of the path helpers to strip off the prefix, using something like
def <override all path helpers>
path = super
path.gsub(%r{^/cs1337}, '')
end
I know the path helpers are dynamically generated, but I can't figure out where start ... I can't even find what module the path helpers are generated in.
Thanks for any help you can offer!
Short answer: No, as far as I can tell.
I couldn't find anything that lets you have the route Rails intercepts be different from the path that the helpers give you. I don't think Rails plays well with .htaccess rewrites.
Do you need the folder name to be in the path? If not, I would remove the scope '/cs1337' do and use something like this StackOverflow post to do domain-specific routes.
If you need it there, I would recommend being okay with the end user seeing "cs1337.mysite.com/cs1337/path".
I have this configuration in the controller in Padrino
MyProject::App.controllers do
get '/' do
handlebars :index
end
get :file, :with => :tokenId do
tokenId = params[:tokenId]
[extra logic]
end
end
GET / works.
GET /file/abc doesn't.
GET /file/:tokenId works!
It looks like :token is not recognized as a parameter placeholder in the route definition.
I've tried
get "/file/:tokenId"
too but with no luck.
I can't find any information on any similar issue, anybody can help? Happy to add more information if needed.
Okay so I am unsure why the change made a difference but camelCase is generally considered poor syntax for variables in ruby.(Padrino may be calling a method such as underscore on your variable i.e.
"tokenID".underscore.to_sym
#=>:token_id
Using underscored_variables instead. (e.g. :tokenID becomes :token_id. This structure also allows for interacting with databases in a nicer way as well since your columns will have names such as token_id not tokenID.
There are uses for camelCasing in ruby and rails such as class naming and generators but trying keep all local and instance variables in lowercase underscore format.
I don't do much work in padrino so I am not 100% sure why this change helped but I am glad I could help.
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.
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.