how to test carrierwave fog google in rspec with setting up the configuration - ruby-on-rails-3

I have below configuration and I wanted to write TC for it in ruby. I am new to ruby and wanted to understand how we can set the configuration of Fog to point to mock and use it in test-case.
class TestUploader < CarrierWave::Uploader::Base
storage :fog
def fog_credentials
{
:provider => 'google',
:google_project =>'my project',
:google_json_key_location =>'myCredentialFile.json'
}
end
def fog_provider
'fog/google'
end
def fog_directory
'{#bucket-name}'
end
def store_dir
when :File
"#{file.getpath}/file"
when :audio
"#{file.getpath}/audio"
else
p " Invalid file "
end
end
end
class TestModel
mount_uploader :images, TestUploader
end
Could someone please assist me from configuring to write and execute the unit test on it with few example. Any help would be really appreciated.

From the test I did, I got the following sample code working with Google Cloud Storage using Fog gem:
require "fog/google"
# Uncomment the following line if you want to use Mock
#Fog.mock!
# Bucket name
bucket = "an-existing-bucket"
# Timestamp used as sample string
test = Time.now.utc.strftime("%Y%m%d%H%M%S")
connection = Fog::Storage.new({
:provider => "Google",
:google_project => "your-project",
:google_json_key_location => "path-to-key.json",
})
# Lists objects in a bucket
puts connection.list_objects(bucket)
#Creates new object
connection.put_object(bucket, test, test)
puts "Object #{test} was created."
It works in production, but fails using mock mode with the following error:
`not_implemented': Contributions welcome! (Fog::Errors::MockNotImplemented)
It seems that it is not implemented as shown at the put_object method definition in the documentation.
Also, this is said in this GitHub issue:
Closing issue. 1.0.0 is out, and we have no more mocks for json backed objects.
Credentials
As shown in the Fog's documentation, to configure Google Credentials you have to them as follows:
connection = Fog::Storage.new({
:provider => 'Google',
:google_storage_access_key_id => YOUR_SECRET_ACCESS_KEY_ID,
:google_storage_secret_access_key => YOUR_SECRET_ACCESS_KEY
})
Mock
In the GitHub - Fog::Google documentation, there is also a minimal config to integrate Fog with Carrierwave.
In order to use the Cloud Storage mock, you can use the following line:
Fog.mock!
connection = Fog::Storage.new(config_hash)
Provider Specific Resources
In the provider documentation section, you will find links to provider specific documentation and examples.
Community supported providers can get assistance by filing Github Issues on the appropriate repository.
Provider
Documentation
Examples
Support Type
Google
Documentation
fog-google-examples
Community
In order to maximize the benefits of open source, you are encouraged submit bugs to Github Issues
In this GitHub example, you could find an implementation for Google Cloud Storage.
Class List
At the RubyGems documentation for fog-google, you can find the class definitions and parameters. For example, the list_objects method:
#list_objects(bucket, options = {}) ⇒ Google::Apis::StorageV1::Objects
Lists objects in a bucket matching some criteria.
Parameters:
bucket (String) — Name of bucket to list
options (Hash) (defaults to: {}) — Optional hash of options
Options Hash (options):
:delimiter (String) — Delimiter to collapse objects under to emulate a directory-like mode
:max_results (Integer) — Maximum number of results to retrieve
:page_token (String) — Token to select a particular page of results
:prefix (String) — String that an object must begin with in order to be returned
:projection ("full", "noAcl") — Set of properties to return (defaults to “noAcl”)
:versions (Boolean) — If true, lists all versions of an object as distinct results (defaults to False)
Returns:
(Google::Apis::StorageV1::Objects)

Related

Rails 3 ActionMailer class loaded but methods not available in controller

Many simmilar Q/A on this topic here and there, but I was unable to find exact solution for my problem. Using Rails 3.0.9 now, and trying to upgrade existing older application(not Rails).
The goal is to send simple email to new clients created by admins.
Have been following this oficial guide (and many others), but with no success.
The issue is, that method(s) defined in this controller, from class 'UserMailer', aren`t recognised from another controller, while class 'UserMailer' itself recognised is(how do I know this, will be explained below):
/app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default :from => "info#xxxxx.sk"
def kokotina # << this is just a dummy method for testing
caf = "ssss"
end
def regMailUsr(nazov, priezvisko, email, pass)
#nazov = nazov
#priezvisko = priezvisko
#email = email
#pass = pass
#url = "http://loyalty2.xxxx.sk"
mail(to: email, subject: 'Vaša registrácia bola dokončená.')
end
end
I have also created View for this mail controller but that is not important right now.
The fragments from clients controller are here:
/app/controllers/clients_controller.rb
# encoding: UTF-8
class ClientsController < ApplicationController
load_and_authorize_resource
.......
def new
#noveHeslo = genHeslo(10) # << I defined this in application_controller.rb and it works
UserMailer.kokotina # << just a dummy method from UserMailer
#client = Client.new(params[:client])
.......
end
.......
def create
.......
if #client.save
#send email to new client:
UserMailer.regMailUsr(params[:client][:fname], params[:client][:lname], params[:client][:email], params[:client][:password]).deliver
.....
end ......
Now how do I know that my class is loaded? If in client controller, I change 'UserMailer' to 'xUserMailer', I will get 'no class or method in ...' error, but without 'x', I get only:
'undefined method `kokotina' for UserMailer:Class'
I also tried to define my methods in UserMailer:Class like this:
def self.kokotina # << this is just a dummy method for testing
caf = "ssss"
end
#or even like this
def self <<
def kokotina # << this is just a dummy method for testing
caf = "ssss"
end
end
#and then tried to invoke this method(s) like this:
UserMailer.new.kokotina
#or simply
kokotina
Strange is, that when I put contents of file '/app/mailers/user_mailer.rb' at the end of 'application_helper.rb' file, just after the end of 'module ApplicationHelper', I get no errors but of course, it won`t work.
Please keep in mind that I have no problem coding in another languages, but this mystic/kryptic rules of Ruby on Rails are still a complete mistery to me and unfortunatelly, I don`t have time or even motivation to read time extensive quides or even books for RoR beginners. I have been coding much more difficult applications and implementations, but this heavily discriminating system is driving me nuts.
Thank you all!
Problem solved!
The trick was, that in '/app/mailers/user_mailer.rb', I had multibyte characters. In mail subject.
So I added:
# encoding: UTF-8
at the very first line of '/app/mailers/user_mailer.rb'
I found this by total accident: later my rails app could not start, and server was simply throwing HTTP 500 error. So no trace, error defining etc.
I found out that multibyte string in:
mail(to: email, subject: 'Vaša registrácia bola dokončená.')
Was responsible for crash. When I removed that string, I noticed one important side effect: my methods became magicaly available for another controller!!!!
So if someone could give me at least one reason to lowe Rails...

