i_am_i_can 3.0.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +236 -174
  4. data/lib/generators/i_am_i_can/setup_generator.rb +3 -7
  5. data/lib/generators/i_am_i_can/templates/migrations/i_am_i_can.erb +8 -8
  6. data/lib/generators/i_am_i_can/templates/models/permission.erb +4 -2
  7. data/lib/generators/i_am_i_can/templates/models/role.erb +3 -1
  8. data/lib/generators/i_am_i_can/templates/models/role_group.erb +3 -1
  9. data/lib/i_am_i_can/configs/config.rb +2 -3
  10. data/lib/i_am_i_can/configs/configs.rb +1 -7
  11. data/lib/i_am_i_can/helpers/dynamic.rb +102 -0
  12. data/lib/i_am_i_can/helpers/result_of.rb +71 -0
  13. data/lib/i_am_i_can/permission/assignment.rb +12 -60
  14. data/lib/i_am_i_can/permission/definition.rb +8 -28
  15. data/lib/i_am_i_can/permission.rb +18 -24
  16. data/lib/i_am_i_can/resource.rb +24 -19
  17. data/lib/i_am_i_can/role/assignment.rb +24 -45
  18. data/lib/i_am_i_can/role/definition.rb +17 -47
  19. data/lib/i_am_i_can/role.rb +14 -0
  20. data/lib/i_am_i_can/role_group/assignment.rb +6 -0
  21. data/lib/i_am_i_can/role_group/definition.rb +25 -0
  22. data/lib/i_am_i_can/subject/permission_querying.rb +28 -40
  23. data/lib/i_am_i_can/subject/role_querying.rb +8 -8
  24. data/lib/i_am_i_can/subject.rb +0 -10
  25. data/lib/i_am_i_can/support/association_class_methods.rb +43 -0
  26. data/lib/i_am_i_can/{configurable.rb → support/configurable.rb} +0 -7
  27. data/lib/i_am_i_can/support/reflection.rb +36 -0
  28. data/lib/i_am_i_can/version.rb +1 -1
  29. data/lib/i_am_i_can.rb +33 -16
  30. metadata +9 -9
  31. data/Gemfile.lock +0 -121
  32. data/lib/i_am_i_can/dynamic_generate.rb +0 -95
  33. data/lib/i_am_i_can/permission/helpers.rb +0 -75
  34. data/lib/i_am_i_can/permission/p_array.rb +0 -22
  35. data/lib/i_am_i_can/reflection.rb +0 -25
  36. data/lib/i_am_i_can/role/helpers.rb +0 -76
@@ -5,14 +5,16 @@ class <%= permission_c %> < ActiveRecord::Base
5
5
  has_and_belongs_to_many :related_role_groups,
6
6
  join_table: '<%= group_pms_tb %>', foreign_key: :<%= group_u %>_id, class_name: '<%= group_c %>', association_foreign_key: :<%= permission_u %>_id
7
7
  <% end %>
8
+ belongs_to :obj, polymorphic: true
9
+
8
10
  acts_as_permission
9
11
  end
10
12
 
11
13
  __END__
12
14
 
13
- string :pred, null: false
15
+ string :action, null: false
14
16
  string :obj_type
15
17
  integer :obj_id
16
18
  string :desc
17
19
 
18
- index %i[ pred obj_type obj_id ], unique: true
20
+ index %i[ action obj_type obj_id ], unique: true
@@ -5,9 +5,11 @@ class <%= role_c %> < ActiveRecord::Base
5
5
  has_and_belongs_to_many :related_stored_groups,
6
6
  join_table: '<%= group_role_tb %>', foreign_key: :<%= group_u %>_id, class_name: '<%= group_c %>', association_foreign_key: :<%= role_u %>_id
7
7
  <% end %>
8
- has_and_belongs_to_many :stored_permissions,
8
+ has_and_belongs_to_many :permissions,
9
9
  join_table: '<%= role_pms_tb %>', foreign_key: :<%= permission_u %>_id, class_name: '<%= permission_c %>', association_foreign_key: :<%= role_u %>_id
