friendly_routes 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 20f66faa1c0ee03ba5ee4d409c3533c233fce5a6
4
- data.tar.gz: 86d56ad4c80db6eaefc1b72ebaabc543ac61f74e
3
+ metadata.gz: e2d3509ebae256e805600bb631718d9489eeaf73
4
+ data.tar.gz: dd5d986628e21c2d693f579e1ab621bb3a259161
5
5
  SHA512:
6
- metadata.gz: 587782afc11016d44dd17f9ed2b54e19e1f0c84ec99053ef6314473f1464460a5cfdba97f2c5839581f9815e4a0e26fcbe044e4e3e9ce010988289fba9497918
7
- data.tar.gz: 45e249b6bd390058e8d3be82fe1b716c428ed064709554af10055b99a18819ee930841ee3d2d349e95d09a6c11f6b65635019b4d615f15e450bf93b03b554eb4
6
+ metadata.gz: e9aed8430ef5abc1f2e6fffcd3956022c0ab30904d7690a9c027c6c2c5f4edec643c97ed58a8ec60da8fc098b67406ab0d0c71295e8590f93808d80e44c1de2f
7
+ data.tar.gz: 14e92badb00980a1bb3efb5a134e713146920dc8c3c6aa71baa7c28623c65f9fa05c1c54f4d2cf12e5ed1d98babeb4dc364408d2c9149ac19116e106895a9d32
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Friendly Routes
2
2
  Friendly Routes creates DSL for creating rails routes with human friendly URLs
3
3
 
