Rack::Session::Pool Sessions in Sinatra - ruby

I can't seem to get these sessions to continue into other pages.
app.rb:
class MyApp < Sinatra::Base
use Rack::Session::Pool, :expire_after => 60 * 1
get "/" do
#foo = "one two three"
erb :index
end
get "/first" do
session[:foo] = Time.now
session[:message] = "ALPHA"
session[:message1] = "CHARLIE"
erb :first
end
get "/second" do
session[:message2] = "BRAVO2"
erb :second
end
end
Inside /first and /second:
Sess: <%= session.inspect %><br>
The session doesn't want to carry across pages. On /first I'm displaying this:
Sess: {"message"=>"ALPHA", "message1"=>"CHARLIE", "foo"=>2015-12-01 17:05:31 -0500}
On /second I'm displaying this:
Sess: {"message2"=>"BRAVO2"}

Just needed a restart. Figure that.

Related

Sinatra Session data shared between browsers

I have a basic banking application running on Heroku using Sinatra.
I have tried implementing sessions to ensure each user that visits has a different version of the app. However, at the moment, if I visit it with two separate browsers, I have the same data.
There is no backend database implemented but data I add via the interface persists in every browser I visit in.
Here is my app.rb:
require 'sinatra/base'
require 'tilt/erb'
require 'require_all'
require_all 'lib'
require 'rufus-scheduler'
class BankingApp < Sinatra::Base
enable :sessions
set :session_secret, 'super secret'
get '/' do
session[:accounts] = AccountsController.instance
session[:holders] = HoldersController.instance
session[:loans] = LoansController.instance
erb :index
end
get '/holders' do
#holders = session[:holders].store
erb :holders
end
get '/holders_accounts' do
#holder = session[:holders].find(params[:id].to_i)
message = session[:accounts].get_accounts_of(params[:id].to_i)
#accounts = message.accounts
erb :holders_accounts
end
get '/new_holder' do
erb :new_holder
end
post '/new_holder' do
#message = session[:holders].create(params[:name])
#holders = session[:holders].store
erb :holders
end
get '/create_account' do
erb :create_account
end
post '/create_account' do
type = :Current
id = params[:id].to_i
#message = session[:accounts].open(type, with: id)
erb :index
end
get '/accounts' do
#accounts = session[:accounts].store
erb :accounts
end
get '/transactions' do
message = session[:accounts].get_transactions_of(params[:id].to_i)
#transactions = message.transactions
erb :transactions
end
get '/deposit' do
erb :deposit
end
post '/deposit' do
#accounts = session[:accounts].store
#message = session[:accounts].deposit(params[:amount].to_i, into: params[:id].to_i)
erb :accounts
end
get '/withdraw' do
erb :withdraw
end
post '/withdraw' do
#accounts = session[:accounts].store
#message = session[:accounts].withdraw(params[:amount].to_i, from: params[:id].to_i)
erb :accounts
end
get '/transfer' do
erb :transfer
end
post '/transfer' do
#accounts = session[:accounts].store
#message = session[:accounts].transfer(params[:amount].to_i, from: params[:donar].to_i, to: params[:recipitent].to_i)
erb :accounts
end
get '/add_holder' do
erb :add_holder
end
post '/add_holder' do
#accounts = session[:accounts].store
#message = session[:accounts].add_holder(params[:holder_id].to_i, to: params[:account_id].to_i)
erb :accounts
end
get '/enable_overdraft' do
erb :enable_overdraft
end
post '/enable_overdraft' do
#accounts = session[:accounts].store
#message = session[:accounts].activate_overdraft(params[:id].to_i, params[:amount].to_i)
erb :accounts
end
get '/disable_overdraft' do
erb :disable_overdraft
end
post '/disable_overdraft' do
#accounts = session[:accounts].store
#message = session[:accounts].deactivate_overdraft(params[:id].to_i)
erb :accounts
end
get '/loans' do
#loans = session[:loans].store
erb :loans
end
get '/loan_view' do
message = session[:loans].show(params[:id].to_i)
#transactions = message.transactions
erb :loan_view
end
get '/new_loan' do
erb :new_loan
end
post '/new_loan' do
#loans = session[:loans].store
id = params[:id].to_i
options = { borrowed: params[:amount].to_i, term: params[:term].to_i, rate: params[:rate].to_f }
#message = session[:loans].create_loan(id, options)
erb :loans
end
get '/pay_loan' do
erb :pay_loan
end
post '/pay_loan' do
#message = session[:loans].pay(params[:amount].to_i, off: params[:id].to_i)
#loans = session[:loans].store
erb :loans
end
# start the server if ruby file executed directly
run! if app_file == $0
end
I do not have a great deal of experience with Sinatra so apologies if this is an oversight on my part.
Any help greatly appreciated.
So I'm pretty sure the core of your problem is this line which you have in multiple places throughout your code. As per the ruby docs
This ensures that only one instance of Klass can be created.
You've explicitly told ruby to only ever let one copy of each class/module ever exist. I don't think that's what you want.
It's a bit hard to infer what it is you're trying to achieve exactly but I don't think using Singleton in a web app is going to be the right solution. The assumptions it imposes break down as soon as you run a 2nd instance (or dyno in Heroku parlance) of your app.
I would recommend using this
get '/logout' do
session.clear
end

