Module: OpenStax::Api::Roar

Included in:
V1::ApiController
Defined in:
lib/openstax/api/roar.rb

Instance Method Summary collapse

Instance Method Details

#get_representer(represent_with, model = nil) ⇒ Object



11
12
13
14
15
16
17
18
# File 'lib/openstax/api/roar.rb', line 11

def get_representer(represent_with, model=nil)
  return nil if represent_with.nil?
  if represent_with.is_a? Proc
    represent_with.call(model)
  else
    represent_with
  end
end

#standard_create(model_klass, represent_with = nil, &block) ⇒ Object



38
39
40
# File 'lib/openstax/api/roar.rb', line 38

def standard_create(model_klass, represent_with=nil, &block)
  standard_nested_create(model_klass, nil, nil, represent_with, &block)
end

#standard_destroy(model_klass, id) ⇒ Object



69
70
71
72
73
74
75
76
77
78
# File 'lib/openstax/api/roar.rb', line 69

def standard_destroy(model_klass, id)
  @model = model_klass.find(id)
  OSU::AccessPolicy.require_action_allowed!(:destroy, current_api_user, @model)
  
  if @model.destroy
    head :no_content
  else
    render json: @model.errors, status: :unprocessable_entity
  end
end

#standard_nested_create(model_klass, container_association = nil, container_id = nil, represent_with = nil) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/openstax/api/roar.rb', line 42

def standard_nested_create(model_klass, container_association=nil, container_id=nil, represent_with=nil)
  @model = model_klass.new()

  if container_association && container_id
    foreign_key = model_klass.reflect_on_association(container_association).association_foreign_key
    @model.send(foreign_key + '=', container_id)
  end

  # Unlike the implications of the representable README, "consume!" can
  # actually make changes to the database.  See http://goo.gl/WVLBqA. 
  # We do want to consume before checking the permissions so we can know
  # what we're dealing with, but if user doesn't have permission we don't
  # want to have changed the DB.  Wrap in a transaction to protect ourselves.

  model_klass.transaction do
    consume!(@model, represent_with: get_representer(represent_with, @model))
    yield @model if block_given?
    OSU::AccessPolicy.require_action_allowed!(:create, current_api_user, @model)
  end

  if @model.save
    respond_with @model, represent_with: get_representer(represent_with, @model), status: :created
  else
    render json: @model.errors, status: :unprocessable_entity
  end
end

#standard_read(model_klass, id, represent_with = nil) ⇒ Object



20
21
22
23
24
# File 'lib/openstax/api/roar.rb', line 20

def standard_read(model_klass, id, represent_with=nil)
  @model = model_klass.find(id)
  OSU::AccessPolicy.require_action_allowed!(:read, current_api_user, @model)
  respond_with @model, represent_with: get_representer(represent_with, @model)
end

#standard_sort(model_klass) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/openstax/api/roar.rb', line 80

def standard_sort(model_klass)
  # Take array of all IDs or hash of id => position,
  # Regardless, build up an array of all IDs in the right order and pass those to sort

  new_positions = params['newPositions']
  return head :no_content if new_positions.length == 0

  # Can't have duplicate positions or IDs
  unique_ids =       new_positions.collect{|np| np['id']}.uniq
  unique_positions = new_positions.collect{|np| np['position']}.uniq

  return head :bad_request if unique_ids.length != new_positions.length
  return head :bad_request if unique_positions.length != new_positions.length

  first = model_klass.where(:id => new_positions[0]['id']).first

  return head :not_found if first.blank?

  originalOrdered = first.me_and_peers.ordered.all

  originalOrdered.each do |item|
    raise SecurityTransgression unless item.send(:container_column) == originalOrdered[0].send(:container_column) \
      if item.respond_to?(:container_column)
    OSU::AccessPolicy.require_action_allowed!(:sort, current_api_user, item)
  end

  originalOrderedIds = originalOrdered.collect{|sc| sc.id}

  newOrderedIds = Array.new(originalOrderedIds.size)

  new_positions.each do |newPosition|
    id = newPosition['id'].to_i
    newOrderedIds[newPosition['position']] = id
    originalOrderedIds.delete(id)
  end

  ptr = 0
  for oldId in originalOrderedIds 
    while !newOrderedIds[ptr].nil?; ptr += 1; end
    newOrderedIds[ptr] = oldId
  end

  begin 
    model_klass.sort!(newOrderedIds)
  rescue Exception => e
    return head :internal_server_error
  end

  head :no_content
end

#standard_update(model_klass, id, represent_with = nil) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/openstax/api/roar.rb', line 26

def standard_update(model_klass, id, represent_with=nil)
  @model = model_klass.find(id)
  OSU::AccessPolicy.require_action_allowed!(:update, current_api_user, @model)
  consume!(@model, represent_with: get_representer(represent_with, @model))
  
  if @model.save
    head :no_content
  else
    render json: @model.errors, status: :unprocessable_entity
  end
end