Accessing request context object in rails router - ruby-on-rails

I need to create a few dynamic routes in my rails router in the following way:
Rails.application.routes.draw do
account = Account.find_by(
subdomain: request.subdomain,
domain: request.domain
)
EditableField.where(account_id: account.id).links.each do |link|
get link.link_href, to: link.method
end
end
As shown above, I need to determine the account based on the request domain and subdomain, however I cant find how to access the request object in the rails router. What is the correct way to do this ?

I would suggest using the rack-rewrite gem
https://github.com/jtrupiano/rack-rewrite
It is in lower level and give you much more options to do this kind of dynamic routing
And if you still want to do that in the routes.rb file, you can follow this answer https://stackoverflow.com/a/24411835/2529330
Enjoy :)

Related

Rails 4 Routing within Namespace

I am trying to set the base address www.myplace.com/admin to be directed to www.myplace.com/admin/adminhub within the namespace coding below. I have tried every combination I can think of, but to no avail. I was trying to follow the same code used for the / of the app.
namespace :admin do
...
get "adminhub"
get 'admin', to: 'adminhub'
end
Sounds like you want to redirect the browser to the new URL. You can do this with the redirect helper in the routes.
get '/admin', to: redirect('/admin/adminhub')
This allows you to redirect from one path to another. See the Redirection section in the Rails Routing Guide for more details.

Get absolute URL with Grape-Api gem on Rack app

I'm doing an API with grape gem, in one of my services I would like to retrieve the complete URL. For example if the user does request on :
api.myapp.com/android/users.json
I would like be able to retrieve api.myapp.com/android/users.json or at least /android/users.json
class MyApp::API::Users < Grape::API
resource :users do
get do
request.original_url
# stuff ...
end
end
end
I tried what I know from Rails, but now it's Grape and it doesn't work :
"error": "undefined method `original_url' for #<Grape::Request:0x00000005a78c08>"
I wanted to do the same thing (generate absolute URIs) within my own API and after much research, I eventually gave up. There is, amazingly, no good way I can find to get the information you're looking for out of Grape—you cannot, for instance, specify a resource is "mounted" at a specific path and then retrieve that information later.
What I wound up doing in the meantime was saving the base URL (scheme, hostname and port) in a global variable at the start of each request:
before do
# Save the base URL of the request, used by resources to build
# their canonical URI
Resources::base_url = request.base_url
end
and then, within each resource representer, "manually" assembling the URI using hardcoded path information:
link :self do
RideYork::API::Resources::base_url +
"/resources/agencies/#{represented.id}" if represented.id
end
It's a terrible hack, but I'm not aware of a better solution.
Grape::Request is just a Rack::Request. It looks like the Rack::Request has a #url method you could try.

How do I write a full path in a controller in Rails 3?

