Is there a way in Sinatra to separate helpers used in views and helpers used in routes? - ruby

All helpers in Sinatra can be accessed from both my HAML code and my routes. But I'm finding myself writing two completely separate sets of code for these two.
Ideally I'd like to keep them apart. Currently I have them in two different directories, but that seems kind of pointless. Can anyone suggest a way I can limit the potential damage caused by namespace collision?
At first I thought modules. From the Sinatra readme:
module FooUtils
def foo(name) "#{name}foo" end
end
module BarUtils
def bar(name) "#{name}bar" end
end
helpers FooUtils, BarUtils
But is there any point in actually doing this? Aren't they going to have to share the same namespace inside my Sinatra app?

Some tentative and not-entirely-satisfactory answers:
1) Methods defined in the same way as helpers but without the call to Sinatra::helpers don't appear to be accessible from views, but are accessible from within the Sinatra application block. That is:
require 'sinatra'
module Sinatra
module MyThing
# Helper classes and methods go here
end
helpers MyThing # <- leave this out if you don't want access from views
end
2) You can of course also have MyThingHelpers and MyThingLib modules, instead of just MyThing, to prevent namespace collision.
3) And you can put them in separate subdirectories.
I've yet to be convinced that these represent a comprehensive solution to my concerns. Time and testing will tell, I suppose, unless someone can give me a better answer here.

Related

Loading attributes only once in Grape

I'm little new to Ruby, but I have the following coded using Grape API in Ruby. I have #data = YAML.load() called every time it hits GET /api/v1/foo, is there a way in Grape to only load it once and use it? This way is more optimized and not calling YAML.load() at every time. Should I override the initialize method and put a super() for this operation?
Thanks,
require 'grape'
require 'json'
require "yaml"
module MyProject
CONFIG_FILE = "./config.yml"
class Api < Grape::API
rescue_from :all
prefix 'api'
version 'v1'
format :json
resources :foo do
get do
#data = YAML.load(File.open(MyProject::CONFIG_FILE))
end
end
end
end
The short answer is that Grape doesn't work quite how you think, and attribute variables of the MyProject::Api are not the way forward for your new web service. However, it is an interesting question, and worth exploring why this is so.
If you add a puts self.inspect inside the resources :foo block, and run using rackup, when you call the route you should see that self is in fact a Grape::Endpoint object. Also, no matter what you try to do with instance variables, they will always start in the same state for each request. That is because Grape turns your route definitions into prepared Grape::Endpoint objects, with a lot of the definition data and setup put into a quickly-accessible form (so that it is not figured out on each request). Eventually, on each request, the matching Grape::Endpoint object including your block (and other details you defined for the route) is duplicated before being called, meaning that state is not maintained between requests.
This may seem complicated, but most frameworks covering web service requests will do something similar. Generally you don't want request-handling state to persist between requests. Frameworks with larger scope - e.g. Rails - have places to put more persistent data planned out for you. Grape does not have this defined, which has its pros and cons. One obvious plus point is that you are more free to use whatever other data persistence approach that you wish to.
23tux's answer will sort you out immediately for loading config. Although I'm not entirely sure how ##data becomes accessible to the endpoint block (it may even be creating a closure around the variable).
Longer term, you should look to moving config management out of your MyProject::Api class, and including it as a module via Grape's helpers method (I'm happy to provide an example if you are interested).
Edit: Example based on your current code, but moving config management to a separate module:
require 'grape'
require 'json'
require "yaml"
module MyProject
module Config
CONFIG_FILE = "./config.yml"
##data = nil
def config
##data ||= YAML.load( File.open( CONFIG_FILE ) )
end
end
class Api < Grape::API
rescue_from :all
prefix 'api'
version 'v1'
format :json
helpers MyProject::Config
resources :foo do
get do
config
end
end
end
end
This is one step further, structurally, than 23tux's answer, but is still not completely separating concerns of storage (and caching etc) versus api access. As you progress towards a more sophisticated web service, you will want to keep the Grape route definitions simple, with only a small amount of logic that manages or manipulates the data - well, at least as seen directly in the blocks.
One way to link between your Grape definitions, and other gems that might manage config, logging, authentication and other services, is via Grape's helpers method. Grape also has some built-in helper methods for common tasks.
The main exception to using helpers MyModule to add shared functions into Grape is when you want to manage displaying data objects (aka "models") from your core application. For that you have a few choices, but the grape-entity gem and the present method is not a bad place to start.
If the #data is the same for the whole api, and doesn't change at any time, just use a class variable
require 'grape'
require 'json'
require "yaml"
module MyProject
CONFIG_FILE = "./config.yml"
class Api < Grape::API
##data = YAML.load(File.open(MyProject::CONFIG_FILE))
rescue_from :all
prefix 'api'
version 'v1'
format :json
resources :foo do
get do
puts ##data
end
end
end
end
Not tested, but with this way, you ensure that the data is only loaded once, when your Api class is loaded

