sending file with pony by sinatra app - missing file - ruby

I want to send a email from my sinatra application.
Here is the code:
require 'pony'
class Cms < Application
get "/mail" do
Pony.mail :to => 'to#gmail.com',
:from => "from#gmail.com",
:subject => "Thanks for signing my guestbook!",
:via => :sendmail,
:via_options => {
:address => 'smtp.gmail.com',
:port => '587',
:user_name => 'user#gmail.com',
:pass => 'pass',
:enable_starttls_auto => false
},
:body => erb(:"cms/mail")
redirect '/'
end
end`
Thin is starting application with no errors, but When i request myapp.local/mail i've got an error:
LoadError - no such file to load -- mail/network/delivery_methods/smtp:
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/configuration.rb:31:in lookup_delivery_method'
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/configuration.rb:25:in delivery_method'
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/mail.rb:111:in delivery_method'
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/message.rb:116:in initialize'
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/mail.rb:50:in new'
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/mail.rb:50:in new'
/var/lib/gems/1.8/gems/pony-1.4/lib/pony.rb:174:in build_mail'
/var/lib/gems/1.8/gems/pony-1.4/lib/pony.rb:138:in mail'
./app/controllers/cms.rb:8:in GET /mail'
File /var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/network/delivery_methods/smtp.rb exists.

I was getting this same error when I was using the inline configuration of the Mail gem:
mail.delivery_method :sendmail
mail.deliver!
Removing that first line, and moving the configuration to immediately following the loading of the mail gem fixed it.
Wherever in your app you require 'mail' just configure it immediately:
require 'mail'
Mail.defaults do
delivery_method :sendmail
end
Update: This worked for awhile... But then for some reason I began seeing this error:
rbenv/versions/1.8.7-p374/lib/ruby/gems/1.8/gems/mail-2.5.4/lib/mail/fields/common/common_address.rb:9:in `parse': no such file to load -- mail/elements/address_list (LoadError)
Update2: The failures happen randomly it seems. Something about the way the autoload works in Ruby 1.8.7-p374 is causing it to not be able to find files that do in fact exist. Also, I am using slimgems not rubygems.
These are the hacks I've had to implement so far to use Mail with multi-part email and sendmail delivery method:
require 'mail'
require 'mail/network/delivery_methods/sendmail'
require 'mail/elements/address_list'
require 'mail/fields/common/common_address'
require 'mail/elements/content_type_element'
require 'mail/elements/address'
require 'mail/elements/content_transfer_encoding_element'
Mail.defaults do
delivery_method :sendmail
end

Related

rails + heroku: point root in routes.rb file to app.rb file

