susanin 0.0.1 → 0.1

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: 59b6559ce5c0548853359a6ff22589bd05445937
4
- data.tar.gz: a4f94a1fe9eb848681f264855187ec0174b67e77
3
+ metadata.gz: de5f33ed26b6b589665db41aa026d814640bc551
4
+ data.tar.gz: c3e0d9dc34c3fbd77a8dabf00fb1cdbaa63175c3
5
5
  SHA512:
6
- metadata.gz: 3cca6bf0ac14d8bfdcaa7e9f80fa50f716164f79ad2082acc88f136a2601b4713b85efcb1d545c7c2b8a2155dce80cf66ceda200c20729b90599c9a49bf20c1d
7
- data.tar.gz: 8540146c20a09ef5caadb50a3047f8c90b3b1a57f5ba8df20c291f10dfbb3dbb359408703305ea9fded1375068972a84032612e19ae38b84433b1cbd524d3c50
6
+ metadata.gz: 5cf8df24f3d1229aadf4baa9232ca5979bfec499117af505a9a01f89ed9371bc5f36257b063d54aea81f735c67413b10555e4011d21fe26b9e2f9c0e4e831b09
7
+ data.tar.gz: 9b0279aee97e7635f3acfe218d83c74c13a558dba1958005b6b9281d9d1154ed2a8b9268c1f6829260d24f360a284b037073c24722da0fa15c35be2fa7b9d6f7
data/.cimon.yml ADDED
@@ -0,0 +1,39 @@
1
+ services:
2
+ ruby21:
3
+ from: ruby:2.1.8
4
+ cache:
5
+ - /bundle
6
+ build:
7
+ - gem install bundler
8
+ ruby22:
9
+ from: ruby:2.2.4
10
+ cache:
11
+ - /bundle
12
+ build:
13
+ - gem install bundler
14
+ ruby23:
15
+ from: ruby:2.3.0
16
+ cache:
17
+ - /bundle
18
+ build:
19
+ - gem install bundler
20
+
21
+ default: &default
22
+ prepare:
23
+ - bundle install --path /bundle
24
+ folder: /app
25
+ cmd: bin/rake
26
+ env:
27
+ - COVERAGE=true
28
+
29
+ test21:
30
+ <<: *default
31
+ service: ruby21
32
+
33
+ test22:
34
+ <<: *default
35
+ service: ruby22
36
+
37
+ test23:
38
+ <<: *default
39
+ service: ruby23
data/README.md CHANGED
@@ -24,12 +24,17 @@ By default gems do nothing. Include module 'susanin' to the controller.
24
24
  class ApplicationController < ActionController::Base
25
25
  include ::Susanin
26
26
 
27
- polymorphic_url_prefix do
28
- {
29
- Admin => ->(resource) { [resource.company, resource] },
30
- Photo => ->(resource) { [resource.admin.company, resource.admin, resource] },
31
- Gallery => ->(resource) { [resource.company, resource] }
32
- }
27
+ susanin do
28
+ [
29
+ [:owner, ->(r) { [:admin] }],
30
+ [[:frontend, Link], ->(r) { [:frontend, r] }],
31
+ [User, ->(r) { [:owner, r] }],
32
+ [Project, ->(r) { [:owner, r] }],
33
+ [Link, ->(r) { [:owner, r] }],
34
+ [Admin, ->(r) { [r.company, r] }],
35
+ [Photo, ->(r) { [r.admin.company, r.admin, r] }],
36
+ [Gallery, ->(r) { [r.company, r] }]
37
+ ]
33
38
  end
34
39
 
35
40
  end
@@ -47,7 +52,6 @@ You are able to write this:
47
52
  link_to user.email, [:edit, user], class: 'button'