10
10
 
11
+ has_many_temporary_permissions
12
+
11
13
  acts_as_role
12
14
 
13
15
  # default_scope { with_stored_permissions }
@@ -1,10 +1,12 @@
1
1
  class RoleGroup < ActiveRecord::Base
2
- has_and_belongs_to_many :stored_permissions,
2
+ has_and_belongs_to_many :permissions,
3
3
  join_table: '<%= group_pms_tb %>', foreign_key: :<%= permission_u %>_id, class_name: '<%= permission_c %>', association_foreign_key: :<%= group_u %>_id
4
4
 
5
5
  has_and_belongs_to_many :members,
6
6
  join_table: '<%= group_role_tb %>', foreign_key: :<%= role_u %>_id, class_name: '<%= role_c %>', association_foreign_key: :<%= group_u %>_id
7
7
 
8
+ has_many_temporary_permissions
9
+
8
10
  acts_as_role_group
9
11
 
10
12
  # default_scope { with_members.with_stored_permissions) }
@@ -2,14 +2,13 @@ module IAmICan
2
2
  module Configs
3
3
  class Config
4
4
  attr_accessor :subject_class, :role_class, :role_group_class, :permission_class,
5
- :auto_define_before, :strict_mode, :without_group, :default_save, :act
5
+ :auto_definition, :strict_mode, :without_group, :act
6
6
 
7
7
  def initialize(*classes)
8
8
  self.subject_class, self.role_class, self.permission_class, self.role_group_class = classes
9
- self.auto_define_before = false
9
+ self.auto_definition = false
10
10
  self.strict_mode = false
11
11
  self.without_group = false
12
- self.default_save = true
13
12
  end
14
13
 
15
14
  def subject_model
@@ -2,9 +2,7 @@ require 'i_am_i_can/configs/config'
2
2
 
3
3
  module IAmICan
4
4
  module Configs
5
- cattr_accessor :configs do
6
- { }
7
- end
5
+ cattr_accessor :configs, default: { }
8
6
 
9
7
  def self.set_for(subject:, role:, permission:, role_group: nil, &block)
10
8
  config = Config.new(subject, role, permission, role_group)
@@ -21,9 +19,5 @@ module IAmICan
21
19
  def self.get(class_name)
22
20
  configs[class_name]
23
21
  end
24
-
25
- def self.take
26
- configs.values.first
27
- end
28
22
  end
29
23
  end
