Sinatra - how do I get the server's domain name - ruby

I'm trying to get the domain name in my Sinatra app but as a newbie I really am struggling to figure out how to do this, and I know it must be possible!
Rack::Request#host_with_port looks promising, but I don't know how to get this from my app - how do I get stuff from Rack in my Ruby code?
Or is there another way - I'm thinking I don't really want to do this every time a request happens (although it's not too bad), but I thought it'd be better if I could just do it once when the application loads up.
Any hints?

simply use request.host inside your code.
get "/" do
puts request.host #=> localhost
end

Take a look at:
request.env.inspect
so you can see all the request environment variables.
I think that you are looking for
request.env["SERVER_NAME"]

Related

about Sinatra on multiple Resources

Sorry to ask such a simple question but I didn't see any possible answer in internet.
I just wondering in Sinatra, can I write something like:
get '/users/:user_id/posts/:id' do
xxx
end
just like rails? cause when I write this on my rb file, sinatra keep telling me it didn't know this ditty.
thank you
A (horrible) example from one of our legacy systems.
get '/is_type/:type/id/:id' do
store.valid_for_type?(params)
end
Multiple placeholders in a route is totally fine in Sinatra. It sounds like your config.ru is wrong, you're issuing a POST, or you're calling the wrong endpoint entirely. Can you update your post with an example of the request you are issuing?

What is rack? can I use it build web apps with Ruby?

ruby newbie alert! (hey that rhymes :))
I have read the official definition but still come up empty handed. What exactly is it when they say middleware? Is the purpose using ruby with https?
the smallish tutorial at patnaik's blog makes things clearer but how do I do something with it on localhost? I have ruby 1.9.2 installed along with rack gem and mongrel server.
Do I start mongrel first? How?
Just to add a simplistic explanation of Rack (as I feel that is missing):
Rack is basically a way in which a web app can communicate with a web server. The communication goes like this:
The web server tells the app about the environment - this contains mainly what the user sent in as his request - the url, the headers, whether it's a GET or a POST, etc.
The web app responds with three things:
the status code which will be something like 200 when everything went OK and above 400 when something went wrong.
the headers which is information web browsers can use like information on how long to hold on to the webpage in their cache and other stuff.
the body which is the actual webpage you see in the browser.
These two steps more or less can define the whole process by which web apps work.
So a very simple Rack app could look like this:
class MyApp
def call(environment) # this method has to be named call
[200, # the status code
{"Content-Type" => "text/plain", "Content-length" => "11" }, # headers
["Hello world"]] # the body
end
end
# presuming you have rack & webrick
if $0 == __FILE__
require 'rack'
Rack::Handler::WEBrick.run MyApp.new
end
You would do well to search for other questions & answers that make sense to you. Try "Getting Started with Rails" or "Ruby Web Development". A lot of different topics on this site have been devoted to this exact subject, so you might save yourself some trouble there...
Ignoring the specifics of your question for a minute, it seems like you want to learn Ruby and build web apps. Before you start delving into Rack or Mongrel or anything else, you should know that there are 2 well established frameworks that help build Ruby web applications. The first is Ruby on Rails, and the other is Sinatra. There are many others, but these are the most well documented on Stack Overflow and the internet in general.
Check out the following links for some background...
www.rubyonrails.org
SO: building-a-website-best-practice-and-architecture-with-ruby
www.railstutorial.org
SO: learning-ruby-on-rails
If you still have a burning desire to answer your question - "what is rack?", you should follow the same process, and end up at this Stack Overflow Answer:
What is Rack middleware?
Good luck!
Very nice answers yes indeed. For my two cents I'll add this because if you know how to get to the documentation behind the scenes here you will find lots of information as I have it stashed here and by no means is all that I have.
http://myrackapps.herokuapp.com/

Camping's URL() doesn't give me "site root" as expected?