I have a file called app.rb that runs a server when I run it on my local machine. I would like to deploy app.rb to Heroku so the server will run on Heroku. I think I need to make root in routes.rb point it to. How do I do this?
this is the config.ru:
require_relative 'config/environment'
require '/.app.rb'
run Rails.application
run Sinatra::Application
This is the web server code in app.rb, from codepath guides (https://guides.codepath.com/android/Google-Cloud-Messaging#step-3-setup-web-server):
require 'sinatra'
require 'rest-client'
require 'sequel'
# Create a SQLite3 database
DB = Sequel.connect('sqlite://gcm-test.db')
# Create a Device table if it doesn't exist
DB.create_table? :Device do
primary_key :reg_id
String :user_id
String :reg_token
String :os, :default => 'android'
end
Device = DB[:Device] # create the dataset
# Registration endpoint mapping reg_token to user_id
# POST /register?reg_token=abc&user_id=123
post '/register' do
if Device.filter(:reg_token => params[:reg_token]).count == 0
device = Device.insert(:reg_token => params[:reg_token], :user_id => params[:user_id], :os => 'android')
end
end
# Ennpoint for sending a message to a user
# POST /send?user_id=123&title=hello&body=message
post '/send' do
# Find devices with the corresponding reg_tokens
reg_tokens = Device.filter(:user_id => params[:user_id]).map(:reg_token).to_a
if reg_tokens.count != 0
send_gcm_message(params[:title], params[:body], reg_tokens)
end
end
# Sending logic
# send_gcm_message(["abc", "cdf"])
def send_gcm_message(title, body, reg_tokens)
# Construct JSON payload
post_args = {
# :to field can also be used if there is only 1 reg token to send
:registration_ids => reg_tokens,
:data => {
:title => title,
:body => body,
:anything => "foobar"
}
}
# Send the request with JSON args and headers
RestClient.post 'https://gcm-http.googleapis.com/gcm/send', post_args.to_json,
:Authorization => 'key=' + AUTHORIZE_KEY, :content_type => :json, :accept => :json
end
This is the procfile:
web: bundle exec puma -C config/puma.rb
when I follow the getting started with Ruby on Heroku example, I can see the example webpage. However, if I edit the config.ru file with 'run Sinatra::Application', and deploy to heroku, it is not able to show the example webpage anymore, and just says "Not Found"
require '/.app.rb'
This should be ./app.rb instead.

Set cookie expiration time in Ruby

I am using Ruby with Sinatra do develop a web application.
I have Ruby version 2.3.0, Sinatra 5.0.30
Following the suggestions from Rails cookies, set start date and expire date, I tried this:
#language = 'en-US'
response.set_cookie(:USER_LANGUAGE, :value => #language, :expires => 1.hour.from_now, :domain => '.example.com')
At first I thought it worked because the cookie set except the expiration time is still just only for the session. The error in my Apache error log says this:
NoMethodError - undefined method 'hour' for 1:Fixnum:
Please note: none of these worked to resolve the problem (none of them could be properly found by the compiler)
require 'active_support'
require 'active_support/all'
require 'activesupport'
So, I tried this instead:
#language = 'en-US'
response.set_cookie(:USER_LANGUAGE, :value => #language, :expires => 30, :domain => '.example.com')
Just to see what would happen and nothing changed, it still only expires with the session.
How should I go about setting an expiration time for my cookies in Ruby with Sinatra?
Sinatra doesn't have the ActiveSupport library which provides a helper for number-to-time, so 1.hour.from_now doesn't works here.
You should use this:
class SinatraApp < Sinatra::Base
use Rack::Session::Cookie, :key => 'rack.session',
:domain => 'foo.com',
:path => '/',
:expire_after => 2592000, # In seconds
:secret => 'some_secret'
And set a time in seconds. Because the Sinatra session comes from Rack::Session.
HOW TO ENABLE SESSIONS WITH SINATRA

Sinatra/ActiveRecord can't handle simultaneous requests?

This is my first Sinatra project and I'm pretty late in and I'm realizing that when make multiple requests at once that use ActiveRecord that I run into problems. If I only make one request, each one works on its own. But when I call both at once, I get failure.
So far I've narrowed it down to the problem being two ActiveRecord requests simultaneously. Maybe I'm not setting up ActiveRecord correctly? I use PostgreSQL because Heroku uses it, and am no inclined to change. (The issue happens on Heroku, too.)
Here's the log:
192.168.1.113 - - [30/Sep/2012:10:33:00 MDT] "GET /version/current?platform=android HTTP/1.1" 200 33
- -> /version/current?platform=android ActiveRecord::StatementInvalid - NoMethodError: undefined method `fields' for nil:NilClass: SELECT "rankings".* FROM "rankings" WHERE "rankings"."user_id" = 1 LIMIT 1:
/Users/zablanc/.rvm/gems/ruby-1.9.3-head#emm/gems/activerecord-3.2.7/lib/active_record/connection_adapters/postgresql_adapter.rb:667:in `block in exec_query'
...
Warning! Rack::Session::Cookie data size exceeds 4K.
Warning! Rack::Session::Cookie failed to save session. Content dropped.
192.168.1.113 - - [30/Sep/2012:10:33:01 MDT] "GET /badges/all HTTP/1.1" 200 311
- -> /badges/all
192.168.1.113 - - [30/Sep/2012:10:33:01 MDT] "GET /moves/ranking/all HTTP/1.1" 500 166185
- -> /moves/ranking/all
I have no idea how to shut up those cookie warnings, tho they seem to have no effect on the app. Here's how I configure my app (in a config file I require from the main script):
enable :logging
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use Rack::Session::Cookie, :key => 'rack.session',
:path => '/',
:expire_after => 31_536_000, # In seconds
:secret => 'jeowkfj...secret...kjn5'
ActiveRecord::Base.include_root_in_json = false
def establish_connection(url)
db = URI.parse(url)
ActiveRecord::Base.establish_connection(
:adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
:host => db.host,
:port => db.port,
:username => db.user,
:password => db.password,
:database => db.path[1..-1],
:encoding => 'utf8'
)
end
configure :development do
establish_connection('postgres://postgres:postgres#localhost:5432/emm')
end
configure :test do
establish_connection('postgres://postgres:postgres#localhost:5432/emm-test')
end
configure :production do
establish_connection(ENV['DATABASE_URL'])
end
I'm guessing I'm not setting up ActiveRecord right, but I think it's just like the tutorials I've seen. What gives?
Sounds like you are using threads but have some non-thread-safe code in your application.
Which webserver are you using, which middleware are you using, which postgresql gem are you using, did you check to see that all your gems are thread-safe?

Storage of variables without initializing an object? Ruby Gem 'Mail'

Working with the Ruby Gem 'Mail', I am confused as to how variables are able to be stored without initializing an object? For example:
Mail.defaults do
retriever_method :pop3, :address => "pop.gmail.com",
:port => 995,
:user_name => '<username>',
:password => '<password>',
:enable_ssl => true
end
After which you are able to call methods such as Mail.first and have it return the first message in the mailbox with the configured defaults.
I realize everything in Ruby is an object, even a class, so when require 'mail' is called, does an object containing the the class Mail actually get created and mad available to the program? What exactly is happening here?
The contents of mail.rb are loaded into the file that has the require 'mail' statement.
After having a look in the gem, mail.rb contains the Mail module, which in turn contains many other require statements.
mail.rb
module Mail
## skipped for brevity
# Finally... require all the Mail.methods
require 'mail/mail'
end
mail/mail.rb
module Mail
## skipped for brevity
# Receive the first email(s) from the default retriever
# See Mail::Retriever for a complete documentation.
def self.first(*args, &block)
retriever_method.first(*args, &block)
end
end
So then the methods are made available to your program.

using redis and ruby to implement a tiny short url app

I'm making a short URL app, using Ruby, Sinatra, and Redis. Currently it's under 15 lines:
require 'rubygems'
require 'sinatra'
require 'redis'
require 'uri'
configure do
REDISTOGO_URL = "redis://localhost:6379/"
uri = URI.parse(REDISTOGO_URL)
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
end
get '/' do
haml :index
end
post '/shorten' do
a = rand(9999)
REDIS.set(a.to_s, params[:long])
"<pre>http://199.19.118.186/get/#{a}</pre>"
#haml :shorten
end
get '/get/:url' do
redirect REDIS.get(params[:url])
end
Where index.haml is a form that POSTs long to /shorten. I've no problem with that.
Right now, however, when I try to use Redis (with the server running, yes), I get this error:
What am I doing wrong?
EDIT: Copy/paste from Emacs... facepalm
EDIT: When trying to access redis alone from ruby (code below), I get this:
/var/lib/gems/1.8/gems/redis-2.2.2/lib/redis/client.rb:47:in `call': ERR unknown command (RuntimeError)
from /var/lib/gems/1.8/gems/redis-2.2.2/lib/redis.rb:841:in `set'
from /usr/lib/ruby/1.8/monitor.rb:242:in `synchronize'
from /var/lib/gems/1.8/gems/redis-2.2.2/lib/redis.rb:840:in `set'
from test_redis.rb:9
With this code:
require 'rubygems'
require 'redis'
require 'uri'
REDISTOGO_URL = "redis://localhost:6379/"
uri = URI.parse(REDISTOGO_URL)
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
REDIS.set("test", "blah")
puts REDIS.get("test")
Ruby being case sensitive, I would try to replace REDIS.SET by REDIS.set and REDIS.GET by REDIS.get. You can find the documentation of the Redis client here:
https://github.com/ezmobius/redis-rb
I have tested your example with ruby 1.8.7. (default on my Linux box).
After installing sinatra, haml, redis and hiredis gems, I have modified the code as follows:
require 'rubygems'
require 'sinatra'
require 'redis'
require 'uri'
configure do
REDISTOGO_URL = "redis://localhost:6379/"
uri = URI.parse(REDISTOGO_URL)
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
end
get '/' do
"Hello"
haml :index
end
post '/shorten' do
a = rand(9999)
REDIS.set(a.to_s, "http://"+params[:long])
"<pre>http://localhost:4567/get/#{a}</pre>"
end
get '/get/:url' do
redirect REDIS.get(params[:url])
end
I have added the following template in views/index.haml.
!!!
%html
%head
%title My Sinatra Website
%body
%h1 Welcome
%p
Welcome to my website made with Sinatra and HAML
%form{ :action => "/shorten", :method=>"POST" }
%fieldset
%input{ :type =>"text", :name=>"long" }
%input{ :type =>"submit" }
Once Redis is started on port 6379 and sinatra on port 4567, it works like a charm.
I suggest you check your ruby installation and try to access Redis from ruby with a simple non sinatra script.
UPDATE:
The error message is peculiar because normally, when an unknown command is sent to the server, the faulty command is provided:
ERR unknown command 'dummy'
while you just have:
ERR unknown command
Actually, this specific fix was introduced in Redis server more than 2 years ago (in December 2009) - an eternity for Redis.
https://github.com/antirez/redis/commit/2c14807b2dd5c15f1471bec32a7c6dbb077720ee
In other words, you are trying to use a very old (i.e. pre 1-3) version of Redis server with the last version of the Redis client ruby gem, which probably does not support anymore the initial protocol. You may want to compile and install a recent version of Redis server (it is easy), it should work better.

Resources