Detecting Ruby mixin being included

I have a question similar to this one. I'm writing an app that has an addon system. There's an Addon mixin module, which detects when it's included and registers the new addon automatically:
module Addon
def self.included(receiver)
addon = receiver.new # Create an instance of the addon
(snip) # Other stuff to register the addon
addon.on_register # Tell the instance it was registered
end
end
Here is an example of how the mixin would be used:
class MyAddon
def on_register
puts "My addon was registered"
end
include Addon # ** note that this is at the end of the class **
end
As noted above, this implementation requires that the include be at the bottom of the class. Otherwise on_register isn't defined at the time that self.included gets called.
My concern is that an addon developer might accidentally put the include at the top, causing the addon not to work. Or that there might be a derived class or something that would extend the MyAddon class after it was already included.
Is there a better way to go about this?
After distilling the other answers and some other info I found, I wanted to document the answer that ended up working for me.
As this question explains, you can't detect at include() time when a class is "done" being defined. So, relying on the 'included' callback to create the objects was not a very robust solution.
The solution instead was to discover all of the addons and instantiate them after everything had been loaded. The only constraint placed on addon developers was that their code had to share a common top-level module namespace.
I still don't know if this is the best way to do it, but it definitely works better than what I started with.
Here is the code that searches the module for addons. It starts at a passed-in namespace and searches recursively for classes that include the addon class:
def find_and_instantiate(mod, addons)
consts = mod.constants
consts.each do |c|
sym = mod.const_get(c)
if (sym.class == Module)
find_and_instantiate(sym, addons)
else
if (sym.class == Class && sym.include?(Addon))
addons << sym.new(#container)
end
end
end
end
The best I can come up with is to notify the user of your module that it needs to be included after the #on_register method has been declared:
module Addon
def self.included(receiver)
raise "include #{self.name} after the #on_register method is defined" unless receiver.method_defined? :on_register
receiver.new.send(:on_register)
end
end
This is less than ideal but it will prevent aggravating mistakes until you discover a better way of doing this.
Sorry, but I have to hand this to you. So you want to hear your code is clever, pal. Yes, it is, it is too clever. But if you want to be concerned about other developers, you will have to stop being clever and start being normal.
Ruby is an OO language. The basis of OOP is that I define my object structure and their methods first, and then, when everything is defined, I instantiate my world ideally with a single call MyApp.new. That way, it does not matter what I have defined first. 'include' calls serve to establish the module inheritance hierarchy, nothing else.
But no, you do not want to do OOP. You want to abuse the included hook and instantiate receiver (!) in it, and call its instance methods. That's what they call obfuscated code. In other words, you go from OOP back to the old good goto style directive programming. Ruby allows you to obfuscate, not to limit your abilities, but with great power great responsibility, you yourself must exercise moderation.
You will yoursef have to refactor your code to make it normal. We cannot do that for you, because we don't know what do you want to achieve. Who knows, maybe you idea is worthy of a genius. Too bad we don't know it from your question. Some addon system you have. I'm asking you: Do you need it? Isn't good old mixin system good enough for you? Are you sure you are not programming Java in Ruby? And, then, is your app going to be greater than Rails? If yes, go ahead with the addon system. If not – stop playing around and invest your time in writing the algos that actually do what your app is suppose to do rather than creating inextricable addon systems in advance. If you are working in a company - which I doubt - make sure you let your boss read this.

ruby module_function vs including module

In ruby, I understand that module functions can be made available without mixing in the module by using module_function as shown here. I can see how this is useful so you can use the function without mixing in the module.
module MyModule
def do_something
puts "hello world"
end
module_function :do_something
end
My question is though why you might want to have the function defined both of these ways.
Why not just have
def MyModule.do_something
OR
def do_something
In what kind of cases would it be useful to have the function available to be mixed in, or to be used as a static method?
Think of Enumerable.
This is the perfect example of when you need to include it in a module. If your class defines #each, you get a lot of goodness just by including a module (#map, #select, etc.). This is the only case when I use modules as mixins - when the module provides functionality in terms of a few methods, defined in the class you include the module it. I can argue that this should be the only case in general.
As for defining "static" methods, a better approach would be:
module MyModule
def self.do_something
end
end
You don't really need to call #module_function. I think it is just weird legacy stuff.
You can even do this:
module MyModule
extend self
def do_something
end
end
...but it won't work well if you also want to include the module somewhere. I suggest avoiding it until you learn the subtleties of the Ruby metaprogramming.
Finally, if you just do:
def do_something
end
...it will not end up as a global function, but as a private method on Object (there are no functions in Ruby, just methods). There are two downsides. First, you don't have namespacing - if you define another function with the same name, it's the one that gets evaluated later that you get. Second, if you have functionality implemented in terms of #method_missing, having a private method in Object will shadow it. And finally, monkey patching Object is just evil business :)
EDIT:
module_function can be used in a way similar to private:
module Something
def foo
puts 'foo'
end
module_function
def bar
puts 'bar'
end
end
That way, you can call Something.bar, but not not Something.foo. If you define any other methods after this call to module_function, they would also be available without mixing in.
I don't like it for two reasons, though. First, modules that are both mixed in and have "static" methods sound a bit dodgy. There might be valid cases, but it won't be that often. As I said, I prefer either to use a module as a namespace or mix it in, but not both.
Second, in this example, bar would also be available to classes/modules that mix in Something. I'm not sure when this is desirable, since either the method uses self and it has to be mixed in, or doesn't and then it does not need to be mixed in.
I think using module_function without passing the name of the method is used quite more often than with. Same goes for private and protected.
It's a good way for a Ruby library to offer functionality that does not use (much) internal state. So if you (e.g.) want to offer a sin function and don't want to pollute the "global" (Object) namespace, you can define it as class method under a constant (Math).
However, an app developer, who wants to write a mathematical application, might need sin every two lines. If the method is also an instance method, she can just include the Math (or My::Awesome::Nested::Library) module and can now directly call sin (stdlib example).
It's really about making a library more comfortable for its users. They can choose themself, if they want the functionality of your library on the top level.
By the way, you can achieve a similar functionality like module_function by using: extend self (in the first line of the module). To my mind, it looks better and makes things a bit clearer to understand.
Update: More background info in this blog article.
If you want to look at a working example, check out the chronic gem:
https://github.com/mojombo/chronic/blob/master/lib/chronic/handlers.rb
and Handlers is being included in the Parser class here:
https://github.com/mojombo/chronic/blob/master/lib/chronic/parser.rb
He's using module_function to send the methods from Handlers to specific instances of Handler using that instance's invoke method.

How to mount a Sinatra application inside another Sinatra app?

I am trying to write a Sinatra application that groups components together (sort of like controllers). So for the "blog" related things, I want an app called Blog mounted at /blog. All of the routes contained in the Blog app would be relative to its mounted path, so I could simply define an index route without having to specify the mount path in the route.
I originally handled this by using a config.ru file and maping the routes to the different apps. The problem with this that I ran into, was that I was using various sinatra gems/extensions/helpers that needed to be included in all of the apps, so there was a lot of duplicate code.
How can I mount one sinatra app inside of another so that the routes defined in the app are relative to where the app is mounted? If this is not possible out-of-the-box, can you show a code sample of how this could be done?
Here's a simplified example of what it might look like:
class App
mount Blog, at: '/blog'
mount Foo, at: '/bar'
end
class Blog
get '/' do
# index action
end
end
class Foo
get '/' do
# index action
end
end
Take a look at https://stackoverflow.com/a/15699791/335847 which has some ideas about namespacing.
Personally, I would use the config.ru with mapped routes. If you're really in that space between "should this be a separate app or is it just helpful to organize it like this" it allows that, and then later you can still farm off one of the apps on its own without changing the code (or only a little). If you're finding that there's a lot of duplicated set up code, I'd do something like this:
# base_controller.rb
require 'sinatra/base'
require "haml"
# now come some shameless plugs for extensions I maintain :)
require "sinatra/partial"
require "sinatra/exstatic_assets"
module MyAmazingApp
class BaseController < Sinatra::Base
register Sinatra::Partial
register Sinatra::Exstatic
end
class Blog < BaseController
# this gets all the stuff already registered.
end
class Foo < BaseController
# this does too!
end
end
# config.ru
# this is just me being lazy
# it'd add in the /base_controller route too, so you
# may want to change it slightly :)
MyAmazingApp.constants.each do |const|
map "/#{const.name.downcase}" do
run const
end
end
Here's a quote from Sinatra Up and Running:
Not only settings, but every aspect of a Sinatra class will be inherited by its subclasses. This includes defined routes, all the error handlers, extensions, middleware, and so on.
It has some good examples of using this technique (and others). Since I'm in shameless plug mode I recommend it, even though I've nothing to do with it! :)
I just meet the same problems.
I found that whatever inclued extend register or rack middleware style use had problems.
You can use Ruby to solve this problems like that:
require "sinatra"
class App < Sinatra::Base
class << self
def define_routes(&block)
class_eval(&block)
end
end
end
App.define_routes do
get "/hello"
"hello world"
end
end