Due to circumstances beyond my control, my production Camping site appears at mysite.example.com/mysite. I'm pretty sure this is a common Apache / Passenger configuration issue, and I'm not interested in how to fix it right now because the server is out of my control. Suffice to say, the controller for "/" points there and I can't change that any time soon.
Now, for a long time, this wasn't an issue, because R(MyIndexController) points to the correct place. However, I serve my site's CSS using a Rack::Static call to make $SITE_ROOT/public accessible. This means that the stylesheet is at mysite.example.com/mysite/css/style.css. Here's where the problem comes in: the Camping URL() method, when called in my layout, gives http://mysite.example.com, not http://mysite.example.com/mysite. So I can't get it to point to the /css subdirectory, because it's missing a "hop" in the middle. When I run rackup locally, everything is fine (because this file is at localhost:8080/css/style.css), but on the production server I don't know how to fix it.
My question: is there another method (maybe directly from Rack?) that I should be calling instead? I really want to avoid hardcoding it, and/or having a hack to determine whether I'm running locally (for debug) or in production, for every rendering of the layout.
ETA: OK, this gets stranger. Obviously I've abstracted out some of the actual details above, part of which I think I "over-scrubbed". The "top level" URL is actually more akin to /mysite/rest (the developer-centric HTML presentation of our RESTful interface), as opposed to /mysite/management (accounts) or /mysite/ui (JQuery'd / "nice" UI). These are set up in our config.ru, via run Rack::URLMap.new(Hash['/rest' => RestModule, '/ui' => PrettyInterfaceModule, '/management' => UserManagerModule], etc.
So in answer to the comment below, R(Index), from a view in the RestModule, actually returns /mysite/rest/. As an example, I have a "home" link in the layout, which looks like a :href=>R(Index), and generates code that looks like <a href="/mysite/rest/">. The server is configured to serve files from ./public directly at the "site root", so ./public/css/style.css actually does apppear at http://mysite.example.com/mysite/css/style.css, as noted previously. It's that link that I'm having trouble automatically generating, and it's because of the Rack::URLMap that I thought I may have to rely on a native Rack method (not a Camping abstraction) to locate this resource.
So in this case, URL() actually returns http://mysite.example.com/mysite/rest/?
What about something like this?
URL().merge('../css/style.css')
This is an old question so I assume that you did already find a workaround but the new passenger + apache (or ngnix) behaves correctly for camping as far as I could replicate. Your app would be on the Documents root and all the includes in the /public folder so /public/css should be routed correctly regardless of you using a sub folder /mysite or not as passenger doesn't make a difference (again) as far as I can replicate. Therefore this should be easily solvable with passenger 3 + Apache or ngnix.

Ruby: Get currently logged in user on windows

In C# I can get the current user of a web app using the HttpContext, however, I can't figure out how to do this in Ruby. Is there any way of doing this?
FOR THOSE OF YOU SAYING IT IS IMPOSSIBLE, HERES PROOF:
http://www.codeproject.com/KB/aspnet/How_to_NT_User_Name.aspx
Well, to get the current username, there's this:
puts ENV['USERNAME']
Or go to the Win32API.
require 'dl/win32'
def get_user_name
api = Win32API.new(
'advapi32.dll',
'GetUserName',
'PP',
'i'
)
buf = "\0" * 512
len = [512].pack('L')
api.call(buf,len)
buf[0..(len.unpack('L')[0])]
end
puts get_user_name
Edit: And I'm an idiot. This isn't what you asked for at all. Oh well, it took me time to dig this out of my code, so it might as well stay here for anyone else wondering :P
Edit again: OK, it turns out I'm not an idiot after all. This is what you want. When I went back and re-read your question, the HttpContext threw me off, and I thought it was the current username from HTTP auth or something.
To get the username of the current user on client machine you can use this
ENV['USERNAME']
If you're using Rails try: request.env['HTTP_REMOTE_USER']
I think what you mean is how you can retrieve the username that the user used to login to the web application. That will differ depending on what authentication mechanism you're using. Some Apache authentication modules, for example, will pass REMOTE_USER (e.g. the Kerberos module), the CAS Single-Sign-On module passes CAS-USER, etc. Standard digest authentication and such uses the Authentication header. You should be able to access these using request.env[HEADER] as someone else pointed out above. Check out the documentation on how your authentication layer is passing on the user in the HTTP request.
Is your c# code running as a .NET plugin/client-side code or is it ENTIRELY server side? Your ruby code would be entirely server side. According to the MS docs, only stuff running in the CLR sandbox can really get to that information:
http://msdn.microsoft.com/en-us/magazine/cc163700.aspx (under Defining the sandbox).
One thing interesting to note is that sites registered under LocalIntranet have access to that information. I'm not sure off hand how this maps to security zones in IE though.
The thing to understand is that LOGON_USER is NOT visible to the browser sandbox anymore than the browser can see the contents of a filesystem path on your system. The fact that your c# code sees it almost certainly indicitive of some clientside component passing it upstream.
You have the option of implementing mod_ntlm under apache and pushing the headers downstream. I don't have the points to post a second link but google 'rails ntlm sso' and see the rayapps.com link.
but if your app isn't Rails based, you'll have to port that to your server code. You can also checkout rack-ntlm if your app is rack compliant.
[RUBY ON RAILS ONLY]
This is what worked for me but there are some limitations:
won't work in Chrome: undefined method 'encode' for nil:NilClass
won't validate user credentials
If you don't care about these issues, go ahead:
In your rails application, add Rekado's gem to your Gemfile: gem 'ntlm-sso', '=0.0.1'
Create an initialiser config/initializers/ntlm-sso.rb with:
require 'rack'
require 'rack/auth/ntlm-sso'
class NTLMAuthentication
def initialize(app)
#app = app
end
def call(env)
auth = Rack::Auth::NTLMSSO.new(#app)
return auth.call(env)
end
end
On your application.rb file, add the line: config.middleware.use "NTLMAuthentication"
Call request.env["REMOTE_USER"] on your view or controller to get current username.
PS: Let me know if you find anyway to make it work on Chrome or to validate user credentials.

A copy of ApplicationController has been removed from the module tree but is still active

Whenever two concurrent HTTP requests go to my Rails app, the second always returns the following error:
A copy of ApplicationController has been removed from the module tree but is still active!
From there it gives an unhelpful stack trace to the effect of "we went through the standard server stuff, ran your first before_filter on ApplicationController (and I checked; it's just whichever filter runs first)", then offers the following:
/home/matchu/rails/torch/vendor/rails/activesupport/lib/active_support/dependencies.rb:414:in
`load_missing_constant'
/home/matchu/rails/torch/vendor/rails/activesupport/lib/active_support/dependencies.rb:96:in
`const_missing'
which I'm assuming is a generic response and doesn't really say much.
Google seems to tell me that people developing Rails Engines will encounter this, but I don't do that. All I've done is upgrade my Rails app from 2.2 (2.1?) to 2.3.
What are some possible causes for this error, and how can I go about tracking down what's really going on? I know this question is vague, so would any other information be helpful?
More importantly: I tried doing a test run in a "production" environment just now, and the error doesn't seem to persist. Does this only affect development, then, and need I not worry too much?
This is a bug in Rails 2.3.3:
https://rails.lighthouseapp.com/projects/8994/tickets/2948-exception-a-copy-of-actorscontroller-has-been-removed-from-the-module-tree-but-is-still-active
There is a patch for it (but incomplete?) in 2-3-stable:
http://github.com/rails/rails/commit/d37ac7958fc88fdbf37a8948102f6b4e45c530b3
You have a few options to address the problem:
Revert to Rails 2.3.2, wait for 2.3.4 to come out, probably at the end of August. 2.3.3 has a couple bad issues, so that might be best.
The problem should not happen in production mode, nor will it happen in development mode under the Thin server. If you are having this issue on Google Engines in production mode, the patch is your only hope. If it's only in dev mode, you can just run your local server with Thin instead of Mongrel.
If it is Google Engines, you can move off of Google Engines and host your app another way. This seems like a lot of work though.
Best of luck, this is a really bad bug many people are running into.
I addition to the workarounds mentioned in the other answers, I have encountered two others:
Add "config.cache_classes = false" to your config/environments/development.rb file. This has the unfortunate side effect of requiring you to restart your server whenever you want to see your changes.
Add 'unloadable' inside your controller classes in your engine. See http://strd6.com/?p=250 and http://dev.rubyonrails.org/ticket/6001
I haven't tried the second approach, since I found the other solution first, but there is of course a trade-off between avoiding having to edit plugin code, which may be reverted if a newer version of the plugin is downloaded, and then the ease of development provided by not having to restart the development server all the time in the second solution.
i faced with same problem for my new engine on rails 2.3.4 and i found solution here.
calling unloadable method solved my problem.
Weird.
Trying running "rake rails:update" to make sure the configs are scripts are up to date. You may have to check the existing ones against a template application.
i had this error and from memory it was one of one of these three things that fixed it.
1) I needed to update mongrel/rack
2) I had an environment variable from restful authentication that i had moved into the production.rb and development.rb files from the environment.rb - shifting it back to environment.rb seemed to help
3) will_paginate was out of date
We called out to an activerecord model in a namespaced module which overrides the "name" class method. Rails expects that the name method returns Product::Categories::MilkProducts::Firstproduct but gets just Firstproduct and throws an error. So if you get this error first check if you redefined self.name.
Firstproduct.method(:name).owner should be Module
Firstproduct.method(:name).source_location
source:
module Product::Categories::MilkProducts
class Base
def self.name
self.to_s.demodulize
end
end
class Firstproduct < Base
self.product = Product.first
end
end

Resources