@@ -0,0 +1,102 @@
1
+ module IAmICan
2
+ module Dynamic
3
+ extend self
4
+
5
+ def scopes
6
+ #
7
+ # Generate scopes of each specified i_am_i_can association
8
+ #
9
+ # scope :with_stored_roles, -> { includes(:stored_roles) }
10
+ #
11
+ proc do |keys|
12
+ keys.each do |k|
13
+ scope :"with_#{_reflect_of(k)}", -> { includes(_reflect_of(k)) }
14
+ end
15
+ end
16
+ end
17
+
18
+ def class_reflections
19
+ #
20
+ # Extend each associated querying to a class method that returns ActiveRecord::Relation
21
+ #
22
+ # Suppose: in UserRole model,
23
+ # has_and_belongs_to_many :related_users
24
+ #
25
+ # It will do like this:
26
+ # def self.related_users
27
+ # User.with_stored_roles.where(user_roles: { id: self.ids })
28
+ # end
29
+ #
30
+ # Usage:
31
+ # UserRole.all.related_users
32
+ #
33
+ proc do
34
+ %w[ subject role role_group permission ].each do |k|
35
+ next if _reflect_of(k).blank?
36
+ define_singleton_method _reflect_of(k) do
37
+ model = i_am_i_can.send("#{k}_model")
38
+ raise NoMethodError unless (reflect_name = model._reflect_of(i_am_i_can.act))
39
+
40
+ model.send("with_#{reflect_name}").where(
41
+ self.name.underscore.pluralize => { id: self.ids }
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ def assignment_helpers
49
+ #
50
+ # Generate methods for each Content of Assignment
51
+ #
52
+ # Example for a subject model called User, which `has_and_belongs_to_many :stored_roles`.
53
+ # You call the proc below by given contents [:role], then:
54
+ #
55
+ proc { |contents| contents.each do |content|
56
+ content_cls = i_am_i_can.send("#{content}_class")
57
+ _plural = '_' + content.to_s.pluralize
58
+
59
+ # _stored_roles_exec
60
+ # Add / Remove (by passing action :cancel) roles to a user instance
61
+ define_method "_#{_reflect_of(content)}_exec" do |action = :assignment, instances = [ ], **conditions|
62
+ collection = send(_plural)
63
+ if conditions.present? && action == :assignment
64
+ # Role.where(name: [...]).where.not(id: roles.ids)
65
+ query_result = content_cls.constantize.where(conditions).where.not(id: collection.ids)
66
+ elsif conditions.present? && action == :cancel
67
+ # Role.where(id: roles.ids, name: [...])
68
+ query_result = content_cls.constantize.where(id: collection.ids, **conditions)
69
+ end
70
+
71
+ objects = [*(query_result || [ ]), *(instances - collection)].uniq
72
+ action == :assignment ? collection << objects : collection.destroy(objects)
73
+ objects
74
+ end
75
+ #
76
+ alias_method "_stored#{_plural}_exec", "_#{_reflect_of(content)}_exec"
77
+ end }
78
+ end
79
+
80
+ def definition_helpers
81
+ #
82
+ # Generate class methods for each Content of Definition
83
+ #
84
+ # Example for a subject model called User,
85
+ # which `has_many_temporary_roles` and `has_and_belongs_to_many :stored_roles`.
86
+ # You call the proc below by given contents [:role], then:
87
+ #
88
+ proc { |contents| contents.each do |content|
89
+ content_cls = i_am_i_can.send("#{content}_class")
90
+ _plural = '_' + content.to_s.pluralize
91
+
92
+ # _create_roles
93
+ # Define and store roles of Subject
94
+ define_singleton_method "_create#{_plural}" do |objects|
95
+ # Role.create([{ name: .. }]).reject { the roles that validation failed }
96
+ content_cls.constantize.create(objects)
97
+ .reject {|record| record.new_record? }
98
+ end
99
+ end }
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,71 @@
1
+ module IAmICan
2
+ module ResultOf
3
+ module Role
4
+ def roles definition, i_am_i_can, given: [ ]
5
+ ResultOf.(definition, [ [], given ], config: i_am_i_can,
6
+ msg_prefix: 'Role Definition: ',
7
+ fail_msg: 'have been used by other roles!'
8
+ )
9
+ end
10
+
11
+ def role assignment, i_am_i_can, given: [ ]
12
+ ResultOf.(assignment, given, config: i_am_i_can,
13
+ msg_prefix: 'Role Assignment: ',
14
+ fail_msg: 'have not been defined or have been repeatedly assigned!'
15
+ )
16
+ end
17
+
18
+ ResultOf.include self
19
+ end
20
+
21
+ module RoleGroup
22
+ def members assignment, i_am_i_can, given: [ ]
23
+ ResultOf.(assignment, given, config: i_am_i_can,
24
+ msg_prefix: 'Role Grouping: ',
25
+ fail_msg: 'have not been defined!'
26
+ )
27
+ end
28
+
29
+ ResultOf.include self
30
+ end
31
+
32
+ module Permission
33
+ def permissions definition, i_am_i_can, given: [ ]
34
+ ResultOf.(definition, [ [], given ], config: i_am_i_can,
35
+ msg_prefix: 'Permission Definition: ',
36
+ fail_msg: 'have been used by other permissions!'
37
+ )
38
+ end
39
+
40
+ def permission assignment, i_am_i_can, given: [ ]
41
+ ResultOf.(assignment, given, config: i_am_i_can,
42
+ msg_prefix: 'Permission Assignment: ',
43
+ fail_msg: 'have not been defined or have been repeatedly assigned!'
44
+ )
45
+ end
46
+
47
+ ResultOf.include self
48
+ end
49
+
50
+ def call(assignment, given, msg_prefix:, fail_msg:, config:)
51
+ instances, names = given
52
+ instances.map!(&:name).map!(&:to_sym)
53
+ assignment = assignment.map(&:name).map(&:to_sym) unless assignment.first.is_a?(Symbol)
54
+
55
+ to_be_assigned_names = (instances + names).uniq
56
+ failed_items = to_be_assigned_names - assignment
57
+
58
+ msg = msg_prefix + (assignment.blank? ? 'do nothing' : "#{assignment} DONE")
59
+ msg << "; And #{failed_items} #{fail_msg}" if failed_items.present?
60
+
61
+ if config.strict_mode && failed_items.present?
62
+ raise Error, msg
63
+ else
64
+ Rails.logger.info(msg) unless ENV['ITEST']
65
+ assignment
66
+ end
67
+ end
68
+
69
+ extend self
70
+ end
71
+ end
@@ -1,75 +1,27 @@
1
- require 'i_am_i_can/permission/helpers'
2
-
3
1
  module IAmICan
4
2
  module Permission
5
3
  module Assignment
6
- include Helpers::Ins
7
-
8
- # permission assignment for stored role
9
- def can *preds, obj: nil, strict_mode: false, auto_define_before: i_am_i_can.auto_define_before
10
- self.class.have_permissions *preds, obj: obj if auto_define_before
11
- not_defined_items, covered_items = [ ], [ ]
12
-
13
- preds.each do |pred|
14
- pms_name = pms_naming(pred, obj)
15
- covered_items << pms_name if pms_matched?(pms_name, in: stored_permission_names)
16
- not_defined_items << pms_name unless stored_permissions_add(pred: pred, **deconstruct_obj(obj))
17
- end
18
-
19
- _pms_assignment_result(preds, obj, not_defined_items, covered_items, strict_mode)
4
+ def can *actions,
5
+ resource: nil, obj: resource,
6
+ _d: i_am_i_can.auto_definition, auto_definition: _d
7
+ self.class.have_permissions *actions, obj: obj if auto_definition
8
+ _permissions_assignment(actions, obj)
20
9
  end
21
10
 
22
11
  alias has_permission can
23
12
 
24
- def temporarily_can *preds, obj: nil, strict_mode: false, auto_define_before: i_am_i_can.auto_define_before
25
- raise Error, "Permission Assignment: local role `#{name}` was not defined" unless i_am_i_can.subject_model.defined_local_roles.key?(self.name.to_sym)
26
- self.class.have_permissions *preds, obj: obj, save: false if auto_define_before
27
- not_defined_items, covered_items = [ ], [ ]
28
-
29
- preds.each do |pred|
30
- pms_name = pms_naming(pred, obj)
31
- next not_defined_items << pms_name unless pms_name.in?(defined_permissions.keys)
32
- covered_items << pms_name if pms_matched?(pms_name, in: pms_of_defined_local_role(self.name))
33
- pms_of_defined_local_role(self.name) << pms_name
34
- end
35
-
36
- _pms_assignment_result(preds, obj, not_defined_items, covered_items, strict_mode)
37
- end
38
-
39
- alias locally_can temporarily_can
40
-
41
- def cannot *preds, obj: nil, saved: true
42
- not_defined_items = [ ]
43
-
44
- preds.each do |pred|
45
- pms_name = pms_naming(pred, obj)
46
- if saved
47
- next if stored_permissions_rmv(pred: pred, **deconstruct_obj(obj))
48
- not_defined_items << pms_name
49
- else
50
- next not_defined_items << pms_name unless pms_name.in?(defined_permissions.keys)
51
- pms_of_defined_local_role(self.name).delete(pms_name)
52
- end
53
- end
54
-
55
- _pms_assignment_result(preds, obj, not_defined_items)
13
+ def cannot *actions, obj: nil
14
+ _permissions_assignment(:cancel, actions, obj)
56
15
  end
57
16
 
58
17
  alias is_not_allowed_to cannot
59
18
 
60
- # `can? :manage, User` / `can? :manage, obj: User`
61
- def can? pred, obj0 = nil, obj: nil
62
- obj = obj0 || obj
63
- pms_name = pms_naming(pred, obj)
64
- temporarily_can?(pred, obj) || pms_matched?(pms_name, in: stored_permission_names)
19
+ def _permissions_assignment(action = :assignment, actions, obj)
20
+ permissions = actions.product(Array[obj]).map { |(p, o)| { action: p, **deconstruct_obj(o) } }
21
+ assignment = _stored_permissions_exec(action,
22
+ permissions.reduce({ }) { |a, b| a.merge(b) { |_, x, y| [x, y] } })
23
+ ResultOf.permission assignment, i_am_i_can, given: [[], permissions.map { |pms| pms.values.compact.join('_').to_sym }]
65
24
  end
66
-
67
- def temporarily_can? pred, obj
68
- pms_name = pms_naming(pred, obj)
69
- pms_matched?(pms_name, in: pms_of_defined_local_role(self.name))
70
- end
71
-
72
- alias locally_can? temporarily_can?
73
25
  end
74
26
  end
75
27
  end
@@ -1,40 +1,20 @@
1
- require 'i_am_i_can/permission/helpers'
2
- require 'i_am_i_can/permission/p_array'
3
-
4
1
  module IAmICan
5
2
  module Permission
6
3
  module Definition
7
- include Helpers::Cls
8
-
9
- def have_permission *preds, obj: nil, desc: nil, save: i_am_i_can.default_save
10
- failed_items = [ ]
11
-
12
- preds.each do |pred|
13
- pms_name = pms_naming(pred, obj)
14
- description = desc || pms_name.to_s.tr('_', ' ')
15
- if save
16
- failed_items << pms_name unless _to_store_permission(pred, obj, desc: description)
17
- else
18
- failed_items << pms_name if pms_name.in?(defined_local_permissions.keys)
19
- defined_local_permissions[pms_name] ||= { desc: description }
20
- end
21
- end
22
-
23
- _pms_definition_result(preds, obj, failed_items)
4
+ def have_permission *actions, obj: nil
5
+ permissions = actions.product(Array[obj]).map { |(p, o)| { action: p, **deconstruct_obj(o) } }
6
+ definition = _create_permissions(permissions)
7
+ ResultOf.roles definition, i_am_i_can, given: permissions.map { |pms| pms.values.compact.join('_').to_sym }
24
8
  end
25
9
 
26
- alias have_permissions have_permission
27
- alias has_permission have_permission
28
- alias has_permissions have_permission
10
+ %i[ have_permissions has_permission has_permissions ].each { |aname| alias_method aname, :have_permission }
29
11
 
30
- def declare_permission *preds, **options
31
- have_permission *preds, **options, save: false
12
+ def deconstruct_obj(obj)
13
+ i_am_i_can.permission_model.deconstruct_obj(obj)
32
14
  end
33
15
 
34
- alias declare_permissions declare_permission
35
-
36
16
  def self.extended(kls)
37
- kls.delegate :defined_permissions, :pms_naming, :deconstruct_obj, :pms_of_defined_local_role, to: kls
17
+ kls.delegate :deconstruct_obj, to: kls
38
18
  end
39
19
  end
40
20
  end
@@ -1,4 +1,3 @@
1
- require 'i_am_i_can/permission/p_array'
2
1
  require 'i_am_i_can/permission/definition'
3
2
  require 'i_am_i_can/permission/assignment'
4
3
 
@@ -7,19 +6,23 @@ module IAmICan
7
6
  extend ActiveSupport::Concern
8
7
 
9
8
  class_methods do
10
- def matched?(pms_name = nil, pred: nil, obj: nil, **options)
11
- PArray.new(options[:in]).matched?(pms_name || naming(pred, obj))
9
+ def matched(actions, obj)
10
+ _ = deconstruct_obj(obj)
11
+ where(action: actions,
12
+ obj_type: [nil, _[:obj_type]],
13
+ obj_id: [nil, _[:obj_id]])
12
14
  end
13
15
 
14
- def which(pred:, obj: nil, **conditions)
15
- find_by!(pred: pred, **deconstruct_obj(obj), **conditions)
16
+ def matched?(actions, obj)
17
+ matched(actions, obj).present?
16
18
  end
17
19
 
18
- def naming(pred, obj)
19
- obj_type, obj_id = deconstruct_obj(obj).values
20
- otp = "_#{obj_type}" if obj_type.present?
21
- oid = "_#{obj_id}" if obj_id.present?
22
- [pred, otp, oid].join.to_sym
20
+ def matched_all?(actions, obj)
21
+ matched(actions, obj).count == Array(actions).count
22
+ end
23
+
24
+ def which(action:, obj: nil, **conditions)
25
+ find_by!(action: action, **deconstruct_obj(obj), **conditions)
23
26
  end
24
27
 
25
28
  def deconstruct_obj(obj)
@@ -34,32 +37,23 @@ module IAmICan
34
37
  end
35
38
  end
36
39
 
37
- def exists?(pred, obj)
38
- super(pred: pred, **deconstruct_obj(obj))
40
+ def names
41
+ all.map(&:name)
39
42
  end
40
43
  end
41
44
 
42
45
  included do
43
46
  # like: manage_User_1
44
47
  def name
45
- otp = "_#{obj_type}" if obj_type.present?
46
- oid = "_#{obj_id}" if obj_id.present?
47
- [pred, otp, oid].join.to_sym
48
+ [action, obj_type, obj_id].compact.join('_').to_sym
48
49
  end
49
50
 
50
51
  # def assign_to role: nil, group: nil
51
- # obj = if role
52
- # role.is_a?(Symbol) ? i_am_i_can.role_model.find(name: role) : role
53
- # else
54
- # group.is_a?(Symbol) ? i_am_i_can.role_group_model.find(name: role) : group
55
- # end
56
- # obj.have_permission self.pred, obj: self.obj
57
52
  # end
58
- #
59
- # alias is_assigned_to assign_to
60
53
 
61
- # :user, User, user
54
+ # returns :user, User, user
62
55
  def obj
56
+ return if obj_type.blank?
63
57
  return obj_type.constantize.find(obj_id) if obj_id.present?
64
58
  obj_type[/[A-Z]/] ? obj_type.constantize : obj_type.to_sym
65
59
  end
@@ -2,28 +2,33 @@ module IAmICan
2
2
  module Resource
3
3
  extend ActiveSupport::Concern
4
4
 
5
- class_methods do
6
- # Book.that_allow(User.all).to(:read)
7
- # Book.that_allow(User.last).to(:write)
8
- def that_allow(subject)
9
- ThatAllow.new(self, subject)
5
+ included do
6
+ # Book.that_allow(User.all, to: :read)
7
+ # Book.that_allow(User.last, to: :write)
8
+ scope :that_allow, -> (subject, to:) do
9
+ tmp_role_ids = Array(subject).flat_map(&:temporary_roles).map(&:id).uniq
10
+ allowed_ids = subject.i_am_i_can.role_model.where(id: (subject._roles.ids + tmp_role_ids).uniq)
11
+ ._permissions.where(action: to, obj_type: self.name).pluck(:obj_id).uniq
12
+ where(id: allowed_ids)
10
13
  end
11
14
  end
12
- end
13
15
 
14
- class ThatAllow
15
- attr_accessor :records, :subject
16
-
17
- def initialize(records, subject)
18
- self.records = records
19
- self.subject = subject
20
- end
21
-
22
- def to(pred)
23
- roles = Configs.take.subject_model._roles
24
- permissions = Configs.take.role_model._permissions
25
- allowed_ids = subject.send(roles).send(permissions).where(pred: pred, obj_type: records.name).pluck(:obj_id).uniq
26
- records.where(id: allowed_ids)
16
+ class_methods do
17
+ # def that_allow(subject)
18
+ # ThatAllow.new(self, subject)
19
+ # end
27
20
  end
28
21
  end
22
+
23
+ # class ThatAllow
24
+ # attr_accessor :records, :subject
25
+ #
26
+ # def initialize(records, subject)
27
+ # self.records = records
28
+ # self.subject = subject
29
+ # end
30
+ #
31
+ # def to(action)
32
+ # end
33
+ # end
29
34
  end
@@ -1,62 +1,41 @@
1
- require 'i_am_i_can/role/helpers'
2
-
3
1
  module IAmICan
4
2
  module Role
5
3
  module Assignment
6
- include Helpers::Ins
7
-
8
- def becomes_a *roles, which_can: [ ], obj: nil, auto_define_before: i_am_i_can.auto_define_before, save: i_am_i_can.default_save
9
- should_define_role = which_can.present? || auto_define_before
10
- self.class.have_roles *roles, which_can: which_can, obj: obj, save: save if should_define_role
11
- failed_items = [ ]
12
-
13
- roles.map(&__role).each do |role|
14
- if save
15
- failed_items << role unless stored_roles_add(role)
16
- else
17
- next failed_items << role unless role.in?(defined_roles.keys)
18
- local_role_names << role unless role.in?(local_role_names)
19
- end
20
- end
21
-
22
- _role_assignment_result(roles, failed_items)
4
+ def becomes_a *roles, which_can: [ ], obj: nil,
5
+ _d: i_am_i_can.auto_definition,
6
+ auto_definition: _d || which_can.present?,
7
+ save: true
8
+ self.class.have_roles *roles, which_can: which_can, obj: obj if auto_definition
9
+ _roles_assignment(roles, save)
23
10
  end
24
11
 
25
- alias is becomes_a
26
- alias is_a_role becomes_a
27
- alias is_roles becomes_a
28
- alias has_role becomes_a
29
- alias has_roles becomes_a
30
- alias role_is becomes_a
31
- alias roles_are becomes_a
12
+ %i[ is is_a is_a_role is_roles has_role has_roles role_is role_are ].each { |aname| alias_method aname, :becomes_a }
32
13
 
33
- def temporarily_is *roles, **options
14
+ def is_a_temporary *roles, **options
34
15
  becomes_a *roles, save: false, **options
35
16
  end
36
17
 
37
- alias locally_is temporarily_is
18
+ def falls_from *roles, saved: true
19
+ _roles_assignment(:cancel, roles, saved)
20
+ end
21
+
22
+ %i[ is_not_a will_not_be removes_role leaves has_not_role has_not_roles ].each { |aname| alias_method aname, :falls_from }
38
23
 
39
- def falls_from *roles, saved: i_am_i_can.default_save
40
- failed_items = [ ]
24
+ def is_not_a_temporary *roles
25
+ falls_from *roles, saved: false
26
+ end
41
27
 
42
- roles.each do |role|
43
- if saved
44
- failed_items << role unless stored_roles_rmv(role)
45
- else
46
- next failed_items << role unless role.in?(defined_roles.keys)
47
- local_role_names.delete(role)
48
- end
28
+ def _roles_assignment(action = :assignment, roles, save)
29
+ instances, names = Role.extract(roles, i_am_i_can)
30
+ if save
31
+ assignment = _stored_roles_exec(action, instances, name: names)
32
+ else
33
+ to_be_assigned_names = (instances.map(&:name).map(&:to_sym) + names).uniq
34
+ assignment = _temporary_roles_exec(action, to_be_assigned_names)
49
35
  end
50
36
 
51
- _role_assignment_result(roles, failed_items)
37
+ ResultOf.role assignment, i_am_i_can, given: [instances, names]
52
38
  end
53
-
54
- alias is_not_a falls_from
55
- alias will_not_be falls_from
56
- alias removes_role falls_from
57
- alias leaves falls_from
58
- alias has_not_role falls_from
59
- alias has_not_roles falls_from
60
39
  end
61
40
  end
62
41
  end