Module: DescribedRoutes::DescribedRoutesHelper

Included in:
RailsController
Defined in:
lib/described_routes/helpers/described_routes_helper.rb

Constant Summary collapse

REGISTERED_RELS =

Map rels to standard relation types, used by #make_link_header

{
  'edit' => 'edit',
  'up'   => 'up'
}
{
  :self => false, :describedby => true, :up => false, :related => false
}
{
  :self => false, :describedby => true, :up => false, :related => false
}

Instance Method Summary collapse

Instance Method Details

Render links as <link <url> rel=<rel> … type=<type>> elements. Add to the <head> part of your layout with:

<%= link_elements %>


49
50
51
# File 'lib/described_routes/helpers/described_routes_helper.rb', line 49

def link_elements(separator="\n", options=LINK_ELEMENT_OPTIONS)
  make_link_header(options).to_html(separator)
end

Returns a LinkHeader object that represents the required links.

Link relation types (“rel” attributes) will contain a standard type (‘self’, ‘up’, ‘describedby’) &/or an extension type in the form “described_route_url(name)#rel”, using the name and rel of the resource template.

The output is filtered by the options hash, with members :self, :describedby, :up, :related.



66
67
68
69
70
71
72
73
74
75
76
77
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
128
129
# File 'lib/described_routes/helpers/described_routes_helper.rb', line 66

def make_link_header(options)
  links = []
  rt = resource_template
  if rt
    type_prefix = described_routes_url + '#'
    #
    # For the application's root, the link with rel="describedby" has meta="ResourceTemplates" and it refers to a list of all
    # top level resource templates. Otherwise, rel="describedby" has meta="ResourceTemplate" and it refers to a single resource
    # template (together with any descendants).
    #
    if rt.name == 'root'
      described_by = described_routes_url
      related = resource_templates
      meta = "ResourceTemplates"
    else
      described_by = described_route_url(rt.name)
      related = rt.resource_templates
      meta = "ResourceTemplate"
    end
    
    #
    # Add any query parameters to the rel="describedby" link
    #
    if resource_parameters.empty?
      described_by_with_params = described_by
    else
      described_by_with_params = described_by + '?' + resource_parameters.to_query
    end
    
    # data for rel="self"
    links << LinkHeader::Link.new(request.url, [['rel', 'self'], ['role', type_prefix + rt.name]]) if options[:self]

    # data for rel="described_by"
    links << LinkHeader::Link.new(described_by_with_params, [['rel', 'describedby'], ['meta', meta]]) if options[:describedby]

    # data for rel="up"
    # TODO move this to ResourceTemplate
    if options[:up]
      if rt.parent
        links << LinkHeader::Link.new(rt.parent.uri_for(resource_parameters), [['rel', 'up'], ['role', type_prefix + rt.parent.name]])
      elsif rt.name != 'root'
        links << LinkHeader::Link.new(root_url, [['rel', 'up'], ['role', type_prefix + 'root']])
      end
    end

    # data for rel="related"
    if options[:related]
      related.expand_links(resource_parameters).each do |l|
        if l.name != rt.name
          rel = l.rel || l.name
          rels = [['rel', described_by + '#' + rel]]
          if l.rel
            registered_rel = REGISTERED_RELS[rel]
            if registered_rel
              rels.unshift(['rel', registered_rel])
            end
          end
          links << LinkHeader::Link.new(l.uri, rels + [['role', type_prefix + l.name]])
        end
      end
    end
  end
  LinkHeader.new(links)
end

#resource_parametersObject

combined path and query parameters (not POST parameters), with the id param renamed to foo_id (say)



36
37
38
39
40
41
42
43
44
45
# File 'lib/described_routes/helpers/described_routes_helper.rb', line 36

def resource_parameters
  @resource_parameters ||= begin
    p = request.path_parameters.merge(request.query_parameters)
    r = resource_templates.routing[[controller_name, action_name]]
    if r && r[1] && p[:id]
      p[r[1]] = p.delete(:id)
    end
    p.except("action", "controller")
  end
end

#resource_templateObject

get the resource template for the current request



30
31
32
33
# File 'lib/described_routes/helpers/described_routes_helper.rb', line 30

def resource_template
  r = resource_templates.routing[[controller_name, action_name]]
  r[0] if r
end

#resource_templatesObject

get the resource template structure, initialised (once) from Rails routes



22
23
24
25
26
27
# File 'lib/described_routes/helpers/described_routes_helper.rb', line 22

def resource_templates
  @@resource_templates ||= begin
    base_url = root_url rescue nil
    RailsRoutes.get_resource_templates(base_url)
  end
end

Sets a link header in the response

after_filter :set_link_header


55
56
57
# File 'lib/described_routes/helpers/described_routes_helper.rb', line 55

def set_link_header(options=LINK_HEADER_OPTIONS)
  response.headers["Link"] = make_link_header(options).to_s
end