diff --git a/app/controllers/suppliers/application_controller.rb b/app/controllers/suppliers/application_controller.rb index a5e4f504..d2dbc6fc 100644 --- a/app/controllers/suppliers/application_controller.rb +++ b/app/controllers/suppliers/application_controller.rb @@ -21,6 +21,7 @@ module Suppliers find_current_supplier! return unless current_supplier.present? current_employee.enrich_with_settings current_supplier.settings_for(current_employee) + raise CanCan::AccessDenied unless current_employee.active? @current_ability = ::Ability.new( current_employee ) end diff --git a/app/models/employee.rb b/app/models/employee.rb index cd5586f6..d1d0d8a9 100644 --- a/app/models/employee.rb +++ b/app/models/employee.rb @@ -1,13 +1,19 @@ class Employee include SimplyStored::Couch include ActiveModel::SerializerSupport + attr_reader :settings DEFAULT_SETTINGS = { 'manager' => false, 'active' => true, 'color' => '#3a87ad' } - attr_accessor *DEFAULT_SETTINGS.keys - attr_reader :settings + DEFAULT_SETTINGS.each do |attribute, default_value| + define_method(attribute) { settings.public_send attribute } + define_method("#{attribute}=") { |value| settings.set attribute, value } + if default_value == true or default_value == false # boolean + define_method(:"#{attribute}?"){ public_send attribute } + end + end view :by_confirmation_token, key: :confirmation_token # devise confirmable devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable, :confirmable @@ -35,10 +41,13 @@ class Employee def enrich_with_settings(settings) @settings = settings - settings.settings.each do |attribute, value| - public_send "#{attribute}=", value - end - settings + end + alias_method :settings=, :enrich_with_settings + + alias_method :orig_save, :save + def save(*args) + settings.persist! + orig_save(*args) end def settings diff --git a/app/models/supplier.rb b/app/models/supplier.rb index a9511627..8bbe7c54 100644 --- a/app/models/supplier.rb +++ b/app/models/supplier.rb @@ -45,7 +45,7 @@ class Supplier alias_method :non_enriced_employees, :employees def employees - non_enriced_employees.tap { |es| es.each{ |e| e.enrich_with_settings(settings_for(e) ) }} + @cached_enriched_employees ||= non_enriced_employees.tap { |es| es.each{ |e| e.enrich_with_settings(settings_for(e) ) }} end after_create :add_section_on_create @@ -94,6 +94,14 @@ class Supplier @active_lists end + before_method :reload do + @employees = nil + @cached_enriched_employees = nil + @employee_settings = nil + @active_lists = nil + @active_orders = nil + end + # Return the currently active tables for the supplier def active_tables(options = {}) diff --git a/app/serializers/supplier_employees_settings.rb b/app/serializers/supplier_employees_settings.rb index 4e2bf604..6d173190 100644 --- a/app/serializers/supplier_employees_settings.rb +++ b/app/serializers/supplier_employees_settings.rb @@ -6,13 +6,13 @@ class SupplierEmployeesSettings @employee_ids = supplier.employee_ids || [] end - def for_employee(employee_id) - employee_id = employee_id.id if employee_id.is_a?(Employee) - if employee_ids.include? employee_id - SupplierEmployeeSettings.new(self, employee_id, dictionary[employee_id]) + def for_employee(employee) + if employee_ids.include? employee.id + settings = SupplierEmployeeSettings.new(self, employee, dictionary[employee.id]) else - SupplierEmployeeSettings::NullObject.new + settings = SupplierEmployeeSettings::NullObject.new end + employee.settings = settings end def [](val) @@ -48,7 +48,7 @@ class SupplierEmployeesSettings class SupplierEmployeeSettings delegate :as_json, :to_json, to: :settings - attr_reader :id, :settings, :all_employees_settings + attr_reader :employee, :settings, :all_employees_settings class NullObject < ::NullObject ::Employee::DEFAULT_SETTINGS.each do |attribute, value| if value == true or value == false @@ -58,9 +58,9 @@ class SupplierEmployeesSettings end end - def initialize(all_employees_settings, employee_id, settings = {}) + def initialize(all_employees_settings, employee, settings = {}) @all_employees_settings = all_employees_settings - @id = employee_id + @employee = employee @settings = Employee.default_settings.merge(settings || {}) end @@ -70,10 +70,7 @@ class SupplierEmployeesSettings def set(attribute, value, persist: false) settings[attribute] = value - all_employees_settings[id][attribute] = value - if employee = all_employees_settings.supplier.employees.find{|e| e.id == id} - employee.public_send("#{attribute}=", value) - end + all_employees_settings[employee.id][attribute] = value persist! if persist self end diff --git a/config/initializers/monkey_patches.rb b/config/initializers/monkey_patches.rb index 0eefdc57..6f743353 100644 --- a/config/initializers/monkey_patches.rb +++ b/config/initializers/monkey_patches.rb @@ -3,3 +3,22 @@ class NilClass false end end + +module MethodPrependAndAppend + def before_method(m, &blk) + alias_method :"#{m}_before_extending", m + define_method m do + instance_eval(&blk) + send :"#{m}_before_extending" + end + end + def after_method(m, &blk) + alias_method :"#{m}_before_extending", m + define_method m do + result = send :"#{m}_before_extending" + instance_eval(result, &blk) + end + end +end + +Class.send :include, MethodPrependAndAppend diff --git a/spec/models/employee_spec.rb b/spec/models/employee_spec.rb index a49e8ca1..7687ac8f 100644 --- a/spec/models/employee_spec.rb +++ b/spec/models/employee_spec.rb @@ -13,4 +13,53 @@ describe Employee do end end end + + describe 'settings' do + let(:supplier){ build :supplier } + let(:employee){ create :employee} + before do + supplier.add_employee employee + employee.enrich_with_settings supplier.settings_for(employee) + end + + it 'responds to defaults' do + employee.manager?.should be false + employee.active?.should be true + employee.color.should == '#3a87ad' + end + + it 'Sets the values non persisted on the supplier' do + employee.manager = true + supplier.employee_settings_storage[employee.id]['manager'].should be true + supplier.reload + supplier.employee_settings_storage.should_not be_present + end + + it 'persists settings of the supplier on save' do + employee.manager = true + employee.save + supplier.reload + supplier.employee_settings_storage[employee.id]['manager'].should be true + end + + it 'does not non existant suppliers on save' do + employee.manager = true + ->{ employee.save }.should_not change{ Supplier.count } + end + + it 'sets attributes on the employee if fetched through the supplier' do + settings = supplier.settings_for employee + settings.is_manager! + employee.manager?.should be true + end + + it 'Implements settings on employees' do + supplier.update employee_settings_storage: {employee.id => { 'manager' => true }} + supplier.reload + # Without the acessor employees on the supplier, the employee and therefore its settings are not linked to the supplier + linked_employee = supplier.employees.find{|e| e.id == employee.id } + linked_employee.should be_manager + end + + end end