Skip to content

Commit

Permalink
Merge pull request #1019 from mdeniz/add_style_guide_into_docs_dir
Browse files Browse the repository at this point in the history
[webui+api] Added style guide into docs dir for RoR
  • Loading branch information
mdeniz committed Aug 17, 2015
2 parents e5ffb8a + 6064232 commit fd14247
Show file tree
Hide file tree
Showing 7 changed files with 390 additions and 1 deletion.
31 changes: 31 additions & 0 deletions docs/dev/GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Development Style Guide
This development guide tries to show you how we style the code of OBS.

## Models
All the **ActiveRecord::Base** models should use the same structure to be easy to follow for everyone. We have
overwritten the template for model, so you can just use Rails::Generators like that:

```
rails generate model Dog
```

For a better comprehension [here](model_template_example.rb) you have an example with code in it's place.

## Scaffold Controllers

All the Controllers should use the same structure to be easy to follow for everyone. We have
overwritten the template for controllers too, so you can just use Rails::Generators like that:

```
rails generate scaffold_controller Webui::Dog
```

Have in mind that namespaced controllers that uses non-namespaced models should be created as follows:

```
rails generate scaffold_controller Webui::Dog --model-name=Dog
```

Also to have in mind is that the template is based on **Pundit policies** and you will have to create it.

For a better comprehension [here](controller_template_example.rb) you have an example with code in it's place.
104 changes: 104 additions & 0 deletions docs/dev/controller_template_example.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Controller to manage dogs
class Webui::DogsController < ApplicationController
#### Includes and extends ###################################################
include AnimalControl

#### Constants ##############################################################
BASIC_DOG_NAMES = %w(Tobby Thor Rambo Dog Blacky)

#### Self config ############################################################

#### Callbacks macros: before_action, after_action, etc. ####################
before_action :set_dog, only: [:show, :edit, :update, :destroy]
# Pundit authorization policies control
after_action :verify_authorized, :except => [:index, :blacks]
after_action :verify_policy_scoped, :only => [:index, :blacks]

#### CRUD actions ###########################################################

# GET /dogs
def index
@dogs = policy_scope(Dog)
end

# GET /dogs/1
def show
if @dog.present?
authorize @dog
else
skip_authorization
end
end

# GET /dogs/new
def new
@dog = Dog.new
authorize @dog
end

# GET /dogs/1/edit
def edit
authorize @dog
end

# POST /dogs
def create
@dog = Dog.new(dog_params)
authorize @dog
if @dog.save
redirect_to @dog, notice: 'Dog was successfully created.'
else
render :new
end
end

# PATCH/PUT /dogs/1
def update
authorize @dog
if @dog.update(dog_params)
redirect_to @dog, notice: 'Dog was successfully updated.'
else
render :edit
end
end

# DELETE /dogs/1
def destroy
authorize @dog
@dog.destroy
redirect_to dogs_url, notice: 'Dog was successfully destroyed.'
end

#### Non CRUD actions #######################################################

# List all the black dogs
# GET /dogs/blacks
def blacks
@dogs = policy_scope(Dog).blacks
call_them(@dogs)
render :index
end

#### Non actions methods ####################################################
# Use hide_action if they are not private

def call_them(dogs = [])
say("Hey!")
dogs.each do |dog|
dog.bark
end
end

hide_action :call_them

private
# Use callbacks to share common setup or constraints between actions.
def set_dog
@dog = Dog.find(params[:id])
end

# Only allow a trusted parameter "white list" through.
def dog_params
params.require(:dog).permit(:name, :color)
end
end
105 changes: 105 additions & 0 deletions docs/dev/model_template_example.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# This is a model class to represent dogs and is an example of how they have to
# be structured for a better comprehension
class Dog < ActiveRecord::Base
#### Includes and extends ###################################################
include AnimalSystems
include ActiveModel::AttributeMethods

#### Constants ##############################################################
NUMBER_OF_LEGS = 4
NUMBER_OF_QUEUES = 1
NUMBER_OF_EYES = 2
POSSIBLE_COLORS = %w(white black brown vanilla chocolate dotted)

#### Self config ############################################################
self.table_name = "OBS_dogs"

#### Attributes #############################################################
attr_accessor :number_of_barks
attribute_method_prefix 'reset_'

alias_method :go_home, :save
alias_method :go_home!, :save!

#### Associations macros (Belongs to, Has one, Has many) ####################
belongs_to :owner, class_name: 'Person'
belongs_to :herd
belongs_to :house
has_one :prefered_person, class_name: 'Person'
has_many :places_to_pee, class_name: 'Place'
has_many :places_to_sleep, through: :house

#### Callbacks macros: before_save, after_save, etc. ########################
before_destroy :bark
after_destroy :cry

#### Scopes (first the default_scope macro if is used) ######################
default_scope where(alive: true)
scope :blacks, -> { where(color: 'brown') }
scope :deads, -> { rewhere(alive: false) }