Best Practice for sharing global data over several Thor tasks

I am currently building a Thor executable that supports several different tasks. Some tasks inoke other tasks. For example
Auth
authenticates the local user
Create
Invoke Auth
Does something
Invoke Configure
Configure:
Invoke Auth
Does something
The nice thing about thor is that I can now call all of the three tasks separately, but be sure that authenticate for example is only called once through invoke.
But what is now the best way to share Data between those tasks. For example when Authenticating I want to set the User-ID of the current user. Thus when I want to request Data from our webservice I can take the user id from anywhere in my code the same way.
Right now I am implementing this through Modules, but I am not really sure if this is the best way to do it.
Using Singleton would be another way, but somehow this seems like a little bit too much for this purpose.
Maybe you guys have experience with a better way to do this, or maybe using modules is the best way to store the information anyway.
I would have done something like this:
module PRJ
class << self
attr_accessor :api_key, :account_name, :api_version, :api_url, ......
def configure
yield self
end
end
end
require "#{directory_of_all_other_classes}"
require 'thor'
class CLI < Thor
include Thor::Actions
def login
...
PRJ.api_key = response[:api_key]
end
As you want to invoke Auth in every cases, so I think it should be in main CLI file.
Regarding storing and using data it would be better to use attributes instead of constant. I may not be right about this but I prefer using class attributes.
Now you can access and change PRJ.api_key from anywhere (require PRJ module in every file)
P.S. The structure of code snippet might not be accurate, I just wanted to share some basic skeleton. Do something like above for remaining classes.
If you just need to store simple data structures I would go for common class variables
class Test < Thor
##my_shared_var = nil
desc 'my_first_task','sdfasdf'
def my_first_task
##my_shared_var = 'foo'
end
desc 'my_second_task','sdfasdf'
def my_second_task
invoke :my_first_task
puts ##my_shared_var
end
end

Resources