4
+ [![Gem Version](https://badge.fury.io/rb/friendly_routes.svg)](https://badge.fury.io/rb/friendly_routes)
4
5
  [![Code Climate](https://codeclimate.com/github/RoM4iK/friendly_routes/badges/gpa.svg)](https://codeclimate.com/github/RoM4iK/friendly_routes)
5
6
  [![Build Status](https://travis-ci.org/RoM4iK/friendly_routes.svg?branch=master)](https://travis-ci.org/RoM4iK/friendly_routes)
6
7
  ## Usage
@@ -22,7 +23,8 @@ Or install it yourself as:
22
23
  ```bash
23
24
  $ gem install friendly_routes
24
25
  ```
25
- ## Usage example
26
+ ## Examples
27
+ ### Routes.rb example
26
28
 
27
29
  ```ruby
28
30
  # config/routes.rb
@@ -37,57 +39,31 @@ second_dummies_route = FriendlyRoutes::Route.new([free, 'categories', category],
37
39
 
38
40
  friendly_url_for dummies_route, :get, '/' # '/:free/categories/:category'
39
41
  friendly_url_for dummies_route, :get, '/hello/' # '/hello/:free/categories/:category'
42
+ ```
43
+
44
+ ### Controller example
40
45
 
46
+ ```ruby
41
47
  # app/controllers/dummies_controller.rb
42
48
  class DummiesController < ApplicationController
43
49
  before_action :parse_friendly_routes, only: [:index]
44
50
  def index
45
51
  end
46
52
  end
47
-
48
- # Categories:
49
- # <Category id: 1, title: "lorem">
50
- # <Category id: 2, title: "ipsum">
51
-
52
-
53
- # GET "/free/lorem" - { free: true, category_id: 1}
54
- # GET "/free/ipsum" - { free: true, category_id: 2}
55
- # GET "/paid/lorem" - { free: false, category_id: 1}
56
- # GET "/paid/ipsum" - { free: false, category_id: 2}
57
- ```
58
-
59
- ## Configuration
60
- ### Routes
61
-
62
- 1. Create new route, pass **method**, **path**, **controller name**, and **action** to it.
63
- ```ruby
64
- dummies_route = FriendlyRoutes::Route.new('/', controller: :dummies, action: :index)
65
53
  ```
66
- 2. Create route params. *Note: params in route will be accepted in creation order*
67
54
 
68
- Boolean param, pass **name**, and hash with **true** and **false** keys.
69
- ```ruby
70
- FriendlyRoutes::Params::BooleanParams.new(:discount, true: :true_condition, false: :false_condition)
71
- ```
55
+ ### Request result example
72
56
 
73
- collection param, pass **name**, **collection**, and **attribute** keys.
74
- ```ruby
75
- FriendlyRoutes::Params::CollectionParams.new(:categories, Category.where(active: true), :title)
76
57
  ```
58
+ Categories:
59
+ <Category id: 1, title: "lorem">
60
+ <Category id: 2, title: "ipsum">
77
61
 
78
- hash param, pass **name**, **collection**, and **attribute** keys.
79
- ```ruby
80
- FriendlyRoutes::Params::HashParams.new(:rooms, 'one-roomed' => 1, 'two-roomed' => 2)
81
- ```
82
- 4. Initialize route wih `friendly_url_for`
83
- ```ruby
84
- friendly_url_for dummies_route, :get
85
- ```
86
62
 
87
- ### Controllers
88
- Simply call `parse_friendly_routes` before controller action to parse params.
89
- ```ruby
90
- before_action :parse_friendly_routes, only: [:index]
63
+ GET "/free/lorem" - { free: true, category_id: 1}
64
+ GET "/free/ipsum" - { free: true, category_id: 2}
65
+ GET "/paid/lorem" - { free: false, category_id: 1}
66
+ GET "/paid/ipsum" - { free: false, category_id: 2}
91
67
  ```
92
68
 
93
69
  ## Contributing
@@ -7,7 +7,9 @@ require 'friendly_routes/params/base'
7
7
  require 'friendly_routes/params/boolean_params'
8
8
  require 'friendly_routes/params/collection_params'
9
9
  require 'friendly_routes/params/hash_params'
10
+ require 'friendly_routes/services/composer'
10
11
  require 'friendly_routes/services/constraints'
12
+ require 'friendly_routes/services/multi_composer'
11
13
  require 'friendly_routes/services/parser'
12
14
  require 'friendly_routes/services/prefixed_param'
13
15
  require 'friendly_routes/services/prefixed_params'
@@ -2,6 +2,11 @@
2
2
 
3
3
  module FriendlyRoutes
4
4
  module Params
5
+ # Abstract base class for route params.
6
+ #
7
+ # @abstract
8
+ # @attr [Symbol] type
9
+ # @attr [Symbol, String] name
5
10
  class Base
6
11
  attr_accessor :type, :name
7
12
 
@@ -11,13 +16,39 @@ module FriendlyRoutes
11
16
  @optional = optional
12
17
  end
13
18
 
19
+ # returns true if param is optional
14
20
  def optional?
15
21
  @optional == true
16
22
  end
17
23
 
24
+ # returns true if param required
25
+ def required?
26
+ @optional == false
27
+ end
28
+
29
+ # Regexp with allowed params
18
30
  def constraints
19
31
  raise NotImplementedError
20
32
  end
33
+
34
+ # Parse values from request
35
+ #
36
+ # Inverse of {compose}
37
+ def parse
38
+ raise NotImplementedError
39
+ end
40
+
41
+ # Generate request value from params
42
+ #
43
+ # Inverse of {parse}
44
+ def compose
45
+ raise NotImplementedError
46
+ end
47
+
48
+ # Check if value can be composed
49
+ def allowed?
50
+ raise NotImplementedError
51
+ end
21
52
  end
22
53
  end
23
54
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module FriendlyRoutes
4
4
  module Params
5
+ # @attr [String] true value for matching true
6
+ # @attr [String] false value for matching false
5
7
  class BooleanParams < Base
6
8
  attr_accessor :true, :false
7
9
 
@@ -16,10 +18,27 @@ module FriendlyRoutes
16
18
  Regexp.new "#{@true}|#{@false}"
17
19
  end
18
20
 
21
+ # (see Base#parse)
22
+ # @param [String] value request value
23
+ # @return [Boolean]
19
24
  def parse(value)
20
25
  value == @true
21
26
  end
22
27
 
28
+ # (see Base#compose)
29
+ # @param [Boolean] value
30
+ # @return [String] request value
31
+ def compose(value)
32
+ value ? @true : @false
33
+ end
34
+
35
+ # (see Base#allowed?)
36
+ # @param [Boolean] value
37
+ # @return [Boolean]
38
+ def allowed?(value)
39
+ [true, false].include? value
40
+ end
41
+
23
42
  private
24
43
 
25
44
  def check_params(options)
@@ -2,6 +2,10 @@
2
2
 
3
3
  module FriendlyRoutes
4
4
  module Params
5
+ # Created to work with ActiveRecord collection
6
+ #
7
+ # @attr [Object] collection Instance of ActiveRecord collection
8
+ # @attr [Symbol, String] key_attr name of attribute for matching
5
9
  class CollectionParams < Base
6
10
  attr_accessor :collection, :key_attr
7
11
 
@@ -16,10 +20,27 @@ module FriendlyRoutes
16
20
  Regexp.new @collection.all.map(&@key_attr).compact.map(&:downcase).join('|')
17
21
  end
18
22
 
23
+ # (see Base#parse)
24
+ # @param [String] value value of item key attr
25
+ # @return [Integer, nil] item id or nil if item not found
19
26
  def parse(value)
20
27
  @collection.find_by(@key_attr => value).try(:id)
21
28
  end
22
29
 
30
+ # (see Base#compose)
31
+ # @param [Integer] id id of collection member
32
+ # @return [String] member key attr
33
+ def compose(id)
34
+ @collection.find(id)[@key_attr]
35
+ end
36
+
37
+ # (see Base#allowed?)
38
+ # @param [Integer] id id of collection member
39
+ # @return [Boolean]
40
+ def allowed?(id)
41
+ @collection.exists?(id)
42
+ end
43
+
23
44
  private
24
45
 
25
46
  def check_params
@@ -2,6 +2,7 @@
2
2
 
3
3
  module FriendlyRoutes
4
4
  module Params
5
+ # @attr [Hash] hash *keys* are values for matching and *values* is needed values
5
6
  class HashParams < Base
6
7
  attr_accessor :hash
7
8
 
@@ -15,10 +16,27 @@ module FriendlyRoutes
15
16
  Regexp.new @hash.keys.join('|')
16
17
  end
17
18
 
19
+ # (see Base#parse)
20
+ # @param [String, Symbol] value hash key
21
+ # @return [Object] hash value
18
22
  def parse(value)
19
23
  @hash[value]
20
24
  end
21
25
 
26
+ # (see Base#compose)
27
+ # @param [Object] value hash value
28
+ # @return [String, Symbol] hash key
29
+ def compose(value)
30
+ @hash.key(value)
31
+ end
32
+
33
+ # (see Base#allowed?)
34
+ # @param [Integer] value hash value
35
+ # @return [Boolean]
36
+ def allowed?(value)
37
+ @hash.values.include?(value)
38
+ end
39
+
22
40
  private
23
41
 
24
42
  def check_params
@@ -21,6 +21,10 @@ module FriendlyRoutes
21
21
  @params.select { |param| param.is_a?(FriendlyRoutes::Params::Base) }
22
22
  end
23
23
 
24
+ def required_params
25
+ dynamic_params.select(&:required?)
26
+ end
27
+
24
28
  def inspect
25
29
  dynamic_params.map(&:name).join(', ')
26
30
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FriendlyRoutes
4
+ # Compoer will map passed params to friendly_route params
5
+ class Composer
6
+ def initialize(route, params = {})
7
+ @route = route
8
+ @params = params.dup
9
+ end
10
+
11
+ def call
12
+ return unless @route
13
+ @route.dynamic_params.each do |param|
14
+ compose(param)
15
+ end
16
+ @params
17
+ end
18
+
19
+ def can_be_composed?
20
+ return unless @route
21
+ @route.required_params.all? do |param|
22
+ param.allowed? @params[param.name]
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def compose(param)
29
+ value = @params[param.name]
30
+ return unless param.allowed?(value)
31
+ prefixed_name = FriendlyRoutes::PrefixedParam.new(param.name, @route.prefix).call
32
+ @params[prefixed_name] = param.compose(value)
33
+ @params.delete(param.name) unless param.name == prefixed_name
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FriendlyRoutes
4
+ # Compoer will map passed params to friendly_route params
5
+ class MultiComposer
6
+ attr_reader :matched_route
7
+
8
+ def initialize(routes, params = {})
9
+ @routes = routes
10
+ @params = params.dup
11
+ end
12
+
13
+ def call
14
+ compose unless @composed_params
15
+ @composed_params
16
+ end
17
+
18
+ private
19
+
20
+ def compose
21
+ @routes.each do |route|
22
+ composer = Composer.new(route, @params)
23
+ next unless composer.can_be_composed?
24
+ @matched_route = route
25
+ @composed_params = composer.call
26
+ break
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FriendlyRoutes
4
- VERSION = '0.3.3'
4
+ VERSION = '0.4.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: friendly_routes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Gritsay
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-07 00:00:00.000000000 Z
11
+ date: 2016-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -147,7 +147,9 @@ files:
147
147
  - lib/friendly_routes/params/collection_params.rb
148
148
  - lib/friendly_routes/params/hash_params.rb
149
149
  - lib/friendly_routes/route.rb
150
+ - lib/friendly_routes/services/composer.rb
150
151
  - lib/friendly_routes/services/constraints.rb
152
+ - lib/friendly_routes/services/multi_composer.rb
151
153
  - lib/friendly_routes/services/parser.rb
152
154
  - lib/friendly_routes/services/prefixed_param.rb
153
155
  - lib/friendly_routes/services/prefixed_params.rb