You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ruby on Rails is one of our favourite frameworks for web applications development. We love it because of agile and interesting development process, high performance and, of course, ruby programming language.
Below you can find an example of a project`s structure, and its main components
File structure
contains your current database schema and migrations
+-- lib => extended modules for your application
+-- log => app log files
+-- public => The only folder seen by the world as-is. Contains static files and compiled assets.
+-- spec => Unit tests, features, and other test apparatus.
+-- tmp => Temporary files (like cache and pid files).
+-- vendor => third-party code">project_name +-- app | +-- assets => images, fonts, stylesheets, js | +-- controllers | +-- decorators | +-- helpers | +-- mailers | +-- models | +-- performers | +-- policies | +-- presenters | +-- serializers | +-- services | +-- uploaders | +-- views | +-- workers => workers for running processes in the background +-- bin => contains script that starts, update, deploy or run your application. +-- config => configure your application's routes, database, and more +-- db => contains your current database schema and migrations +-- lib => extended modules for your application +-- log => app log files +-- public => The only folder seen by the world as-is. Contains static files and compiled assets. +-- spec => Unit tests, features, and other test apparatus. +-- tmp => Temporary files (like cache and pid files). +-- vendor => third-party code
Controllers
Action Controller is the C in MVC. After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output.
There are a lot of opinions on what a controller should do. A common ground of the responsibilities a controller should have include the following:
Authentication and authorization -- checking whether the entity (oftentimes, a user) behind the request is who it says it is and whether it is allowed to access the resource or perform the action.
Data fetching -- it should call the logic for finding the right data based on the parameters that came with the request. In the perfect world, it should be a call to one method that does all the work. The controller should not do the heavy work, it should delegate it further.
Template rendering -- finally, it should return the right response by rendering the result with the proper format (HTML, JSON, etc.). Or, it should redirect to some other path or URL.
classBooksController < ApplicationController
defshow @book=Book.find(params[:id]) end
defcreate @book=Book.new(book_params)
if@book.save redirect_toaction: 'list' else @subjects=Subject.all renderaction: 'new' end end
private
defbook_params params.require(:books).permit(:title,:price,:subject_id,:description) end
end
classListingsController < ApiController
defindex listings=Current.user.listings
renderjson: ListingSerializer.new(listings).serializable_hash end
Active Record is the M in MVC - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database.
# == Schema Information # # Table name: colors # # id :integer not null, primary key # created_at :datetime not null # updated_at :datetime not null #
Use form object pattern to make your models more lightweight.
Single responsibility principle helps us make the best design decisions about what the class should be responsible for. Your model is a database table, it represents a single entry in the code, so there is no reason to worry and user action.
Form Objects are responsible for the presentation of the form in your application. Each form field is an attribute in a class and can be checked through validation, which will give us clean data and they will go further along the chain. This can be your model, defining a table in the database or, for example, a search form.
if@investor_form.submit(params) flash[:success]='Investor was successfully created.' redirect_toadmin_investor_path(@investor_form.id) else render:new end end
if@investor_form.submit(params) flash[:success]='Investor was successfully updated.' redirect_toadmin_investor_path(@investor) else render:edit end end
The performer pattern creates seperation for the methods in your model that are view related. The performers are modules and are included into the corresponding model.
moduleInvestmentDataPerformer
defself.included(base) base.extendClassMethods end
moduleClassMethods
end
defnon_final_profit returnnilunlessinvestment.non_final_profit investment.non_final_profit * holding / 100 end
deffinal_distribution returnunlessinvestment.distribution.present? investment.distribution * holding / 100 end
Pundit provides a set of helpers which guide in leveraging regular Ruby classes and object oriented design patterns to build a simple, robust and scalable authorization system.
Facades provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
One of the responsibilities that is being thrown at the controller is to prepare the data so it can be presented to user. To remove the responsibility of preparing the data for the view we're using Facade pattern.
classAdmin
classDocumentsFacade
attr_reader:loan,:investor
definitialize(loan_id,investor_id) @loan=Loan.find(loan_id) @investor=Investor.find(investor_id) end
deflender? investor.present? end
defdocuments Document.where(investment_id: loan.id,investor_id: investor.id) end
deflenders loan.lenders.order(:name).uniq.collect{ |l| [l.name,l.id]} end
end
end
Now we can reduce our controller down to:
classDocumentsController < LoansController
defindex add_breadcrumb'Documents' @documents_data=Admin::DocumentsFacade.new(params[:loan_id],params[:investor_id]) end
At Codica we use sidekiq as a full-featured background processing framework for Ruby. It aims to be simple to integrate with any modern Rails application and much higher performance than other existing solutions.
classPartnerAlertWorker
includeSidekiq::Worker
defperform(id) @partner=Partner.find(id) PartnerMailer.alert(@partner).deliver_now end