#### Validations macros #####################################################
validates :name, :color, pressence: true

#### Class methods using self. (public and then private) ####################
#### To define class methods as private use private_class_method
def self.born!(attributes)
say("It's alive!")
dog = new(attributes)
dog.alive = true
dog.save!
dog.cry
dog
end

def self.killall_by(attributes = {})
say("Die!")
where(attributes).each do |dog|
dog.kill
end
end

def self.call_all
say("Fiuuiuuuu!")
all.each do |dog|
dog.bark
end

end

#### private

def self.say(string)
puts "[Dog's Master] >> #{string}"
end

private_class_method :say

#### Instance methods (public and then protected/private) ###################
def initialize(attributes={})
super
@number_of_barks = 0
end

def bark
say('Guau!')
@number_of_barks++
end

def cry
say('Iiiiii Iiii Iiiii!!')
end

protected

def say(string)
puts "[#{name}] >> #{string}"
end

private

def reset_attribute(attribute)
send("#{attribute}=", 0)
end

end
13 changes: 13 additions & 0 deletions src/api/app/policies/application_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,17 @@ def destroy?
def scope
Pundit.policy_scope!(user, record.class)
end

class Scope
attr_reader :user, :scope

def initialize(user, scope)
@user = user
@scope = scope
end

def resolve
scope
end
end
end
41 changes: 41 additions & 0 deletions src/api/lib/templates/active_record/model/model.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<% module_namespacing do -%>
# TODO: Please overwrite this comment with something explaining the model target
class <%= class_name %> < <%= parent_class_name.classify %>
#### Includes and extends ###################################################

#### Constants ##############################################################

#### Self config ############################################################

#### Attributes #############################################################
<% attributes.select(&:token?).each do |attribute| -%>
has_secure_token<% if attribute.name != "token" %> :<%= attribute.name %><% end %>
<% end -%>
<% if attributes.any?(&:password_digest?) -%>
has_secure_password
<% end -%>
#### Associations macros (Belongs to, Has one, Has many) ####################
<% attributes.select(&:reference?).each do |attribute| -%>
belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %><%= ', required: true' if attribute.required? %>
<% end -%>
#### Callbacks macros: before_save, after_save, etc. ########################
#### Scopes (first the default_scope macro if is used) ######################
#### Validations macros #####################################################
#### Class methods using self. (public and then private) ####################
#### To define class methods as private use private_class_method
#### private
#### Instance methods (public and then protected/private) ###################
protected
private
end
<% end -%>
95 changes: 95 additions & 0 deletions src/api/lib/templates/rails/scaffold_controller/controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<% if namespaced? -%>
require_dependency "<%= namespaced_file_path %>/application_controller"
<% end -%>
<% module_namespacing do -%>
# TODO: Please overwrite this comment with something explaining the controller target
class <%= controller_class_name %>Controller < ApplicationController
#### Includes and extends ###################################################
#### Constants ##############################################################
#### Self config ############################################################
#### Callbacks macros: before_action, after_action, etc. ####################
before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy]
# Pundit authorization policies control
after_action :verify_authorized, :except => :index
after_action :verify_policy_scoped, :only => :index
#### CRUD actions ###########################################################
# GET <%= route_url %>
def index
@<%= plural_table_name %> = policy_scope(<%= class_name %>)
end
# GET <%= route_url %>/1
def show
if @<%= singular_table_name %>.present?
authorize @<%= singular_table_name %>
else
skip_authorization
end
end
# GET <%= route_url %>/new
def new
@<%= singular_table_name %> = <%= orm_class.build(class_name) %>
authorize @<%= singular_table_name %>
end
# GET <%= route_url %>/1/edit
def edit
authorize @<%= singular_table_name %>
end
# POST <%= route_url %>
def create
@<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
authorize @<%= singular_table_name %>
if @<%= orm_instance.save %>
redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully created.'" %>
else
render :new
end
end
# PATCH/PUT <%= route_url %>/1
def update
authorize @<%= singular_table_name %>
if @<%= orm_instance.update("#{singular_table_name}_params") %>
redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully updated.'" %>
else
render :edit
end
end
# DELETE <%= route_url %>/1
def destroy
authorize @<%= singular_table_name %>
@<%= orm_instance.destroy %>
redirect_to <%= index_helper %>_url, notice: <%= "'#{human_name} was successfully destroyed.'" %>
end
#### Non CRUD actions #######################################################
#### Non actions methods ####################################################
# Use hide_action if they are not private
private
# Use callbacks to share common setup or constraints between actions.
def set_<%= singular_table_name %>
@<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
end

# Only allow a trusted parameter "white list" through.
def <%= "#{singular_table_name}_params" %>
<%- if attributes_names.empty? -%>
params[:<%= singular_table_name %>]
<%- else -%>
params.require(:<%= singular_table_name %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
<%- end -%>
end
end
<% end -%>

0 comments on commit fd14247

Please sign in to comment.