Rails Server restart every time I make a change - ruby

I have a module file that I need to use for my rails project. When I make a change to any Rails models, views, controller etc the server doesn't need to restart. but when I make a change in that module I need to restart the server.
The module.rb does not inherit anything from Rails classes.
The structure is this:
class_1.rb < class_2.rb includes module.rb
class_1.rb, class_2.rb are also not ActiveRecord classes.
They are all located in my models' directory.
My config/enviroments/development.rb file is correct, as it has this:
config.cache_classes = false

Update: For rails 3.2.9 this should work right out of the box !
Here is what i tried and it works without restarting the server:
# ../models/a.rb
class A
include SomeModule
def test
" test:a"
end
end
# ../models/b.rb
class B < A
def test
super + " test:b"
end
end
# ../models/some_module.rb
module SomeModule
def call_test
test + " test:module"
end
end
# ../controllers/home_controller.rb
class HomeController < ApplicationController
def index
#i = B.new.call_test
end
end
You can place this inside your application.rb when your module doesnt live within the autoload paths:
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/your_module_folder/**/"]

Related

Ruby Module Constant Set and Read

I'm developing a module that contains standard methods as well as CLI (Thor) and API (Sinatra). I've created a Submodule that includes a class that inherits Sinatra::Base:
module Monteverde
module Activity
def self.version
"1.0.1"
end
class API < Sinatra::Base
set :port, 22340
get "/version" do
Monteverde::Activity.version
end
run! if defined? Monteverde::OPERATION
end
end
end
This "Activity" is invokes from the CLI (Thor):
module Monteverde
class CLI < Thor
desc "api", "Start Activity API"
def api
Monteverde.const_set("OPERATION", "started")
Monteverde::Activity::API
end
desc "aversion", "Get Activity Version"
def aversion
puts Monteverde::Activity.version
end
end
end
If I don't add an "if" to Sinatra's run! it will run automatically and take over the rest of the methods in the module:
...
class API < Sinatra::Base
register Sinatra::DefaultRoutes
set :port, 22340
get "/version" do
Monteverde::Activity.version
end
run!
end
$ ruby monteverde.rb aversion
$ == Sinatra (v2.0.0) has taken the stage on 22340 for development with backup from Puma
$ ...
My issue is that the OPERATION constant is not recognized even though it's set right before the module is called.
Why isn't OPERATION being recognized and how can I get it to be?
Is there another more intuitive/useful way to get Sinatra not to fire when I call the module?
In your API class definition, the run! line happens as soon as you require that file. It doesn't run again if you reference the class, as you're trying to do with the last line of your def api method.
To get around this, you can move the run! command into a method, and call that from Thor:
class API < Sinatra::Base
# ... other stuff
def self.start
run! if defined? Monteverde::OPERATION
end
end
Then in the Thor file:
def api
Monteverde.const_set("OPERATION", "started")
Monteverde::Activity::API.start
end
You can deduce that run! is a class method since it's callable in the scope of the class definition (not in an instance method), and so I define a class method to call it.
It would be simpler, though, to not define def self.start, and instead just call the run! method from the Thor file directly:
def api
Monteverde::Activity::API.run!
end

Including Service class in Controller

I want to include the following class from my services folder into my Controller..
Here is the Class in ..services/product_service.rb
class MyServices
class << self
def screen_print
"These are the words in screen print"
end
end
end
And all I want to do is this in my controller:
class AmazonsController < ApplicationController
def index
#joe = MyServices.screen_print
end
end
I thought I could just include it in the controller. And its not a module so include isn't working, and I tried updating my config/appliaction.rb file and that didn't work either..
Your class name needs to be the same as the name of your file, I believe. So since your file is named product_service.rb, your class should be:
class ProductService
class << self
def screen_print
"These are the words in screen print"
end
end
end
and in your controller:
class AmazonsController < ApplicationController
def index
#joe = ProductService.screen_print
end
end
In addition to the naming problems already pointed out, Rails won't automatically require arbitrary files from folders it doesn't know about.
If you want files in a new folder to be automatically required, you need to add it to Rails' autoload paths:
# config/application.rb
config.autoload_paths << Rails.root.join('services')
See Auto-loading lib files in Rails 4 for more details.
Rails does not load files from uncommon locations. You will need to tells Rails that the services folder exists and to load file from it.
Add the following to your config/application.rb:
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += [Rails.root.join('app', 'services')]