Add session id to each log in Rails

Is there a way to add the session id to each log in Rails.
Now, I've added this in my environment.rb:
class Logger
def format_message(severity, timestamp, progname, msg)
"#{timestamp.to_formatted_s(:db)} #{severity} #{msg}\n"
end
end
First of all, is this best-practice? And how do I add the session id?
Unfortunately, giving :session_id to log_tags don't work yet (as of May 23 2012), since there is no session_id in Rack middleware.
Since log_tags array accept a Proc object, and the proc object is invoked with a request object, I could configure the log_tags following way:
config.log_tags = [ :uuid, :remote_ip,
lambda {|req| "#{req.cookie_jar["_session_id"]}" } ]
It's working with Rails 3.2.3, with ActiveRecord's session store is in use.
when you are working with rails 3.2 you can use log tags:
Update Rails::Rack::Logger middleware to apply any tags set in
config.log_tags to the newly ActiveSupport::TaggedLogging
Rails.logger. 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 DHH
with some luck, adding this to your environment might work:
config.log_tags = [:uuid, :remote_ip, :session_id]
UPDATE
for the unlucky, the solution is from the answer of #shigeya.
unfortunately rails does NOT provide a way to access your sessionid in a sane manner.
you always have to rely on what rack is doing in it's internals... accessing the cookie_jar with your cookie key is the "recommended" way of doing so.
this is what i use for my application:
config.log_tags = [
:host,
:remote_ip,
lambda { |request| "#{request.uuid}"[0..15] },
lambda { |request| "#{request.cookie_jar["_session_id"]}"[0..15] },
]
output then looks like this:
[hamburg.onruby.dev] [127.0.0.1] [27666d0897c88b32] [BAh7B0kiD3Nlc3Np] Completed 200 OK in 298ms (Views: 286.2ms | ActiveRecord: 9.2ms)
For Rails 3.2 with ActiveSupport::TaggedLogging, if you're using :cookie_store:
config.log_tags = [ :uuid, :remote_ip,
lambda { |r| "#{r.cookie_jar.signed["_session_id"]["session_id"]}" } ]
Note: Change the "_session_id" with your :key value at config/initializers/session_store.rb
Unfortunately this isn't easy with Rails log tags. Moreover, it clutters your logs to the point where they are unreadable.
I'd recommend something like timber, it captures session ids (and more) by simply augmenting your logs with metadata. It's automatic and you don't lose readability.

