Class: Role::AbilityGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/models/role.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(role, model_name, user, through, parent_name, intermediary = nil) ⇒ AbilityGenerator

Returns a new instance of AbilityGenerator.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/models/role.rb', line 134

def initialize(role, model_name, user, through, parent_name, intermediary = nil)
  begin
    @model = model_name.constantize
  rescue NameError
    raise "#{model_name} model is used in `config/models/roles.yml` for the #{role.key} role but is not defined in `app/models`."
  end

  @role = role
  @ability_data = role.models[model_name]
  @through = through
  @parent = user.send(through).reflect_on_association(parent_name)&.klass
  @parent_ids = user.parent_ids_for(@role, @through, parent_name) if @parent
  @intermediary = intermediary
  @intermediary_class = @model.reflect_on_association(intermediary)&.class_name&.constantize if @intermediary.present?
end

Instance Attribute Details

#modelObject (readonly)

Returns the value of attribute model.



132
133
134
# File 'lib/models/role.rb', line 132

def model
  @model
end

Instance Method Details

#actionsObject



154
155
156
157
158
159
160
161
162
# File 'lib/models/role.rb', line 154

def actions
  return @actions if @actions
  @actions = (@ability_data["actions"] if @ability_data.is_a?(Hash)) || @ability_data
  # crud is a special value that we substitute for the 4 crud actions
  # This is instead of :manage which covers all 4 actions _and_ any extra actions the controller may respond to
  @actions = crud_actions if @actions.to_s.downcase == "crud"
  @actions = [actions] unless actions.is_a?(Array)
  @actions.map!(&:to_sym)
end

#conditionObject



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/models/role.rb', line 179

def condition
  return @condition if @condition
  return nil unless @parent_ids
  if @model == @parent
    return @condition = {id: @parent_ids}
  end
  parent_association = possible_parent_associations.find { |association| @model.reflect_on_association(association) || @intermediary_class&.reflect_on_association(association) }
  return nil unless parent_association.present?
  # If possible, use the team_id attribute because it saves us having to join all the way back to the source parent model
  # In some scenarios this may be quicker, or if the parent model is in a different database shard, it may not even
  # be possible to do the join
  parent_with_id = "#{parent_association}_id"
  @condition = if @model.column_names.include?(parent_with_id)
    {parent_with_id.to_sym => @parent_ids}
  elsif @intermediary.present? && @model.reflect_on_association(@intermediary)
    {@intermediary.to_sym => {parent_with_id.to_sym => @parent_ids}}
  else
    {parent_association => {id: @parent_ids}}
  end
end

#crud_actionsObject



164
165
166
# File 'lib/models/role.rb', line 164

def crud_actions
  [:create, :read, :update, :destroy]
end

#possible_parent_associationsObject



168
169
170
171
172
173
174
175
176
177
# File 'lib/models/role.rb', line 168

def possible_parent_associations
  ary = @parent.to_s.split("::").map(&:underscore)
  possibilities = []
  current = nil
  until ary.empty?
    current = "#{ary.pop}#{"_" unless current.nil?}#{current}"
    possibilities << current
  end
  possibilities.map(&:to_sym)
end

#valid?Boolean

Returns:

  • (Boolean)


150
151
152
# File 'lib/models/role.rb', line 150

def valid?
  actions.present? && model.present? && condition.present?
end