Where to put Padrino controller files in standalone Sinatra application? - ruby

I'm attempting to use Padrino's routing as a standalone addition to a basic Sinatra application.
http://www.padrinorb.com/guides/standalone-usage-in-sinatra
The main reason I need/want the additional Padrino functionality is the ability to separate my routes into multiple controller files.
Is this something I can do without using the whole Padrino package? If so, where do I place the separate controller files? I've tried /controllers/main.rb and /app/controllers/main.rb, where my core Sinatra app is at /app.rb.

You don't quite need to use the padrino routing to achieve the idea of controllers in Sinatra. In your main .rb file for your Sinatra app you can do:
Dir.glob("controllers/*.rb").each { |r| require_relative r }
Place your "controllers" into a controllers directory and the above will require_relative all of them for you. The code all gets lumped into the main ruby file eventually but you gain the ability to logically separate the code.

Related

Rails 3.1 and the lack of a service layer

I'm writing an hotel-like app in Rails 3.1 and I'm new to Rails.
I'd need some advice about how write what is normally managed in the service layer of an app.
The app needs some service to calculate the price, and this methods have to be available for more than one controller. Till now I put all this stuff in a controller but now I have to get it out from there and really I' don't know how and where.
I thought about writing a helper and include it in the controller but I dislike this solution because helpers should only help to render stuff in the view and they shouldn't mess with the business layer related tasks.
How would you code this?
Maybe you can create a folder named services
/app
/controllers
/services
calculation_service.rb
Then you use it on your controllers like this:
def show
#model = Model.find(params[:id])
#total = CalculationService.calculate_sum(#model.price, #model.subtotal)
end
I wouldn't even do this in the controller. I would push the logic to your model if possible. If it's required in multiple models, I'd create a mixin in your lib folder and include it in each model.

Correct Way to do Routes in Sinatra Views

What's the correct way to do routing in a Sinatra view. In Rails we have named routes which are accessible in the controller and view.
Hardcoding the route in the the view feels bad. Is it just a matter of writing custom route helpers, or is there a more standard approach?
The best way is to set up a view helper function. Since Sinatra does not provide view helpers by default, and there is no helper available in sinatra contrib, there is no standard library, and also searching for url helpers turns out not to be too helpful.
Everything that Sinatra provides is the URL Helper but this is not constructing urls either.
I did find however an outdated gem that is doing what you want. It's just one method to do named routing, maybe this provides you with some inspiration to achieve dynamic route calling.

Rails 3.1/Sprockets: Injecting controller variables (or helpers) into javascript assets

I have an action with
def new
#test_var = 'i want this to show'
end
All I want to do is inject that into the javascript called for that page. For example:
#app/assets/javascript/my_model.js.coffee.erb
$ ->
console.log('<%= #test_var %>')
I'm guessing this doesn't work because that the coffeescript/erb is compiled before the controller is accessed...so, if I wanted to inject controller variables into a JavaScript file (client side - NOT accessed via ajax) in 3.1, how should I go about doing it?
I believe the problem is that you're thinking about the asset pipeline all wrong...
asset being the operative word.
It's not a view pipeline. Other things which are assets? images & css files, things which can be preprocessed and then served as-is. The erb/preprocessing of your assets doesn't occur on each pageload/request, rather it occurs on startup/filechange so in production said assets can be optimised, cached and served statically.
You could probably figure out a way to achieve it using Live Compilation (see section 4.2 of http://guides.rubyonrails.org/asset_pipeline.html) but as the docs say:
This mode uses more memory and is lower performance than the default. It is not recommended.
The bad answer would be 'inject the javascript into your view', but decoupling your javascript from your rails controllers/views is a good idea.
A better answer would be to have an asset folder containing all of your controller javascripts, and use some "what page am I on?" javascript to determine whether to run the code or not.
Here's some answers that explain various approaches to this:
Rails 3.1 asset pipeline: how to load controller-specific scripts?
Using Rails 3.1, where do you put your "page specific" javascript code?

Rails structure, should I use a service layer in this case?

I'm new to Ruby and Rails and I'm making my first app. Basically I'm parsing HTML and sending it as JSON to the client.
Right now I've two sources for the HTML data but I could have more in the future. Because of this I thought that it'd be a good idea to remove the code responsible to parse the HTML from the controller and put it into a service layer. I came up with this structure:
app
controllers
main_controller.rb
model
project.rb
task.rb
services
source1_service.rb
source2_service.rb
The MainController call both services to get the projects and tasks; each service parse its own HTML.
Is this a good solution? Is there a more RoR way to do this?
put your services in your models directory, there is no rule that all models have to extend from ActiveRecord::Base, but your services are opaquely data models to the rest of your app (if I understand you right). Ideally, let the service code mimic active record so other people that are just using your model code dont have to know its a different than any other model in your rails app.
Unlike in the Java world, 'the service layer classes' concept is not really popular/used in the RoR world. Its a good idea to remove that code form your controllers (you want your controllers to be thin). But i think you can inject them to your models. If you feel its getting too complicated you can break up your extra code into modules and mixin those modules to your models.
Its not the one and only way of doing things though.
However if parsing HTML include some common logic that can be reused, even in another project its a good idea to put it inside the lib/ folder.

Sinatra, where to place the require statments

I'm currently developing a Sinatra/Rack app, and I've run into a design problem. I was looking around, and I'm not quite sure where to place the bulk of the require statements.
I figure they go in one of two places, either the main.rb after requiring Sinatra itself, or they go in the config.ru so they are all loaded at the start of the application.
I'm currently leaning towards the main.rb as that is what's loaded by all of the testing applications.
Thank you for your help.
I recommend:
Require your main app file only from your config.ru.
Require Sinatra and views gems in your main app
Create individual init.rb files for each of your helpers, models, and routes, and require those in your main app.
Require DB-related gems in models/init.rb
Here's an example of the layout I use:
Using Sinatra for larger projects via multiple files
Note that by loading DB-related gems and setting up your DB in your models/init.rb you can (from IRB) load just that file and have your full model stack available for poking at.
Take a look at this blog post by Engine Yard. It does a fairly good job of explaining what you want to know: https://www.engineyard.com/blog/using-the-rubygems-bundler-for-your-app
Take a look at my source code.
https://github.com/sirfilip/sinatrablog
:)
Just realized i have to remove all of the require statements in my models since they are not needed anyway.
The most interesting file in there is the bootloader.rb. If you want to follow the request path start from the config ru which acts as a front controller for the app.

Resources