Dropbox API working, now trying to copy images to Amazon S3 with carrierwave

I have an ipad app that uses dropbox to sync images to the cloud so that i can access them with a webapp and process them etc etc.
the part i'm having trouble with is getting the file from dropbox to s3 via carrierwave. i have a photo model and i can create a new photo and upload and an image successfully. I can also put a file on dropbox. However when i try to get a file off of dropbox and put it on s3, the contents of the file is just text.
Are there some sort of mime types i need to set or something?
I am using dropbox_sdk and the get_file_and_metadata method. It returns me the file object successfully, but the contents are all just text. this is me hard coding the image file so i can be sure it exists..
dbsession = DropboxSession.deserialize(session[:dropbox_session])
#client = DropboxClient.new(dbsession, ACCESS_TYPE) #raise an exception if session not authorized
#info = #client.account_info # look up account information
#photo = Photo.new(params[:photo])
#db_image metadata = #client.get_file_and_metadata('/IMG_1575.jpg')
the part i don't know how to do is say take this image #db_image and use that file when creating a new photo and store it on S3.
I'm thinking it might be a 'mime type' issue, but i've read that that is only based on the file ext.
any insight you guys could share would really help me get past this hurdle. thanks!
Figured this out. Instead I used the direct_url.url method that is part of the dropbox-api gem used with the carrierwave gem. the direct_url.url method returns a secure full url path to that file that you can use as the remote_url value for carrierwave.
#client = Dropbox::API::Client.new(:token => 'derp', :secret => 'derp')
#dropbox_files = #client.ls "images/#{#event.keyword}/#{photo_size}/"
#dropbox_files.each do |f|
photo_exists = Photo.where(:dropbox_path => f.direct_url.url).count
if photo_exists == 0
#photo = Photo.create(:remote_filename_url => f.direct_url.url,
:dropbox_path => f.direct_url.url,
:event_id => #event.id)
end
end
Now, i'm pretty new at ruby, so i'll be posting a better way to step through the results, as that seems pretty slow and clunky.

Seeking finer-grained logging options in Rails. How can I log entire requests and/or individual filters to alternative log files?

