<repo_name>suarezcumare/rankmi-api<file_sep>/spec/models/tree_spec.rb
# == Schema Information
#
# Table name: trees
#
#  id         :integer          not null, primary key
#  area       :string
#  nota       :float
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  ancestry   :string
#

require 'rails_helper'

RSpec.describe Tree, type: :model do
  
  context 'validations' do
    it "should presence_of a area" do
      should validate_presence_of(:area)
    end

    it "should presence_of a nota" do
      should validate_presence_of(:nota)
    end
  end

  describe "#sibling_count" do
   let (:management) { FactoryGirl.create(:tree, area: "Management", nota: 0) }

   it "when is siblings, returns the number in the tree" do
      management_1 = management.children.create(area: "management 1", nota: 1)
      management_2 = management.children.create(area: "management 2", nota: 2)
     expect(management_1.sibling_count - 1).to eq 1
   end

   it "when is not siblings, returns the number of siblings in the tree" do
     expect(management.sibling_count - 1).to eq 0
   end
  end

  describe "#sibling_notas" do
   let (:management) { FactoryGirl.create(:tree, area: "Management", nota: 1) }

   it "when is siblings, returns the number in the tree" do
      management_1 = management.children.create(area: "management 1", nota: 5)
      management_2 = management.children.create(area: "management 2", nota: 2)
     expect(management_2.sibling_notas).to eq 7
   end

   it "when is not siblings, returns the number of siblings in the tree" do
     expect(management.sibling_notas).to eq 1
   end
  end

  describe "#as_json" do
    context 'when is elements' do
      let (:management) { FactoryGirl.create(:tree, area: "Management", nota: 1) }

      it "when is siblings, returns the number in the tree" do
        management_1 = management.children.create(area: "management 1", nota: 5)
        management_2 = management.children.create(area: "management 2", nota: 2)
        _tree = Tree.as_json
        expect(_tree.count).to eq 1
        expect(_tree.first[:hijos].count).to eq 2
      end
    end

    context 'when is not elements' do
      Tree.destroy_all
      it "when is not siblings, returns the number of siblings in the tree" do
        _tree = Tree.as_json
        expect(_tree).to eq []
        expect(_tree.count).to eq 0
      end
    end
  end
end
<file_sep>/config/routes.rb
Rails.application.routes.draw do
  resources :trees, only: [:index, :update] do
    post :create_child
  end
end
<file_sep>/palindrome.rb
#palindromo
#solucion, sin mucho que decir
#Solo en dada la palabra si es igual al contrario y al reverse, retorna palindromo
def palindromo(text)
  if text.downcase == text.downcase.reverse
    "palindrome"
  else
    "no palindrome"
  end
end


#Dado un numero, retornar el valor de la posicion en un archivo de excel.

#solucion
#En esta solucion com te comente ruby tiene para hacer el recorrido sin problemas, lo que hice fue iterar hasta el numero
#que necesitaba y al final solo obtener el valor necesitado, teniendo la constante de hash guarda al ejecutar la app
#se ejecutara una vez, lo demas ya seria solo buscar la solucion rapida y sencilla
h = {}
('a'..'zzz').each_with_index{|w, i| h[i+1] = w }

def excel(number)
  h[number]
end



#.- Crear un algoritmo al cual se le deba ingresar un array de n números enteros, más un numero de resultado, ejemplo: Input: numbers={2, 7, 11, 15}, target=9 Este algoritmo debe ser capaz de encontrar dos números dentro del array que sumados sean igual al numero target,obviamente el algoritmo no puede ser un for que vaya sumando todos los números de uno en uno, debe tener mayor inteligencia.El resultado debe indicar la posición del array de los números que sumados dan el resultado esperado, ejemplo: Output: index1=1, index2=2


#solucion
#en ruby existe combination par aun numero de valores, entonces recorro todas las posibles opciones y 
#alli lo que hago es iterar por cada una de ella y obtener lo que necesito al final

 #numbers( [2, 7, 11, 15], 9)
 def numbers(array = [], sum = 0)
   value = array.combination(2).find_all { |x, y| x + y == sum } || []

   if value.count > 0
     puts "index1=#{array.index(value.first[0])}, index2=#{array.index(value.first[1])}"
   else
     puts "index1=-1, index2=-1, sin solucion"
   end
 end
<file_sep>/spec/requests/trees_spec.rb
require 'rails_helper'

