Passing multiple arguments to Rack middleware in Rails application.rb - ruby-on-rails

I am creating a Rack Middleware which I want to use in my Rails App. Basically, I need to log requests matching particular urls to my Database. In order to do this I need to pass database configuration to my Middleware so it can establish connection with DB. I am trying to do:-
db_yml = Rails.root.join('config/database.yml')
db_config = YAML.load(db_yml.read)[Rails.env]
But this is giving an error
config/application.rb:40:in <class:Application>': undefined methodread' for # (NoMethodError)
If I add byebug and run the same in the byebug console it works fine. I am not able to find out why. I want to do following things:-
I need to read & modify the database configuration before passing it to my middleware as argument.
I want to read the domain of the request url. We are using Apartment gem and Our schema name will be the domain name.
I followed multiple articles here & here.
I am a newbie to Rails and don't know good resources so please help.
Thanks in advance!

You should use:
db_yml = Rails.root.join('config/database.yml')
db_config = YAML.load(File.open(db_yml))[Rails.env]
Rails.root.join('config/database.yml') return the file path which is a string.

Related

Apartment gem - Adding current database to all server logs

I am using the Apartment gem to switch the tenant (database) being used for a multi tenancy Rails application.
In my server logs I would like to output the current tenant (database) being used for every single line in the log file.
When I do rails s the server never actually starts with the code below that is in the initializers directory. The server just hangs... so odd. No error message and no running server. If I take out #{Apartment::Tenant.current} below everything is fine... but... I really want to know the current tenant (database) in my log files.
/initializers/log_formatting.rb:
class ActiveSupport::Logger::SimpleFormatter
def call(severity, time, progname, msg)
"#{Apartment::Tenant.current} #{msg.strip} (pid:#{$$})\n"
end
end
Any ideas on how to get the current tenant (database) being used output to every line of my log file?
Thank you!
I would suggest you to use log_tags.
From the rails documentation :
config.log_tags accepts a list of: methods that the request object responds to, a Proc that accepts the request object, or something that responds to to_s. This makes it easy to tag log lines with debug information like subdomain and request id - both very helpful in debugging multi-user production applications.
You can add this configuration in application.rb or production.rb whichever fits your need.
For ex: config.log_tags = [ :subdomain, :request_id, lambda { |request| request.headers["tenant_name"] } ]
Note: In case you are adding this for development environment and you are running on your_subdomain.localhost:3000 then subdomain won't be present as localhost doesn't support subdomains. There are some workarounds like modifying /etc/hosts file but i won't recommend it. The more cleaner solution is to use your_subdomain.lvh.me:3000

Dynamic domain name in Rails action mailer while using sidekiq

In my requirement ,there are different domain names for single project.I would like to send reset password link with a domain name where the user requested for the reset password.For that I have done the follows in application_controller.rb and it works well.
before_filter :set_mailer_host
def set_mailer_host
ActionMailer::Base.default_url_options[:host] = request.host_with_port
$url_host = request.host_with_port
end
Later,I have used sidekiq for delayed mailer and updated like follows on entire application
Notifier.delay.password_reset(user.id)
As the mailer was configured with sidekiq it was using default domain name provided in configuration only and it was not using the dynamic domain name provided from request on application_controller.rb
Any suggestion to get the dynamic domain on mailers running by sidekiq would be greatly appreciated.
Rails - 3.2.8
Ruby - 1.9.3
sidekiq - 2.13.1
Thanks!!!
One of the options would be to associate each user with a domain and use this information when sending the email in sidekiq.
You'll need to construct the url yourself rather than rely on AM to do it for you.

uninitialized constant UploadsController::Bucket when trying to write general AWS::S3 Upload controller

I'm trying to write a general Amazon S3 uploader (will be used mostly for images) for my rails project. I was able to set up the environment in my console following http://amazon.rubyforge.org/.
I was able to follow the guide in the console. However, I had trouble when I applied it to my rails project. When I try to access my new view, I get the following error:
NameError in UploadsController#new
uninitialized constant UploadsController::Bucket
Here is my controller:
class UploadsController < ApplicationController
require 'aws/s3'
def new
photo_bucket = Bucket.find('photos')
#photos = photo_bucket.objects
end
def create
file = 'black-flowers.jpg'
S3Object.store(file, open(file), 'photos')
end
end
In my controller, my new action will contain the form for the upload and a list of all the photos.
My create action will just save the file. I haven't figured out how the params from the form will be passed into the controller yet, so ignore the 'black-flowers.jpg' line.
My guess is that I did not establish a connection in the controller.
How do I establish a connection or fix this error?
Thanks for looking.
Bucket is not a top level constant in this case. You probably want the AWS::S3::Bucket constant for new, and I'd assume something similar for S3Object.
Note that you may also want to look into the Fog library for this.
The fact that you haven't figured out how params will be passed in implies that you may also want to work through the Rails tutorials without S3 first.
I had a similar issue and it was solved by just checking all files required were provided and restarting the server

Ruby on Rails Directory Path

I need to print Ruby on Rails complete url in my application. in details
with RAILS_ROOT I m getting a url like this
D:/projects/rails_app/projectname/data/default.jpg
But for my application I need a path like this
http://localhost:3000/data/default.jpg
Please help me to solve this issue. I am using Rails 2
Thanks
Today we use URI. Simply require the library and you will be able to parse your current dynamic and static URI any way you please. For example I have a function that can read URI parameters like so...
#{RAILS_ROOT}/app/helpers/application_helper.rb (The literal path string of the file depicted below)
def read_uri(parameter)
require 'uri'
#raw_uri = URI.parse(request.original_fullpath)
#uri_params_raw = #raw_uri.query
if #uri_params_raw =~ /\=/
#uri_vars = #uri_params_raw.split('=')
return #uri_vars[parameter]
end
return false
end
This should split all URI parameters into an array that gives the requested (numeric) "parameter".
I believe that simply the URI.parse(request.original_fullpath) should work for you.
I come from using a minimum of rails 4.2.6 with this method so, I hope it works for anyone who might view this later on. Oh, and just as a disclaimer: I wasn't so wise to rails at the time of posting this.

Rails - How to obtain an absolute URL for the site? https://example.com

For one of my models I have a method:
def download_url
url = xxxxx
end
which works nicely to make /xxxx/xxxx/3
What i want to do is updated this to include an absolute URL so I can use this method in an email:
https://example.com/xxxx/xxxx/3
But I don't want to hard code. I want it to be an environment var so it works on dev & production
Emails are effectively views, and can use helpers. The model shouldn't really have any knowledge about the views - instead, you should use url_for or one of its descendant methods in the email view template to generate a URL. Those helpers can generate absolute URLs based on the location that the application is running (and associated configuration - you'll want to set config.action_mailer.default_url_options[:host] in your environment file) without having to mess with environment variables and the like.
I would define the domain as a constant in development.rb & production.rb:
APP_DOMAIN = "https://mysite.com"
And then just use this constant in your method within the model:
def download_url
"#{APP_DOMAIN}/download/#{id}"
end
It may be ugly, but it's necessary. Rails apps don't and shouldn't know their root URL. That's a job for the web server. But, hardcoding sucks...
If you're using capistrano or some other deployment method, you can define the server host in a variable and write it out to a file that you can read from the app.

Resources