This is a two part question, but may have the same answer.
Part One:
In our app, one particular controller get hit a lot -- so much so that we'd like to it be logged in a file separate from all other requests. Setting the FoosController.logger is not what I'm looking for, because the request exercises some lib files and active record object that have their logger object, and rails will log some info before handing control to the controller in question.
Part Two:
We have a global before filter included in our root application_controller.rb that is run before most actions of most controllers. This before_filter is very wordy in the logs, and is a candidate for having all its logging info sent to a separate file. This before filter also calls out to libs and ActiveRecord code with their own refererences to the logger.
One possible solution is to run the single controller as its own standalone application. I haven't tried it yet, because it's pretty tied into the internals of app. This approach also would not help with the before_filter.
Are there any good solutions for more fine-grained logging in rails apps?
Thanks!
For part I
I recommend creating your own logger class (possibly inheriting from the ruby logger (1), have the logger filter out the request url and based on that log to a specific file.
For part II
the easiest solution would be to just use a seperate logger for these methods. Instead of logger.debug "your message" you just call method_logger.debug "your message".
Creating your own logger is simple, just use the ruby logger class (1). The following code creates a logger that logs to a my_method.log file in the logs dir of your rails application.
method_logger = Logger.new(Rails.root.join('logs','my_method.log')
You can then write to your log with the following command, which should look familiar to you as rails uses the Ruby logger as well.
method_logger.debug "your debug message here"
(1) http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html
Here's the code for a custom logger that you can use to solve Part I. I adapted it for my own use from another Stack Overflow question, even including the answerer's inline comments. The main difference is that you can specify a different log path for development and production:
# app/concerns/event_notifications_logger.rb
class EventNotificationsLogger < Rails::Rack::Logger
def initialize(app, opts = {})
#default_logger = Rails.logger
#notifications_logger = Logger.new(notifications_log_path)
#notifications_logger.formatter = LogFormat.new
#notifications_logger.level = #default_logger.level
#app = app
#opts = opts
end
def call(env)
logger = if env['PATH_INFO'] == '/event_notifications/deliver'
#notifications_logger
else
#default_logger
end
# What?! Why are these all separate?
ActiveRecord::Base.logger = logger
ActionController::Base.logger = logger
Rails.logger = logger
# The Rails::Rack::Logger class is responsible for logging the
# 'starting GET blah blah' log line. We need to call super here (as opposed
# to #app.call) to make sure that line gets output. However, the
# ActiveSupport::LogSubscriber class (which Rails::Rack::Logger inherits
# from) caches the logger, so we have to override that too
#logger = logger
super
end
private
def notifications_log_path
Rails.env.production? ? '/var/log/event-notifications.log' : Rails.root.join('log/event-notifications.log')
end
end
Then include it in your application configuration:
require File.expand_path('../boot', __FILE__)
require 'rails/all'
require File.expand_path('../../app/concerns/event_notifications_logger', __FILE__)
module YourApp
class Application < Rails::Application
config.middleware.swap Rails::Rack::Logger, EventNotificationsLogger
# ...
end
end
Rails 3.2 provides filter options for the logs, called "Tagged Logging".
See the announcement or the new Rails 3.2 guide on ActiveSupport.

Rails 3 Carrierwave-Fog-S3 error: Expected(200) <=> Actual(404 Not Found)

I'm using Carrerwave 0.5.3 and getting a 404 error on my call to Picture.save in the Create method of my picture controller. Per the instructions in lib/carrierwave/storage/s3.rb I have the following in my initialization file (config/initializers/carrierwave_fog.rb):
CarrierWave.configure do |config|
config.s3_access_key_id = "xxxxx"
config.s3_secret_access_key = "xxxxx"
config.s3_bucket = "mybucket" #already created in my S3 account
end
In photo_uploader.rb I have:
class PhotoUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :s3
def store_dir
"uploads" # already created in my s3 account
end
def cache_dir
"uploads/cache" #already created in my s3 account
end
end
The exact error:
Excon::Errors::NotFound in PicturesController#create
Expected(200) <=> Actual(404 Not Found)
request => {:expects=>200}
response => #<Excon::Response:0x00000104a72448 #body="", #headers={}, #status=404>
I found a slightly similar question here Carrierwave and s3 with heroku error undefined method `fog_credentials=' . But setting things up the way I have it now apparently worked in that case. Unfortunately it didn't for me.
I've put a picture in my bucket and set the permissions to public and can access the picture via a browser. So things on the AWS S3 side seem to be working.
Not sure where to go next. Any ideas?
Well, I slept on this for a night came back the next day and all was good. Not sure why it suddenly started working.
Make sure your file names are sanitized and do not contain invalid characters like spaces or slashes.
To sanitize a string you can call the gsub method on it. The following method call will sanitize files for upload to S3, Google Cloud Storage etc.
"Invalid\ file *& | | name.png".gsub(/[^0-9A-z.\-]/, '_')