Implement procedure cloning

This commit is contained in:
Guillaume Lazzara 2016-06-15 11:34:05 +02:00
parent 7fd2aa40ca
commit 7af7859334
10 changed files with 113 additions and 1 deletions

View file

@ -22,6 +22,8 @@ gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
# Enable deep clone of active record models
gem 'deep_cloneable', '~> 2.2.1'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

View file

@ -119,6 +119,8 @@ GEM
sprockets (>= 2.0.0)
database_cleaner (1.4.1)
debug_inspector (0.0.2)
deep_cloneable (2.2.1)
activerecord (>= 3.1.0, < 5.2.0)
devise (3.4.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
@ -634,6 +636,7 @@ DEPENDENCIES
coffee-rails (~> 4.1.0)
css_splitter
database_cleaner
deep_cloneable (~> 2.2.1)
devise
draper
factory_girl
@ -690,4 +693,4 @@ DEPENDENCIES
will_paginate-bootstrap
BUNDLED WITH
1.11.2
1.12.5

View file

@ -83,6 +83,23 @@ class Admin::ProceduresController < AdminController
change_status({archived: params[:archive]})
end
def clone
@procedure = current_administrateur.procedures.find(params[:procedure_id])
new_procedure = @procedure.clone
if new_procedure
flash.notice = 'Procédure clonée'
redirect_to edit_admin_procedure_path(id: new_procedure.id)
else
flash.now.alert = @procedure.errors.full_messages.join('<br />').html_safe
render 'index'
end
rescue ActiveRecord::RecordNotFound
flash.alert = 'Procédure inéxistante'
redirect_to admin_procedures_path
end
def active_class
@active_class = 'active'
end

View file

@ -58,4 +58,11 @@ class Procedure < ActiveRecord::Base
published?
end
def clone
procedure = self.deep_clone(include: [ :types_de_piece_justificative, :types_de_champ, :module_api_carto ])
procedure.archived = false
procedure.published = false
return procedure if procedure.save
end
end

View file

@ -3,6 +3,7 @@
%thead
%th#ID= smart_listing.sortable 'ID', 'id'
%th#libelle= smart_listing.sortable 'Libellé', 'libelle'
%th#lien Actions
- @procedures.each do |procedure|
- procedure = procedure.decorate
@ -10,6 +11,7 @@
%td.col-md-1.col-lg-1= procedure.id
%td.col-md-6.col-lg-6
= link_to(procedure.libelle, "/admin/procedures/#{procedure.id}")
%td= link_to('cloner', admin_procedure_clone_path(procedure.id), 'data-method' => :put, class: 'btn-xs btn-primary')
= smart_listing.paginate
= smart_listing.pagination_per_page_links

View file

@ -4,6 +4,7 @@
%th#ID= smart_listing.sortable 'ID', 'id'
%th#libelle= smart_listing.sortable 'Libellé', 'libelle'
%th#lien Lien
%th#lien Actions
- @procedures.each do |procedure|
- procedure = procedure.decorate
@ -12,6 +13,7 @@
%td.col-md-6.col-lg-6
= link_to(procedure.libelle, "/admin/procedures/#{procedure.id}")
%td= link_to procedure.lien, procedure.lien
%td= link_to('cloner', admin_procedure_clone_path(procedure.id), 'data-method' => :put, class: 'btn-xs btn-primary')
= smart_listing.paginate
= smart_listing.pagination_per_page_links

View file

@ -100,6 +100,7 @@ Rails.application.routes.draw do
put 'archive' => 'procedures#archive', as: :archive
put 'publish' => 'procedures#publish', as: :publish
put 'clone' => 'procedures#clone', as: :clone
resource :accompagnateurs, only: [:show, :update]

View file

@ -265,4 +265,35 @@ describe Admin::ProceduresController, type: :controller do
it { expect(flash[:alert]).to have_content 'Procédure inéxistante' }
end
end
describe 'PUT #clone' do
let!(:procedure) { create(:procedure, administrateur: admin) }
subject { put :clone, procedure_id: procedure.id }
it { expect{ subject }.to change(Procedure, :count).by(1) }
context 'when admin is the owner of the procedure' do
before do
subject
end
it 'creates a new procedure and redirect to it' do
expect(response).to redirect_to edit_admin_procedure_path(id: Procedure.last.id)
expect(flash[:notice]).to have_content 'Procédure clonée'
end
end
context 'when admin is not the owner of the procedure' do
let(:admin_2) { create(:administrateur) }
before do
sign_out admin
sign_in admin_2
subject
end
it { expect(response).to redirect_to :admin_procedures }
it { expect(flash[:alert]).to have_content 'Procédure inéxistante' }
end
end
end

View file

@ -122,4 +122,44 @@ describe Procedure do
it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
end
end
describe 'clone' do
let(:archived) { false }
let(:published) { false }
let(:procedure) { create(:procedure, archived: archived, published: published) }
let!(:type_de_champ_0) { create(:type_de_champ, procedure: procedure, order_place: 0) }
let!(:type_de_champ_1) { create(:type_de_champ, procedure: procedure, order_place: 1) }
let!(:piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
let!(:piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
subject { procedure.clone }
it 'should duplicate specific objects with different id' do
expect(subject.id).not_to eq(procedure.id)
expect(subject).to have_same_attributes_as(procedure)
expect(subject.module_api_carto).to have_same_attributes_as(procedure.module_api_carto)
subject.types_de_champ.zip(procedure.types_de_champ).each do |stc, ptc|
expect(stc).to have_same_attributes_as(ptc)
end
subject.types_de_piece_justificative.zip(procedure.types_de_piece_justificative).each do |stc, ptc|
expect(stc).to have_same_attributes_as(ptc)
end
end
it 'should not duplicate specific related objects' do
expect(subject.dossiers).to eq([])
expect(subject.gestionnaires).to eq([])
expect(subject.assign_to).to eq([])
end
describe 'procedure status is reset' do
let(:archived) { true }
let(:published) { true }
it 'sets published and archived to false' do
expect(subject.archived).to be_falsey
expect(subject.published).to be_falsey
end
end
end
end

View file

@ -113,4 +113,11 @@ RSpec.configure do |config|
end
end
}
RSpec::Matchers.define :have_same_attributes_as do |expected|
match do |actual|
ignored = [:id, :procedure_id, :updated_at, :created_at]
actual.attributes.with_indifferent_access.except(*ignored) == expected.attributes.with_indifferent_access.except(*ignored)
end
end
end