I need to write the full path so need to know what the rails_root domain is. How do I do that? For example:
string = "{RAILS_ROOT}/vendors/#{#vendor.id}"
What is the equivalent of "RAILS_ROOT" to give me what the full domain is for my application? So that in development it would subsstitute localhost:3000 and on my heroku site the right full domain?
You should always avoid, if possible, hard-coding your path, because it is less flexible and more prone to result in broken links in the future. Plus, you can use Rails routing, which is an elegant way to generate everything cohesively in Rails without any need to create the composite parts yourself.
If you have your routes set up properly, you should be able to call:
link_to "View vendor", vendor_url(#vendor.id)
Vendor_url(#vendor.id) in Rails gives you your full URL, which you can then contain in your string variable. Here's how to generate the routes needed for the above:
# in routes.rb
resources :vendors
Try:
File.realpath(RAILS_ROOT)
You could access the request object. request.host_with_port would give you the hostname and port. request.protocol will give you the protocol (http:// or https://). request.fullpath will give you the path with query params.

How to get the subdomain value from a url?

how can I get the subdomain value in rails, is there a built-in way to do this?
e.g.
test123.example.com
I want the test123 part of the url.
Rails 3.0 has this capability built-in, you can access the subdomain from request.subdomain.
You can also route based on the subdomain:
class SupportSubdomain
def self.matches?(request)
request.subdomain == "support"
end
end
Basecamp::Application.routes do
constraints(SupportSubdomain) do
match "/foo/bar", :to => "foo#bar"
end
end
If you're using 2.3, you'll need to use a plugin such as subdomain-fu.
Use the following method inside your controller
request.subdomains
This Returns an array of subdomains
account_location is also a good plugin. After using it, you can find the account based on different subdomains. And you can find out subdomain from url just by writing request.subdomains(0).first in your code.
In case you are working with a string, and assuming it can be a true URI, you can do this to extract the subdomain.
require 'uri'
uri = URI.parse('http://test123.example.com')
uri.host.split('.').first
=> "test123"
https://stackoverflow.com/a/13243810/3407381
Simple in your controller just do the following
unless request.subdomains.any?
#No domains available redirect
redirect_to subdomain: 'www'
end
You can use the SubdomainFu plugin. This plugin gives you a method current_subdomain which returns the current_subdomain of your app.
You can also have a look at this Railscast
UPDATE
You can also use request.subdomains this will give you an array of subdomains.
For anyone looking to get the subdomains on localhost using WEBrick:
Put config.action_dispatch.tld_length = 0 into config/environments/development.rb and everything should work.
Link to SO post here:
Can I make Rails / WEBrick recognize entries in /etc/hosts as subdomains (instead of domains)?
Link to Github post:
https://github.com/rails/rails/issues/12438
current domain with subdomains:
"#{request.subdomain}.#{request.domain}"
# or
"#{request.subdomains.join(".")}.#{request.domain}"
A bit late to the party but here's what I used in older versions of rails.
subdomain = request.subdomains.join('.')
It should be backwards compatible in newer versions

Support for multiple domains/subdomains in Rails

I have a Rails app that has a similar setup to Tumblr, that is, you can have either:
(1) Subdomain hosting (your-username.myapp.com)
(2) Domain hosting (your-username.com)
Both would forward to a personalized website for that user, created with my application.
How can I accomplish this in Rails? I have been able to get (1) working with subdomain-fu, but I'm not sure how to get (2) working. Any pointers (plugins, gems, tutorials), etc. would be greatly helpful, I can't seem to find any.
Thanks!
The principle for domains is the same as the subdomain - find the domain, map to an account.
The details will depend on how your hosting is going to handle the DNS.
I am currently using Heroku and its wildcard service.
In this case, the domain is mapped with a cname to the subdomain hosted by my Heroku app. From here I can work out the associated account and details.
EDIT: I've found a much easier way: http://www.arctickiwi.com/blog/7-host-and-domain-based-routing-in-ruby-on-rails
Not exactly an answer but this is the best I can give. Maybe this'll help you too.
Ideally, this blog post from transfs.com and subdomain-fu should do the trick. I've been trying to implement it, however, and they don't seem to play nicely together.
Basically, if I don't include the intiializer, the subdomain route works fine. If I include the initializer, the subdomain route breaks (everything gets caught by map.root). I have a feeling it's with the way it builds the condition string in the initializer. If you can figure out how it breaks, then you'll have a working app.
My initializer:
module ActionController
module Routing
class RouteSet
def extract_request_environment(request)
env = { :method => request.method }
env[:domain] = request.domain if request.domain
env[:host] = request.host if request.host
env
end
end
class Route
alias_method :old_recognition_conditions, :recognition_conditions
def recognition_conditions
result = old_recognition_conditions
[:host, :domain].each do |key|
if conditions[key]
operator = "==="
if conditions[key].is_a?(Regexp)
operator = "=~"
end
result << "conditions[:#{key.to_s}] #{operator} env[:#{key.to_s}]"
end
end
result
end
end# end class Route
end
end
My routes (just for development). You'll see my local development domain, stiltify.dev. Sorry, I tried to make it look good in here but I couldn't get the code block to look nice. I put it on pastie instead: http://pastie.org/940619.
The comments section in Ryan Bates' screencast was very helpful, and got me to figure out the subdomain => false and the other errors they were getting into. Still didn't fix the problem though!

Resources