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



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

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



36
37
38
# File 'lib/openstax/api/roar.rb', line 36

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

Raises:

  • (SecurityTransgression)


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

def standard_destroy(model_klass, id)
  @model = model_klass.find(id)
  raise SecurityTransgression unless current_user.can_destroy?(@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



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

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?
    raise SecurityTransgression unless current_user.can_create?(@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

Raises:

  • (SecurityTransgression)


18
19
20
21
22
# File 'lib/openstax/api/roar.rb', line 18

def standard_read(model_klass, id, represent_with=nil)
  @model = model_klass.find(id)
  raise SecurityTransgression unless current_user.can_read?(@model)
  respond_with @model, represent_with: get_representer(represent_with, @model)
end

#standard_sort(model_klass) ⇒ Object



78
79
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
# File 'lib/openstax/api/roar.rb', line 78

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)
    raise SecurityTransgression unless current_user.can_sort?(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

Raises:

  • (SecurityTransgression)


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

def standard_update(model_klass, id, represent_with=nil)
  @model = model_klass.find(id)
  raise SecurityTransgression unless current_user.can_update?(@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