48
53
  ```
49
54
 
50
-
51
55
  ## Contributing
52
56
 
53
57
  1. Fork it ( https://github.com/[my-github-username]/susanin/fork )
data/Rakefile CHANGED
@@ -1,2 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
2
3
 
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "susanin"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require "pry"
11
+ Pry.start
data/bin/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("rake", "rake")
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/susanin.rb CHANGED
@@ -1,45 +1,56 @@
1
+ require "active_support/core_ext/array"
2
+ require "active_support/concern"
3
+ require "active_support/dependencies/autoload"
1
4
  require "susanin/version"
2
5
 
3
6
  module Susanin
4
7
  extend ActiveSupport::Concern
5
8
 
9
+ autoload :Resource, 'susanin/resource'
10
+ autoload :Pattern, 'susanin/pattern'
11
+
6
12
  included do
7
- hide_action :polymorphic_url
8
- helper_method :polymorphic_url
13
+ hide_action :polymorphic_url, :polymorphic_path
14
+ helper_method :polymorphic_url, :polymorphic_path
9
15
  end
10
16
 
11
- class Resource
17
+ module ClassMethods
18
+ def susanin(content = nil, &block)
19
+ content_proc = block_given? ? Proc.new(&block) : Proc.new { content }
12
20
 
13
- def initialize(values={}, default = ->(resource) { resource })
14
- @resources = values.dup
15
- @resources.default = default
21
+ define_method :susanin do
22
+ @susanin ||= Resource.new(Array.wrap(instance_exec(&content_proc)))
23
+ end
16
24
  end
25
+ end
17
26
 
18
- def get(record)
19
- @resources[record.class][record]
20
- end
27
+ def polymorphic_url(record_or_hash_or_array, options={})
28
+ params = susanin_converter(record_or_hash_or_array, options)
21
29
 
30
+ if (params.first.size == 1) && params.first[0].is_a?(String)
31
+ params.first.first
32
+ else
33
+ super(*params)
34
+ end
22
35
  end
23
36
 
24
- module ClassMethods
25
- def polymorphic_url_prefix(content = nil)
26
- content_proc = if block_given?
27
- Proc.new
28
- else
29
- Proc.new { content }
30
- end
31
- define_method :polymorphic_url_prefix do
32
- @polymorphic_url_prefix ||= Resource.new(*Array.wrap(instance_exec(&content_proc)))
33
- end
37
+ def polymorphic_path(record_or_hash_or_array, options={})
38
+ params = susanin_converter(record_or_hash_or_array, options)
39
+
40
+ if (params.first.size == 1) && params.first[0].is_a?(String)
41
+ params.first.first
42
+ else
43
+ super(*params)
34
44
  end
35
45
  end
36
46
 
37
- def polymorphic_url(record_or_hash_or_array, options={})
38
- parameters = Array.wrap(record_or_hash_or_array).map {|i| polymorphic_url_prefix.get(i) }.flatten
39
- super(parameters, options)
47
+ def susanin_converter(record_or_hash_or_array, options={})
48
+ params = susanin.url_parameters(Array.wrap(record_or_hash_or_array))
49
+ params_options = params.extract_options!
50
+ [params, options.merge(params_options)]
40
51
  end
41
52
 
42
- def polymorphic_url_prefix
43
- @polymorphic_url_prefix ||= Resource.new()
53
+ def susanin
54
+ @susanin ||= Resource.new()
44
55
  end
45
56
  end
@@ -0,0 +1,37 @@
1
+ require "active_support/core_ext/array"
2
+
3
+ module Susanin
4
+
5
+ class Pattern
6
+ include Enumerable
7
+
8
+ def initialize(arr)
9
+ @arr = Array.wrap(arr)
10
+ end
11
+
12
+ def each(&block)
13
+ shifts.map do |s|
14
+ a = @arr.slice(*s)
15
+ block.call(a.size == 1 ? a[0] : a)
16
+ end
17
+ end
18
+
19
+ def arr_size
20
+ @arr.size
21
+ end
22
+
23
+ def shifts
24
+ arr_size.downto(1).flat_map do |shift|
25
+ (0).upto(arr_size-shift).map do |i|
26
+ [0+i, shift]
27
+ end
28
+ end
29
+ end
30
+
31
+ def inspect
32
+ map{|i|i}
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,209 @@
1
+ require "active_support/core_ext/array"
2
+ require "active_support/concern"
3
+
4
+ module Susanin
5
+
6
+ class Resource
7
+
8
+ def initialize(values=[])
9
+ @resources = values.dup
10
+ end
11
+
12
+ def url_parameters(record_or_hash_or_array, options={})
13
+ params = self.get(Array.wrap(record_or_hash_or_array)).flatten
14
+ merged_options(params, options={})
15
+ end
16
+
17
+ #
18
+ # get(
19
+ # [:a, :c, :d],
20
+ # [
21
+ # [[:A, :B], ->(r) {:a}]
22
+ # [[:A], ->(r) {:q}]
23
+ # [[:C], ->(r) {:w}]
24
+ # [[:E], ->(r) {:e}]
25
+ # ]
26
+ # )
27
+ #
28
+ # [:qwe, :wer, :d]
29
+ #
30
+ def get(record, resources=@resources)
31
+ new_record, new_resources = replace_with(Array.wrap(record), resources)
32
+ if record == new_record
33
+ new_record
34
+ else
35
+ get(new_record, new_resources)
36
+ end
37
+ end
38
+
39
+ #
40
+ # replace_with(
41
+ # [:a, :b, :c, :d],
42
+ # [
43
+ # [[:A, :B], ->(r) {:a}]
44
+ # [[:C], ->(r) {:w}]
45
+ # [[:E], ->(r) {:e}]
46
+ # ]
47
+ # )
48
+ #
49
+ # [
50
+ # [:a, :c, :d],
51
+ # [
52
+ # [[:C], ->(r) {:w}]
53
+ # [[:E], ->(r) {:e}]
54
+ # ]
55
+ # ]
56
+ #
57
+ def replace_with(record, resources)
58
+ record = record.dup
59
+ resources = resources.dup
60
+ pattern, converter = find_first_pattern(record, resources)
61
+
62
+ [replace_subrecord(record, pattern, converter), resources_except(resources, pattern)]
63
+ end
64
+
65
+ #
66
+ # find_first_pattern(
67
+ # [:a, :b, :c, :d],
68
+ # [
69
+ # [[:A, :B], ->(r) {:a}]
70
+ # [[:C], ->(r) {:w}]
71
+ # [[:E], ->(r) {:e}]
72
+ # ]
73
+ # )
74
+ #
75
+ # [[:A, :B], ->(r) {:a}]
76
+ #
77
+ def find_first_pattern(record, resources)
78
+ record_patterns = patterns(get_key(record))
79
+
80
+ resources.select do |r|
81
+ record_patterns.include?(r[0])
82
+ end.first || []
83
+ end
84
+
85
+ #
86
+ # resources_except(
87
+ # [
88
+ # [[:A, :B], ->(r) {:a}]
89
+ # [[:A], ->(r) {:q}]
90
+ # [[:C], ->(r) {:w}]
91
+ # [[:E], ->(r) {:e}]
92
+ # ],
93
+ # [:A, :B]
94
+ # )
95
+ #
96
+ # [
97
+ # [[:C], ->(r) {:w}]
98
+ # [[:E], ->(r) {:e}]
99
+ # ],
100
+ #
101
+ def resources_except(resources, keys)
102
+ keys = Array.wrap(keys)
103
+ new_resources = resources.dup
104
+ new_resources.reject! { |r| contains_subarray?(keys, Array.wrap(r[0])) }
105
+ new_resources
106
+ end
107
+
108
+ #
109
+ # get_key(a) => A
110
+ # get_key(A) => A
111
+ # get_key([a]) => [A]
112
+ # get_key([a, B]) => [A, B]
113
+ # get_key([A]) => [A]
114
+ # get_key([A]) => [A]
115
+ # get_key(:qwe) => :qwe
116
+ # get_key([:qwe]) => [:qwe]
117
+ # get_key('qwe') => 'qwe'
118
+ #
119
+ def get_key(record)
120
+ case record
121
+ when Class then record
122
+ when Array then record.map { |i| get_key(i) }
123
+ when Symbol then record
124
+ when String then record
125
+ else record.class
126
+ end
127
+ end
128
+
129
+ #
130
+ # merged_options([], {}) #=> []
131
+ # merged_options([a], {}) #=> [a]
132
+ # merged_options([a, {}], {}) #=> [a]
133
+ # merged_options([a, {a: 1}], {}) #=> [a, {a: 1}]
134
+ # merged_options([a, {}], {a: 1}) #=> [a, {a: 1}]
135
+ # merged_options([a, {a: 1}], {a: 2}) #=> [a, {a: 1}]
136
+ #
137
+ def merged_options(params, options={})
138
+ params = params.dup
139
+ default_options = params.extract_options!
140
+ params + ((default_options.any? || options.any?) ? [default_options.merge(options)] : [])
141
+ end
142
+
143
+ #
144
+ # contains_subarray?([1,2,3,4,5], [1,2,3]) => true
145
+ # contains_subarray?([1,2,3,4,5], [3,4]) => true
146
+ # contains_subarray?([1,2,3,4,5], [1,3,4]) => false
147
+ # contains_subarray?([1,2,3,4,5], 5) => true
148
+ #
149
+ def contains_subarray?(source, subarray)
150
+ source = Array.wrap(source)
151
+ subarray = Array.wrap(subarray)
152
+ iteration_count = source.length - subarray.length
153
+ 0.upto(iteration_count).any? do |i|
154
+ source[i..(i+subarray.length-1)] == subarray
155
+ end
156
+ end
157
+
158
+ def patterns(arr)
159
+ Pattern.new(arr)
160
+ end
161
+
162
+ #
163
+ # replace_subrecord(
164
+ # [:a, :b, :c, :a, :b, :b],
165
+ # [:a, :b],
166
+ # ->(){ '_1_' }
167
+ # )
168
+ #
169
+ # ['_1_', :c, '_1_', :b]
170
+ #
171
+ def replace_subrecord(record, pattern, resource)
172
+ record = record.dup
173
+ pattern = Array.wrap(pattern)
174
+
175
+ i = pattern.length
176
+
177
+ return record if i == 0
178
+
179
+ while i <= record.length do
180
+ set = (0+(i-pattern.length))..(i-1)
181
+ subset = record[set]
182
+
183
+ if pattern_match?(subset, pattern)
184
+ value = resource.call(*subset)
185
+ record[set] = value
186
+ i += Array.wrap(value).size
187
+ else
188
+ i += 1
189
+ end
190
+ end
191
+
192
+ record
193
+ end
194
+
195
+ #
196
+ # pattern_match?([a, b], [A, B]) => true
197
+ # pattern_match?([a, b], [a, b]) => false
198
+ #
199
+ def pattern_match?(record, pattern)
200
+ Array.wrap(get_key(record)) == Array.wrap(pattern)
201
+ end
202
+
203
+ def array_unwrap(a)
204
+ a.size == 1 ? a[0] : a
205
+ end
206
+
207
+ end
208
+
209
+ end
@@ -1,3 +1,3 @@
1
1
  module Susanin
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1"
3
3
  end
data/susanin.gemspec CHANGED
@@ -7,19 +7,22 @@ Gem::Specification.new do |spec|
7
7
  spec.name = "susanin"
8
8
  spec.version = Susanin::VERSION
9
9
  spec.authors = ["Alexey Osipenko"]
10
- spec.email = ["alexey@osipenko.in.ua"]
10
+ spec.email = ["alexey@cimon.io"]
11
11
  spec.summary = %q{polymorphic_url extention to help with route generation}
12
12
  spec.description = %q{This gem simplify the route generation which generates via `polymorphic_url` method }
13
- spec.homepage = "https://github.com/aratak/susanin"
13
+ spec.homepage = "https://github.com/cimon-io/susanin"
14
14
  spec.license = "MIT"
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0")
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "actionpack", "~> 4.1.1"
21
+ spec.add_dependency "actionpack", ">= 4.1.1", "< 5.0"
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.6"
24
- spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "bundler", "~> 1.11"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "pry"
26
+ spec.add_development_dependency "minitest", "~> 5.1"
27
+ spec.add_development_dependency "simplecov"
25
28
  end
metadata CHANGED
@@ -1,45 +1,93 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: susanin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: '0.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexey Osipenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-11 00:00:00.000000000 Z
11
+ date: 2016-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 4.1.1
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: 4.1.1
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: bundler
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '1.6'
39
+ version: '1.11'
34
40
  type: :development
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '1.6'
46
+ version: '1.11'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '10.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '10.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: pry
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: minitest
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '5.1'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '5.1'
89
+ - !ruby/object:Gem::Dependency
90
+ name: simplecov
43
91
  requirement: !ruby/object:Gem::Requirement
44
92
  requirements:
45
93
  - - ">="
@@ -55,20 +103,29 @@ dependencies:
55
103
  description: 'This gem simplify the route generation which generates via `polymorphic_url`
56
104
  method '
57
105
  email:
58
- - alexey@osipenko.in.ua
59
- executables: []
106
+ - alexey@cimon.io
107
+ executables:
108
+ - console
109
+ - rake
110
+ - setup
60
111
  extensions: []
61
112
  extra_rdoc_files: []
62
113
  files:
114
+ - ".cimon.yml"
63
115
  - ".gitignore"
64
116
  - Gemfile
65
117
  - LICENSE.txt
66
118
  - README.md
67
119
  - Rakefile
120
+ - bin/console
121
+ - bin/rake
122
+ - bin/setup
68
123
  - lib/susanin.rb
124
+ - lib/susanin/pattern.rb
125
+ - lib/susanin/resource.rb
69
126
  - lib/susanin/version.rb
70
127
  - susanin.gemspec
71
- homepage: https://github.com/aratak/susanin
128
+ homepage: https://github.com/cimon-io/susanin
72
129
  licenses:
73
130
  - MIT
74
131
  metadata: {}
@@ -88,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
145
  version: '0'
89
146
  requirements: []
90
147
  rubyforge_project:
91
- rubygems_version: 2.2.2
148
+ rubygems_version: 2.5.1
92
149
  signing_key:
93
150
  specification_version: 4
94
151
  summary: polymorphic_url extention to help with route generation