Sinatra app doesnt redirect to haml files

This is the Sinatra code that I wrote. All gems exist, the ruby files compiles perfectly but when i go to localhost:4567/ the sinatra app doesnt run. It takes me to the 'Sinatra doesnt know this ditty' page. What mistake am i making here? Is it a syntax issue? I've posted the main ruby file's code here others are just haml files thats all.
require 'bundler'
Bundler.setup(:default)
require 'sinatra'
require 'haml'
require 'twitter'
require 'oauth'
class MyTweetWeek < Sinatra::Base
set :haml, :format => :html5, :attr_wrapper => '"'
enable :sessions, :static, :raise_errors
set :public_dir, File.join(File.dirname(__FILE__), 'public')
get '/' do
haml :index
end
get '/login' do
request_token = consumer.get_request_token(:oauth_callback => ENV['OAUTH_CALLBACK'])
session[:request_token] = request_token.token
session[:request_token_secret] = request_token.secret
redirect request_token.authorize_url
end
get '/oauth_callback' do
request_token = OAuth::RequestToken.new(
consumer,
session[:request_token],
session[:request_token_secret]
)
session[:request_token] = session[:request_token_secret] = nil
access_token = request_token.get_access_token(:oauth_verifier => params[:oauth_verifier])
session[:access_token] = access_token.token
session[:access_secret] = access_token.secret
redirect '/resume'
end
get '/resume' do
redirect '/' unless authenticated?
today = Date.today #get today's date
monday = today - today.cwday + 1 #calculate Monday
search = Twitter::Search.new
#screen_name = client.verify_credentials.screen_name
#number_of_tweets = 0
#number_of_mentions = 0
results = search.from(#screen_name)
.since_date(monday)
.no_retweets
.per_page(100)
.fetch
#number_of_tweets += results.size
while search.next_page?
results = search.fetch_next_page
#number_of_tweets += results.size
end
search.clear
results = search.q("##{#screen_name.gsub('#', '')}")
.since_date(monday)
.no_retweets
.per_page(100)
.fetch
#number_of_mentions += results.size
while search.next_page?
results = search.fetch_next_page
#number_of_mentions += results.size
end
haml :resume
end
error Twitter::Error::Unauthorized do
redirect '/'
end
not_found do
haml :not_found
end
private
def consumer
#consumer ||= OAuth::Consumer.new(
ENV['CONSUMER_KEY'],
ENV['CONSUMER_SECRET'],
:site => "https://api.twitter.com"
)
end
def client
Twitter.configure do |config|
config.consumer_key = ENV['CONSUMER_KEY']
config.consumer_secret = ENV['CONSUMER_SECRET']
config.oauth_token = session[:access_token]
config.oauth_token_secret = session[:access_secret]
end
#client ||= Twitter::Client.new
end
def authenticated?
!session[:access_token].nil? && !session[:access_secret].nil?
end
end
As you have a modular app do you need to require "sinatra/base" rather than "sinatra"? See here
See Serving a Modular App and add the line run! if app_file == $0 at the end of the class. Also see DavB's answer.

Blocks in pure ERB / Erubis