RSpec.describe "Trees", type: :request do
  describe "GET /trees" do
    context 'when tree not exists' do
      Tree.destroy_all
      it "return ok but with 0 element" do
        get trees_path
        expect(response).to have_http_status(200)
        expect(json["response"].length).to equal(0)
      end
    end

    context 'when tree exists' do
      let (:management) { FactoryGirl.create(:tree, area: "Management", nota: 0) }
      it "return ok" do
        management_1 = management.children.create(area: "management 1", nota: 1)
        management_2 = management.children.create(area: "management 2", nota: 2)

        get trees_path
        expect(response).to have_http_status(200)
        expect(json["response"].length).to equal(1)
        expect(json["response"][0]["hijos"].length).to equal(2)
      end
    end
  end

  describe "Put /update/:id" do
    let!(:management) { create(:tree) }
    let(:valid_attributes) { {"tree": { "nota": 10.0 } } }

    context 'when tree exists' do
      let (:management) { FactoryGirl.create(:tree, area: "Management", nota: 0) }
      it "return " do
        management_1 = management.children.create(area: "management 1", nota: 1)
        management_2 = management.children.create(area: "management 2", nota: 2)
        put tree_path(management_2.id), params: valid_attributes
        average = (management_1.nota + management_2.reload.nota) / 2
        expect(json["response"]["id"]).to eq (management_2.id)
        expect(json["response"]["area"]).to eq (management_2.area)
        expect(json["response"]["nota"].to_f).to eq(10.0)
        expect(Tree.first.nota).to eq(average)
      end
    end

    context 'when tree not exists' do
      let(:invalid_attributes) { {"tree": {"nota": 3.1 } } }
      it "return ok but errors" do
        put tree_path(100), params: invalid_attributes
        expect(json["status"]).to eq("not_found") 
      end
    end
  end

  describe "Put /tree/:id/create_child" do
    let!(:management) { create(:tree) }
    let(:valid_attributes) { {"tree": { "area": "nombre", "nota": 3.1 } } }

    context 'when tree exists' do
      let (:management) { FactoryGirl.create(:tree, area: "Management", nota: 0) }
      it "return " do
        management_1 = management.children.create(area: "management 1", nota: 1)
        management_2 = management.children.create(area: "management 2", nota: 2)
        post tree_create_child_path(management_2.id), params: valid_attributes
        average = (management_1.nota + management_2.reload.nota) / 2
        expect(json["response"]["area"]).to eq ("nombre")
        expect(json["response"]["nota"].to_f).to eq(3.1)
        expect(Tree.first.nota).to eq(average)
      end
    end

    context 'when tree not exists' do
      let(:invalid_attributes) { {"tree": {"nota": 3.1 } } }
      it "return ok but errors" do
        post tree_create_child_path(management.id), params: invalid_attributes
        expect(json["response"]["area"][0..17]).to eq( [I18n.t("activerecord.errors.models.tree.attributes.area.blank")] )
      end
    end
  end

end
<file_sep>/db/data/20171015211217_tree_example.rb
class TreeExample < SeedMigration::Migration
  def up
    management = Tree.create(area: "Gerencia", nota: 11)
    management_1 = management.children.create(area: "Gerencia 1", nota: 12)
    management_2 = management.children.create(area: "Gerencia 2", nota: 13)

    management_1.children.create(area: "Gerencia 1 - 1", nota: 14)
    management_1.children.create(area: "Gerencia 1 - 2", nota: 15)

    management_2.children.create(area: "Gerencia 2 - 1", nota: 16)
    management_2.children.create(area: "Gerencia 2 - 2", nota: 17)
  end

  def down
    Tree.destroy_all
  end
end
<file_sep>/README.md
# README

#### It's a test made by [**<NAME>**](https://www.linkedin.com/in/suarezcumare) to Rankmi company.

---

#### About this:

* Ruby 2.4.0

* Rails 5.1.4

* PG

* Rspec

* Anotate

* seed_migration

* ancestry

---

#### Instructions:

"Se requiere crear un api utilizando RoR que permita almacenar los resultados para una
jerarquía de N niveles con 0 a N áreas hijo por area padre. (las tablas creadas deben
ser poblada con seeds o como se estime conveniente).
- El api debe tener un endpoint que retorne la jerarquía de áreas creada con sus
respectivas notas ya calculadas. Debe responder en formato json con una estructura
similar a la siguiente: https://sc-rankmi.herokuapp.com/trees


- Generar un endpoint que permite agregar un nuevo hijo a un área ya creada. Al crearse
el nuevo hijo se debe recalcular la nota de las áreas superiores.
(https://sc-rankmi.herokuapp.com/trees/:id
- Generar un endpoint que permita cambiar un área dentro de la jerarquía. Los resultados
deben ser recalculados al realizarse el cambio.."
(https://sc-rankmi.herokuapp.com/trees/:id/create_child
---

#### Link to the test:

- [**Here**](https://sc-rankmi.herokuapp.com/trees) 

---

<file_sep>/app/models/tree.rb
# == Schema Information
#
# Table name: trees
#
#  id         :integer          not null, primary key
#  area       :string
#  nota       :float
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  ancestry   :string
#

class Tree < ApplicationRecord
  has_ancestry

  validates :area, presence: true
  validates :nota, presence: true
  after_commit :update_parent, on: [:create, :update]

  def self.as_json(options={}, hash=nil)
      hash ||= arrange(options)
      current_hast = []
      hash.each do |node, children|
        branch = {id: node.id, area: node.area, nota: node.nota}
        branch[:hijos] = as_json(options, children) unless children.empty?
        current_hast << branch
      end
      current_hast
    rescue SomeError
      return []
  end

  def sibling_notas
      siblings.pluck(:nota).sum
    rescue SomeError
      return 0
  end

  def sibling_count
      siblings.count
    rescue SomeError
      return 1
  end

  private
    def update_parent(child=self)
      update_notas(child)
    end

    def update_notas(child)
      if child.has_parent?
        parent = child.parent
        average = child.sibling_notas / child.sibling_count
        parent.update_columns(nota: average)
        update_notas(parent)
      end
    end
end
<file_sep>/spec/factories/tree.rb
FactoryGirl.define do
  factory :tree, :class => 'Tree' do
    area { Faker::Name.title}
    nota { Faker::Number.decimal(2, 3) }
  end
end
