Sinatra settings returning strange result - ruby

I have a very simple Sinatra application:
require 'sinatra'
get '/' do
settings.inspect
end
And when I go to the root path I get: Sinatra::Application which is not at all what I expected. The application also doesn't respond well when I call the development? method (NoMethodError). I get the feeling this is because of my environment. I'm running Sinatra 1.4.4 with Ruby 1.9.3 on Windows 8. Any ideas on how to figure this out?

This is right, it’s just the way Sinatra works.
The settings instance method calls the class method (with self.class.settings) and the class method simply returns self, which is Sinatra::Application in the case of classic apps, and whatever your app class is in the case of modular apps.
When you add a setting in Sinatra with set, a new method is created on the app class for it, rather than there being a separate settings object. There is no way, as far as I know, to iterate over just the settings of your app.

Related

Making a Rack CLI

I'm trying to make a framework similar to Rails, but purely focused on GraphQL. Once nice feature of Rails is that it provides a CLI interface and a config.ru for Rack. Therefore, you can call rackup or you can call bin/rails server and the Rails app will run. I managed to mimic this functionality by putting the Rack app into a separate file (config/application.rb), which I import in config.ru and in the CLI, then instantiate and run.
However, I have an issue with Rack middleware. Since Rack middleware appears to just magically work when you run use MyMiddleware with an instantiated Rack app, I'm not really sure how I can do this in both config.ru and in my CLI. Right now it looks like I need to instantiate the app in a separate location, add the middleware, then hand it over to config.ru or the CLI. Which, I could do, but it feels like there has to be a way to attach middleware in a cleaner way. For instance, can I require config.ru in some way and then run it? Or can I attach middleware before I instantiate the app?
config.ru is just a ruby file, it's loaded by Rails as part of running each command. You can require it yourself as normal if that's what you'd like to do.
If you want to really figure out how Rails does it, the config loading is buried in this part of the Rails CLI:
https://github.com/rails/rails/blob/3cac5fe94f0f81b4263cfa03d4822c05a55eb49c/railties/lib/rails/application.rb

Espresso Enginery

i use framwork Espresso with Enginery generator (Ruby gems). I create new project, and not understand how work this application. I will work with Espresso. Explain me struct Expresso Application, please.
I can run this apllication: rackup config.ru
I can edit controllers, but i not understand depending between ruby scripts in this project.
i run projects, but why this work it?
config.ru
require File.expand_path('../base/boot', __FILE__)
puts App.urlmap
run App
in project not /base/boot directory.
requiring '../base/boot' will actually load dependencies, controllers, models etc. and build the application.
The application are stored under App constant, so you can access it from different files:
https://github.com/espresso/enginery/blob/master/app/base/base/boot.rb#L9
puts App.urlmap will display all the routes to be served by app.
And run App will start your app.
You can also start app by ruby app.rb, then you do not need to pass server/port at startup.
Instead you'll set them in config/config.yml, like this:
development:
server: Thin
port: 5252
The config.ru file looks quite normal for a rack start-up file. You would start the application from the project folder, with a command like:
rackup -p 8080
The following line:
require File.expand_path('../base/boot', __FILE__)
will load in the ../base/boot file (similar to require_relative, but also works with older Ruby e.g. 1.8.7), which I would guess requires the dependencies where App is defined. The class or module App will implement a call method. To start the server, the rack host calls App.new (which is called due to run App) and then on each request it will call .call( env ) on the resulting object (the object doesn't have to be an App object, but in simpler frameworks it will be).
The variable env contains all the details of the request and the rack environment that can be inspected to fetch details of the current path, cookies, query params etc. Typically access to this data is abstracted through Sinatra and Espresso helper methods that you will use.
The Sinatra and Espresso helper methods look like they are doing magic declarations, but they are just normal methods. Usually they do some calculation and then stash a code block/lambda for rack to call later. Sinatra's get is like this . . . it isn't true declarative code. Instead, when the controller is parsed, it just takes the code block and tells the application object to call it (later) when the path matches.

Debugging controller methods by running functional tests

I am in a situation where I need to step through the controller method when I run a functional test. I use ruby-debug to debug through my application. My app is a rails 3.1 app which uses ruby-1.8.7 . I can debug my code by using
rails server --debugger OR
rails console --debugger
I can also stop the code by inserting "debugger" in a model and run it's respective unit test.
But I am not able to do the same thing with the controllers. That is I am not able to stop the code by inserting "debugger" in the methods of the controller and run it's respective functional test.
Has anyone faced this issue before?
Also I use devise for authentication so I need to add the following lines to my test_helper
class ActionController::TestCase
include Devise::TestHelpers
def login_user
#request.env["devise.mapping"] = Devise.mappings[:user]
#user.confirm!
sign_in #user
end
end
Not sure I that is going to effect the debugger in anyway.
I was unable to stop at a debugger inserted in my controller method when I ran the functional tests because I was hitting a before_filter

Problems with mountable engine's application controller

I have a rails app called X and a rails mountable engine called Y.
App X has Devise and engine Y has CanCan which works with the hosts apps devise installation. In order to seperate the concerns of host app and mountable engine, the engine has a CanCan ability model as well as the host app.
My problem is the following, as per CanCan documentation you can change the default ability model like so https://github.com/ryanb/cancan/wiki/Changing-Defaults.
My problem is that if I setup the of default ability class in the mountable engines application controller like so:
module Y
class ApplicationController < ActionController::Base
def current_ability
#current_ability = Ability.new(current_user)
end
end
end
I get the following error:
uninitialized constant Ability
(On a side note, when I edit the file and reload the page without restarting the server it works fine)
If however I put the same method into the host app's application controller:
class ApplicationController < ActionController::Base
def current_ability
#current_ability = Y::Ability.new(current_user)
end
end
Everything works as expected (which also means that Devise and CanCan are setup correctly).
Anyone got any ideas of why this is happening? I might not understand mountable engines correctly however I always thought that they are isolated from the host app, thus when accessing a page defined by the mountable engine the host app's application controller shouldn't even be executed.
it is most likely that your engines application controller is not loaded at all. Rails engines behave bad if you have same class name in the main app. here is the issue if you want to look at. I would recommend using the explicit declaration in your engine. Use Y::Ability instead of Ability.

How do I test Sinatra helpers from irb?

I am trying to call a helper method in my Sinatra application from irb in order to test its output. I know I can get a console using this tip, and I've tried racksh as well. But if I do a "defined? my_helper" I always get nil. There must be some simple way of getting at those helpers. I have a feeling that this means digging through the architecture of Rack a little bit. Any hints?
You can of course test your Sinatra helpers via IRB.
Suppose you had a modular Sinatra app with a helper method foo that printed "baz":
require "my-app.rb"
MyApp.new.helpers.foo # => "baz"
I am trying to call a helper method in my Sinatra application from irb in order to test its output
Instead of testing it over the command line, use RSpec. See How can I test helpers blocks in Sinatra, using Rspec?

Resources