I have the following Ruby script:
require 'erubis'
def listing(title, attributes={})
"output" + yield + "more output"
end
example = %Q{<% listing "db/migrate/[date]_create_purchases.rb", :id => "ch01_292" do %>
<![CDATA[class CreatePurchases < ActiveRecord::Migration
def change
create_table :purchases do |t|
t.string :name
t.float :cost
t.timestamps
end
end
end]]>
<% end %>}
chapter = Erubis::Eruby.new(example)
p chapter.result(binding)
I am attempting to use a block here and get it to output "output", then the content in the block and then "more output", but I can't seem to get it to work.
I know that ERB used to work this way in Rails 2.3 and now works with <%= in Rails 3... but I'm not using Rails at all. This is just pure ERB.
How can I get it to output all the content?
Jeremy McAnally linked me to this perfect description of how to do it.
Basically, you need to tell ERB to store the output buffer in a variable.
The script ends up looking like this:
require 'erb'
def listing(title, attributes={})
concat %Q{
<example id='#{attributes[:id]}'>
<programlisting>
<title>#{title}</title>}
yield
concat %Q{
</programlisting>
</example>
}
end
def concat(string)
#output.concat(string)
end
example = %Q{<% listing "db/migrate/[date]_create_purchases.rb", :id => "ch01_292" do %>
<![CDATA[class CreatePurchases < ActiveRecord::Migration
def change
create_table :purchases do |t|
t.string :name
t.float :cost
t.timestamps
end
end
end]]>
<% end %>}
chapter = ERB.new(example, nil, nil, "#output")
p chapter.result(binding)
Great. I remember seeing that a while ago. Playing a bit I was getting this:
require 'erubis'
def listing(title, attributes={})
%Q{<%= "output #{yield} more output" %>}
end
example = listing "some title", :id => 50 do
def say_something
"success?"
end
say_something
end
c = Erubis::Eruby.new(example)
p c.evaluate
# => "output success? more output"

Passing parameters to erb view

I'm trying to pass parameters to an erb view using Ruby and Sinatra.
For example, I can do:
get '/hello/:name' do
"Hello #{params[:name]}!"
end
How do I pass :name to the view?
get '/hello/:name' do
erb :hello
end
And how do I read the parameters inside view/hello.erb?
Thanks!
just pass the :locals to the erb() in your routes:
get '/hello/:name' do
erb :hello, :locals => {:name => params[:name]}
end
and then just use it in the views/hello.erb:
Hello <%= name %>
(tested on sinatra 1.2.6)
Not sure if this is the best way, but it worked:
get '/hello/:name' do
#name = params[:name]
erb :hello
end
Then, I can access :name in hello.erb using the variable #name
get '/hello/:name' do
"Hello #{params[:name]}!"
end
You cannot do this in routes.
You want to set the params in the controller.
app/controllers/some_controller.rb
def index
params[:name] = "Codeglot"
params[:name] = "iPhone"
params[:name] = "Mac Book"
end
app/views/index.html.erb
<%= params[:name] %>
<%= params[:phone] %>
<%= params[:computer] %>

Error generating test routes for Rails 3 plugin?

I'm trying to develop tests for plugin "foobar" that modifies some of the standard Rails helpers. In vendor/plugins/foobar/test/foobar_test.rb, I have the following:
# create the test model
class Thing < ActiveRecord::Base
end
# create the test controller, which renders the included index template
class ThingsController < ActionController::Base
def index
#things = Thing.all
format.html { render(:file => 'index') }
end
def destroy
#thing = Thing.find(params[:id])
#thing.destroy
format.html { render(:file => 'index') }
end
end
# confirm that the test environment is working correctly
class ThingsTest < ActiveSupport::TestCase
test "model is loaded correctly" do
assert_kind_of Thing, Thing.new
end
end
# confirm that the controller and routes are working correctly
class ThingsControllerTest < ActionController::TestCase
test "should load index" do
with_routing do |set|
set.draw do
resources :things, :only => [:index, :destroy]
end
get :index
assert_response :success
end
end
end
When I run rake, I get the following output:
test_should_load_index(ThingsControllerTest):
NameError: undefined local variable or method `_routes' for ThingsController:Class
Any idea what I'm doing wrong that is preventing me from accessing the routes? I've been at this for days and scoured much documentation, to no avail. Thanks for the help!
I got things to work on Rails 3.1.0.rc1 with Ruby 1.9.2, by following "The Basics of Creating Rails Plugins" Rails Guide and correcting the code whenever it exploded due to an incompatibility.
I started by running:
Code$ rails new tester
Code$ cd tester
tester$ rails generate plugin foobar --with-generator
Then modifying the generated code to obtain these files in addition to the default ones:
# vendor/plugins/foobar/init.rb
require 'foobar'
# vendor/plugins/foobar/lib/foobar.rb
%w{ models controllers helpers }.each do |dir|
path = File.join(File.dirname(__FILE__), 'app', dir)
$LOAD_PATH << path
ActiveSupport::Dependencies.autoload_paths << path
ActiveSupport::Dependencies.autoload_once_paths.delete(path)
end
# I'm not entirely sure this is the best way to add our plugin's views
# to the view search path, but it works
ActionController::Base.view_paths =
ActionController::Base.view_paths +
[ File.join(File.dirname(__FILE__), 'app', 'views') ]
<!-- vendor/plugins/foobar/lib/app/views/things/index.html.erb -->
<h1>Listing things</h1>
<table>
<tr>
<th>Name</th>
<th></th>
</tr>
<% #things.each do |thing| %>
<tr>
<td><%= thing.name %></td>
<td><%= link_to 'Destroy', thing, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
# vendor/plugins/foobar/test/database.yml
sqlite:
:adapter: sqlite
:dbfile: vendor/plugins/foobar/test/foobar_plugin.sqlite.db
sqlite3:
:adapter: sqlite3
:database: vendor/plugins/foobar/test/foobar_plugin.sqlite3.db
postgresql:
:adapter: postgresql
:username: postgres
:password: postgres
:database: foobar_plugin_test
:min_messages: ERROR
mysql:
:adapter: mysql
:host: localhost
:username: root
:password: password
:database: foobar_plugin_test
# vendor/plugins/foobar/test/schema.rb
ActiveRecord::Schema.define(:version => 0) do
create_table :things, :force => true do |t|
t.string :name
t.datetime :created_at
t.datetime :updated_at
end
end
# vendor/plugins/foobar/test/test_helper.rb
ENV['RAILS_ENV'] = 'test'
ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/../../../..'
require 'test/unit'
require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb'))
def load_schema
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
db_adapter = ENV['DB']
# no db passed, try one of these fine config-free DBs before bombing.
db_adapter ||=
begin
require 'rubygems'
require 'sqlite'
'sqlite'
rescue MissingSourceFile
begin
require 'sqlite3'
'sqlite3'
rescue MissingSourceFile
end
end
if db_adapter.nil?
raise "No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3."
end
ActiveRecord::Base.establish_connection(config[db_adapter])
load(File.dirname(__FILE__) + "/schema.rb")
require File.dirname(__FILE__) + '/../init'
end
load_schema
# vendor/plugins/foobar/test/foobar_test.rb
require File.dirname(__FILE__) + '/test_helper'
# create the test model
class Thing < ActiveRecord::Base
end
# create the test controller, which renders the included index template
class ThingsController < ActionController::Base
def index
#things = Thing.all
respond_to do |format|
format.html # index.html.erb
end
end
def destroy
#thing = Thing.find(params[:id])
#thing.destroy
respond_to do |format|
format.html { redirect_to things_url }
end
end
end
# confirm that the test environment is working correctly
class ThingsTest < ActiveSupport::TestCase
test "schema has loaded correctly" do
assert_equal [], Thing.all
end
test "model is loaded correctly" do
assert_kind_of Thing, Thing.new
end
end
# confirm that the controller and routes are working correctly
class ThingsControllerTest < ActionController::TestCase
test "should load index" do
with_routing do |set|
set.draw do
resources :things, :only => [:index, :destroy]
end
get :index
assert_response :success
end
end
end
And finally, our test passes:
tester$ cd vendor/plugins/foobar/
foobar$ rake
-- create_table(:things, {:force=>true})
-> 0.0059s
-- initialize_schema_migrations_table()
-> 0.0002s
-- assume_migrated_upto_version(0, ["db/migrate"])
-> 0.0003s
Loaded suite /Users/nick/.rvm/gems/ruby-1.9.2-p0/gems/rake-0.9.2/lib/rake/rake_test_loader
Started
...
Finished in 0.091642 seconds.
3 tests, 3 assertions, 0 failures, 0 errors, 0 skips
Your best bet for debugging this is to do
rake <task> --trace
This will give you a much better idea (i.e. a line number) on what is causing the _routes error.

Resources