Access Sinatra settings from a model

I have a modular Sinatra app. I'm setting some custom variables in my configure block and want to access these settings in my model.
The problem is, I get a NoMethodError when I try and access my custom settings from MyModel. Standard settings still seem to work fine though. How can I make this work?
# app.rb
require_relative 'models/document'
class App < Sinatra::Base
configure do
set :resource_path, '/xfiles/i_want_to_believe'
end
get '/' do
#model = MyModel.new
haml :index
end
end
# models/my_model.rb
class MyModel
def initialize
do_it
end
def do_it
...
settings.resource_path # no method error
...
settings.root # works fine
end
end
i think that you should be able to access it via
Sinatra::Application.settings.documents_path
I ended up doing:
#document.rb
class Document
def self.documents_path=(path)
#documents_path = path
end
def self.documents_path
#documents_path
end
...
end
#app.rb
configure do
set :documents_path, settings.root + "/../documents/"
Document.documents_path = settings.documents_path
end
then just using Document.documents_path inside my find method.

Pass arguments to new sinatra app

Simple question: I want to be able to pass options into my sinatra app in config.ru. How is that possible? My config.ru looks like this:
run MyApp
But I want to have this in my MyApp class to take arguments:
class MyApp < Sinatra::Base
def initialize(config)
#config = config
end
end
But I can't figure out a way to do this. Ideas?
Use set/settings
require 'sinatra/base'
class MyApp < Sinatra::Base
get '/' do
settings.time_at_startup.to_s
end
end
# Just arbitrarily picking time as it'll be static but, diff for each run.
MyApp.set :time_at_startup, Time.now
run MyApp
Use a config file. See Sinatra::ConfigFile in contrib (which also uses set and settings, but loads params from a YAML file)
If you want to configure with params, I figured out that you could do this:
require 'sinatra/base'
class AwesomeApp < Sinatra::Base
def initialize(app = nil, params = {})
super(app)
#bootstrap = params.fetch(:bootstrap, false)
end
end
rnicholson's response will be the best answer in most cases but if what you want is to have access to an instance variable in your routes, you can set these up using the before filter as explained in the Sinatra README:
Before filters are evaluated before each request within the same context as the routes will be and can modify the request and response. Instance variables set in filters are accessible by routes and templates:
before do
#note = 'Hi!'
request.path_info = '/foo/bar/baz'
end
get '/foo/*' do
#note #=> 'Hi!'
params['splat'] #=> 'bar/baz'
end

Sharing filters between applications

I am building a modular Padrino application to mount mutiple applications.
I am mounting a base application to /
class BaseApp < Padrino::Application
...
end
I am then mounting other appilications to other endpoints, such as /clients and these applications inherit from the base application:
class ClientsApp < BaseApp
...
end
This inheritence allows me to define all my settings, error handling and any included rack middleware in the app.rb for the BaseApp class.
So far so good. But I would also like to share before and after routing between apps. For example in my BaseApp controller code I want to do this:
BaseApp.controller do
before do
...
end
after do
...
end
get :index do
...
end
end
Rather than repeating these filters in my ClientsApp controller code, like so:
ClientsApp.controller do
before do
...
end
after do
...
end
get :index do
...
end
end
Is there anyway I can DRY up this code and specify the filters once in BaseApp and have them somehow inherited? I understand these filters are methods calls rather than methods.
Thanks!
You can use standard sinatra extensions, put under lib:
# lib/common_filters.rb
module CommonFilters
def self.registered(app)
app.before do
...
end
app.after do
...
end
end
end
Then in yours apps:
# app/app.rb
class MyApp < Padrino::Application
register CommonFilters
end

Resources