pseudocephalopod 0.3.1 → 0.3.2
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.
- data/README.md +1 -121
- data/Rakefile +5 -97
- data/lib/pseudocephalopod.rb +3 -78
- metadata +13 -101
- data/Gemfile +0 -20
- data/Gemfile.lock +0 -82
- data/lib/generators/pseudocephalopod/slug_migration/slug_migration_generator.rb +0 -24
- data/lib/generators/pseudocephalopod/slug_migration/templates/migration.erb +0 -12
- data/lib/generators/pseudocephalopod/slugs/slugs_generator.rb +0 -24
- data/lib/generators/pseudocephalopod/slugs/templates/migration.erb +0 -20
- data/lib/pseudocephalopod/active_record_methods.rb +0 -112
- data/lib/pseudocephalopod/caching.rb +0 -87
- data/lib/pseudocephalopod/finders.rb +0 -19
- data/lib/pseudocephalopod/memory_cache.rb +0 -29
- data/lib/pseudocephalopod/railtie.rb +0 -9
- data/lib/pseudocephalopod/scopes.rb +0 -13
- data/lib/pseudocephalopod/slug.rb +0 -36
- data/lib/pseudocephalopod/slug_history.rb +0 -41
- data/lib/pseudocephalopod/version.rb +0 -8
- data/pseudocephalopod.gemspec +0 -90
- data/test/caching_test.rb +0 -77
- data/test/helper.rb +0 -44
- data/test/is_sluggable_test.rb +0 -155
- data/test/model_definitions.rb +0 -19
- data/test/pseudocephalopod_test.rb +0 -27
- data/test/slug_history_test.rb +0 -86
@@ -1,13 +0,0 @@
|
|
1
|
-
module Pseudocephalopod
|
2
|
-
module Scopes
|
3
|
-
|
4
|
-
def with_cached_slug(slug)
|
5
|
-
where(self.cached_slug_column => slug.to_s)
|
6
|
-
end
|
7
|
-
|
8
|
-
def other_than(record)
|
9
|
-
record.new_record? ? scoped : where("#{quoted_table_name}.#{connection.quote_column_name(:id)} != ?", record.id)
|
10
|
-
end
|
11
|
-
|
12
|
-
end
|
13
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module Pseudocephalopod
|
2
|
-
class Slug < ActiveRecord::Base
|
3
|
-
set_table_name "slugs"
|
4
|
-
|
5
|
-
validates_presence_of :record_id, :slug, :scope
|
6
|
-
|
7
|
-
scope :ordered, order('created_at DESC')
|
8
|
-
scope :only_slug, select(:slug)
|
9
|
-
scope :for_record, lambda { |r| where(:record_id => r.id, :scope => Pseudocephalopod.key_for_scope(r)) }
|
10
|
-
scope :for_slug, lambda { |scope, slug| where(:scope=> scope.to_s, :slug => slug.to_s)}
|
11
|
-
|
12
|
-
def self.id_for(scope, slug)
|
13
|
-
ordered.for_slug(scope, slug).first.try(:record_id)
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.record_slug(record, slug)
|
17
|
-
scope = Pseudocephalopod.key_for_scope(record)
|
18
|
-
# Clear slug history in this scope before recording the new slug
|
19
|
-
for_slug(scope, slug).delete_all
|
20
|
-
create :scope => scope, :record_id => record.id, :slug => slug.to_s
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.previous_for(record)
|
24
|
-
ordered.only_slug.for_record(record).all.map(&:slug)
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.remove_history_for(record)
|
28
|
-
for_record(record).delete_all
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.usable?
|
32
|
-
table_exists? rescue false
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module Pseudocephalopod
|
2
|
-
module SlugHistory
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
after_save :record_slug_changes
|
7
|
-
after_destroy :remove_slug_history!
|
8
|
-
end
|
9
|
-
|
10
|
-
module InstanceMethods
|
11
|
-
|
12
|
-
def previous_slugs
|
13
|
-
Pseudocephalopod.previous_slugs_for(self)
|
14
|
-
end
|
15
|
-
|
16
|
-
def remove_slug_history!
|
17
|
-
Pseudocephalopod.remove_slug_history_for(self)
|
18
|
-
end
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
def record_slug_changes
|
23
|
-
slug_column = self.cached_slug_column
|
24
|
-
return unless send(:"#{slug_column}_changed?")
|
25
|
-
value = send(:"#{slug_column}_was")
|
26
|
-
Pseudocephalopod.record_slug(self, value) if value.present?
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
module ClassMethods
|
32
|
-
|
33
|
-
def find_using_slug_history(slug, options = {})
|
34
|
-
id = Pseudocephalopod.last_known_slug_id(self, slug)
|
35
|
-
id.present? ? find_by_id(id, options) : nil
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
data/pseudocephalopod.gemspec
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
-
# -*- encoding: utf-8 -*-
|
5
|
-
|
6
|
-
Gem::Specification.new do |s|
|
7
|
-
s.name = %q{pseudocephalopod}
|
8
|
-
s.version = "0.3.1"
|
9
|
-
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Darcy Laycock"]
|
12
|
-
s.date = %q{2010-09-19}
|
13
|
-
s.description = %q{Super simple slugs for ActiveRecord 3.0 and higher, with support for slug history}
|
14
|
-
s.email = %q{sutto@sutto.net}
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"LICENSE",
|
17
|
-
"README.md"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
".document",
|
21
|
-
".gitignore",
|
22
|
-
".rvmrc",
|
23
|
-
"Gemfile",
|
24
|
-
"Gemfile.lock",
|
25
|
-
"LICENSE",
|
26
|
-
"README.md",
|
27
|
-
"Rakefile",
|
28
|
-
"lib/generators/pseudocephalopod/slug_migration/slug_migration_generator.rb",
|
29
|
-
"lib/generators/pseudocephalopod/slug_migration/templates/migration.erb",
|
30
|
-
"lib/generators/pseudocephalopod/slugs/slugs_generator.rb",
|
31
|
-
"lib/generators/pseudocephalopod/slugs/templates/migration.erb",
|
32
|
-
"lib/pseudocephalopod.rb",
|
33
|
-
"lib/pseudocephalopod/active_record_methods.rb",
|
34
|
-
"lib/pseudocephalopod/caching.rb",
|
35
|
-
"lib/pseudocephalopod/finders.rb",
|
36
|
-
"lib/pseudocephalopod/memory_cache.rb",
|
37
|
-
"lib/pseudocephalopod/railtie.rb",
|
38
|
-
"lib/pseudocephalopod/scopes.rb",
|
39
|
-
"lib/pseudocephalopod/slug.rb",
|
40
|
-
"lib/pseudocephalopod/slug_history.rb",
|
41
|
-
"lib/pseudocephalopod/version.rb",
|
42
|
-
"metrics/.gitignore",
|
43
|
-
"pseudocephalopod.gemspec",
|
44
|
-
"test/caching_test.rb",
|
45
|
-
"test/helper.rb",
|
46
|
-
"test/is_sluggable_test.rb",
|
47
|
-
"test/model_definitions.rb",
|
48
|
-
"test/pseudocephalopod_test.rb",
|
49
|
-
"test/slug_history_test.rb"
|
50
|
-
]
|
51
|
-
s.homepage = %q{http://github.com/Sutto/pseudocephalopod}
|
52
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
53
|
-
s.require_paths = ["lib"]
|
54
|
-
s.rubygems_version = %q{1.3.7}
|
55
|
-
s.summary = %q{Super simple slugs for ActiveRecord 3.0 and higher, with support for slug history}
|
56
|
-
s.test_files = [
|
57
|
-
"test/caching_test.rb",
|
58
|
-
"test/helper.rb",
|
59
|
-
"test/is_sluggable_test.rb",
|
60
|
-
"test/model_definitions.rb",
|
61
|
-
"test/pseudocephalopod_test.rb",
|
62
|
-
"test/slug_history_test.rb"
|
63
|
-
]
|
64
|
-
|
65
|
-
if s.respond_to? :specification_version then
|
66
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
67
|
-
s.specification_version = 3
|
68
|
-
|
69
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
70
|
-
s.add_runtime_dependency(%q<activerecord>, ["~> 3.0.0"])
|
71
|
-
s.add_runtime_dependency(%q<activesupport>, ["~> 3.0.0"])
|
72
|
-
s.add_runtime_dependency(%q<uuid>, [">= 0"])
|
73
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
74
|
-
s.add_development_dependency(%q<reversible_data>, [">= 0"])
|
75
|
-
else
|
76
|
-
s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
|
77
|
-
s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
|
78
|
-
s.add_dependency(%q<uuid>, [">= 0"])
|
79
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
80
|
-
s.add_dependency(%q<reversible_data>, [">= 0"])
|
81
|
-
end
|
82
|
-
else
|
83
|
-
s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
|
84
|
-
s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
|
85
|
-
s.add_dependency(%q<uuid>, [">= 0"])
|
86
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
87
|
-
s.add_dependency(%q<reversible_data>, [">= 0"])
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
data/test/caching_test.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class CachingTest < Test::Unit::TestCase
|
4
|
-
with_tables :slugs, :users do
|
5
|
-
|
6
|
-
setup { Pseudocephalopod::MemoryCache.reset! }
|
7
|
-
|
8
|
-
context 'with the default slug setup' do
|
9
|
-
|
10
|
-
setup { setup_slugs! }
|
11
|
-
|
12
|
-
should 'store a cache automatically after finding it' do
|
13
|
-
assert_has_no_cache_for "bob"
|
14
|
-
u = User.create :name => "Bob"
|
15
|
-
assert_has_cache_for "bob"
|
16
|
-
Pseudocephalopod::MemoryCache.reset!
|
17
|
-
assert_has_no_cache_for "bob"
|
18
|
-
assert_same_as_slug u, "bob"
|
19
|
-
assert_has_cache_for "bob"
|
20
|
-
assert_same_as_slug u, "bob"
|
21
|
-
end
|
22
|
-
|
23
|
-
should 'automatically keep cache entries for history by default' do
|
24
|
-
setup_slugs!
|
25
|
-
assert_has_no_cache_for "bob"
|
26
|
-
assert_has_no_cache_for "red"
|
27
|
-
assert_has_no_cache_for "sam"
|
28
|
-
user = User.create :name => "bob"
|
29
|
-
assert_has_cache_for "bob"
|
30
|
-
assert_has_no_cache_for "red"
|
31
|
-
assert_has_no_cache_for "sam"
|
32
|
-
user.update_attributes :name => "Red"
|
33
|
-
assert_has_cache_for "bob"
|
34
|
-
assert_has_cache_for "red"
|
35
|
-
assert_has_no_cache_for "sam"
|
36
|
-
user.update_attributes :name => "Sam"
|
37
|
-
assert_has_cache_for "bob"
|
38
|
-
assert_has_cache_for "red"
|
39
|
-
assert_has_cache_for "sam"
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
should 'remove cache on models without history' do
|
45
|
-
setup_slugs! :history => false
|
46
|
-
u = User.create :name => "Bob"
|
47
|
-
assert_has_cache_for "bob"
|
48
|
-
assert_has_no_cache_for "red"
|
49
|
-
assert_has_no_cache_for "sam"
|
50
|
-
u.update_attributes :name => "Red"
|
51
|
-
u.update_attributes :name => "Sam"
|
52
|
-
assert_has_no_cache_for "bob"
|
53
|
-
assert_has_no_cache_for "red"
|
54
|
-
assert_has_cache_for "sam"
|
55
|
-
end
|
56
|
-
|
57
|
-
should 'allow you to disable caching' do
|
58
|
-
setup_slugs! :use_cache => false
|
59
|
-
assert !User.respond_to?(:has_cache_for_slug?)
|
60
|
-
end
|
61
|
-
|
62
|
-
# Ensure we destroy the contents of the cache after each test.
|
63
|
-
teardown { Pseudocephalopod::MemoryCache.reset! }
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
protected
|
68
|
-
|
69
|
-
def assert_has_cache_for(key)
|
70
|
-
assert User.has_cache_for_slug?(key), "User should have a cache entry for #{key.inspect}"
|
71
|
-
end
|
72
|
-
|
73
|
-
def assert_has_no_cache_for(key)
|
74
|
-
assert !User.has_cache_for_slug?(key), "User should not have a cache entry for #{key.inspect}"
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
data/test/helper.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
$KCODE = 'UTF8'
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler'
|
5
|
-
Bundler.setup
|
6
|
-
Bundler.require
|
7
|
-
|
8
|
-
require 'test/unit'
|
9
|
-
require 'shoulda'
|
10
|
-
require 'redgreen' if RUBY_VERSION < '1.9'
|
11
|
-
require 'ruby-debug' if ENV['DEBUG']
|
12
|
-
|
13
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
-
require 'pseudocephalopod'
|
16
|
-
require 'model_definitions'
|
17
|
-
|
18
|
-
# Use a memory cache for testing.
|
19
|
-
Pseudocephalopod.cache = Pseudocephalopod::MemoryCache
|
20
|
-
|
21
|
-
class Test::Unit::TestCase
|
22
|
-
extend ReversibleData::ShouldaMacros
|
23
|
-
|
24
|
-
def setup_slugs!(*args)
|
25
|
-
options = args.extract_options!
|
26
|
-
field = args.pop || :name
|
27
|
-
User.is_sluggable field, options
|
28
|
-
end
|
29
|
-
|
30
|
-
def assert_same_as_slug(user, slug, options = {})
|
31
|
-
found_user = User.find_using_slug(slug, options)
|
32
|
-
assert_equal user, found_user, "#{slug.inspect} should return #{user.inspect}, got #{found_user.inspect}"
|
33
|
-
end
|
34
|
-
|
35
|
-
def assert_different_to_slug(user, slug, options = {})
|
36
|
-
found_user = User.find_using_slug(slug, options)
|
37
|
-
assert_not_equal user, found_user, "#{slug.inspect} should not return #{user.inspect}, got same record."
|
38
|
-
end
|
39
|
-
|
40
|
-
def assert_none_for_slug(slug)
|
41
|
-
assert User.find_using_slug(slug).blank?, "slug #{slug.inspect} should not return any records."
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
data/test/is_sluggable_test.rb
DELETED
@@ -1,155 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
require 'digest/md5'
|
3
|
-
|
4
|
-
class IsSluggableTest < Test::Unit::TestCase
|
5
|
-
with_tables :slugs, :users do
|
6
|
-
|
7
|
-
class StringWrapper < String
|
8
|
-
def to_url; "my-demo-slug"; end
|
9
|
-
end
|
10
|
-
|
11
|
-
context 'with the default slug options' do
|
12
|
-
|
13
|
-
setup { setup_slugs! }
|
14
|
-
|
15
|
-
should 'correctly sluggify a value' do
|
16
|
-
user = User.create(:name => "Bob")
|
17
|
-
assert_equal "bob", user.to_param
|
18
|
-
assert_equal "bob", user.cached_slug
|
19
|
-
end
|
20
|
-
|
21
|
-
should 'generate a uuid in place of a slug' do
|
22
|
-
user = User.create(:name => '')
|
23
|
-
assert user.cached_slug.present?
|
24
|
-
end
|
25
|
-
|
26
|
-
should 'return need to generate a slug when the cahced slug is blank' do
|
27
|
-
user = User.new(:name => "Ninja Stuff")
|
28
|
-
assert user.cached_slug.blank?
|
29
|
-
assert user.should_generate_slug?
|
30
|
-
user.save
|
31
|
-
assert user.cached_slug.present?
|
32
|
-
assert !user.should_generate_slug?
|
33
|
-
user.name = 'Awesome'
|
34
|
-
assert user.should_generate_slug?
|
35
|
-
end
|
36
|
-
|
37
|
-
should "let you find a record by it's id as needed" do
|
38
|
-
user = User.create :name => "Bob"
|
39
|
-
assert_equal user, User.find_using_slug(user.id)
|
40
|
-
assert_equal user, User.find_using_slug(user.id.to_i)
|
41
|
-
end
|
42
|
-
|
43
|
-
should 'return nil for unfound slugs by default' do
|
44
|
-
assert_nil User.find_using_slug("awesome")
|
45
|
-
end
|
46
|
-
|
47
|
-
should 'let you find slugs and raise an exception' do
|
48
|
-
assert_raises(ActiveRecord::RecordNotFound) do
|
49
|
-
User.find_using_slug!("awesome")
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
should 'default to generate a uuid' do
|
54
|
-
user = User.create :name => ""
|
55
|
-
assert_match /\A[a-zA-Z0-9]{32}\Z/, user.cached_slug.gsub("-", "")
|
56
|
-
user = User.create
|
57
|
-
assert_match /\A[a-zA-Z0-9]{32}\Z/, user.cached_slug.gsub("-", "")
|
58
|
-
end
|
59
|
-
|
60
|
-
should 'automatically append a sequence to the end of conflicting slugs' do
|
61
|
-
u1 = User.create :name => "ninjas Are awesome"
|
62
|
-
u2 = User.create :name => "Ninjas are awesome"
|
63
|
-
assert_equal "ninjas-are-awesome", u1.to_slug
|
64
|
-
assert_equal "ninjas-are-awesome--1", u2.to_slug
|
65
|
-
end
|
66
|
-
|
67
|
-
should 'let you find out if there is a better way of finding a slug' do
|
68
|
-
user = User.create :name => "Bob"
|
69
|
-
user.update_attributes! :name => "Ralph"
|
70
|
-
assert !User.find_using_slug("ralph").has_better_slug?
|
71
|
-
assert User.find_using_slug("bob").has_better_slug?
|
72
|
-
assert User.find_using_slug(user.id).has_better_slug?
|
73
|
-
end
|
74
|
-
|
75
|
-
should 'not keep a users slug when updating themselves' do
|
76
|
-
user = User.create :name => "bob is awesome"
|
77
|
-
assert_equal "bob-is-awesome", user.to_param
|
78
|
-
assert !user.new_record?
|
79
|
-
user.update_attributes :name => "BOB-is-AWESOME"
|
80
|
-
assert_equal "bob-is-awesome", user.to_param
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'with slug syncing disabled' do
|
86
|
-
setup { setup_slugs! :sync => false }
|
87
|
-
|
88
|
-
should 'let you disable syncing a slug' do
|
89
|
-
user = User.create(:name => "Ninja User")
|
90
|
-
assert !user.should_generate_slug?
|
91
|
-
user.name = "Another User Name"
|
92
|
-
assert !user.should_generate_slug?
|
93
|
-
end
|
94
|
-
|
95
|
-
should 'let you force slug generation' do
|
96
|
-
user = User.create(:name => "Ninja User")
|
97
|
-
assert_equal "ninja-user", user.to_slug
|
98
|
-
user.update_attributes :name => "Test User"
|
99
|
-
assert_equal "ninja-user", user.to_slug
|
100
|
-
user.generate_slug!
|
101
|
-
assert_equal "test-user", user.to_slug
|
102
|
-
user.reload
|
103
|
-
assert_equal "test-user", user.to_slug
|
104
|
-
end
|
105
|
-
|
106
|
-
should 'let you force the update of all slugs' do
|
107
|
-
user_a = User.create(:name => "User A")
|
108
|
-
user_b = User.create(:name => "User B")
|
109
|
-
user_c = User.create(:name => "User C")
|
110
|
-
user_a.update_attributes :name => "User A-1"
|
111
|
-
user_b.update_attributes :name => "User B-1"
|
112
|
-
user_c.update_attributes :name => "User C-1"
|
113
|
-
assert_equal "user-a", user_a.to_slug
|
114
|
-
assert_equal "user-b", user_b.to_slug
|
115
|
-
assert_equal "user-c", user_c.to_slug
|
116
|
-
User.update_all_slugs!
|
117
|
-
user_a.reload
|
118
|
-
user_b.reload
|
119
|
-
user_c.reload
|
120
|
-
assert_equal "user-a-1", user_a.to_slug
|
121
|
-
assert_equal "user-b-1", user_b.to_slug
|
122
|
-
assert_equal "user-c-1", user_c.to_slug
|
123
|
-
end
|
124
|
-
|
125
|
-
end
|
126
|
-
|
127
|
-
context 'setting slug convertors' do
|
128
|
-
|
129
|
-
should 'let you specify a symbol' do
|
130
|
-
setup_slugs! :convertor => :upcase
|
131
|
-
assert_equal "AWESOME USER", User.create(:name => "Awesome User").to_slug
|
132
|
-
end
|
133
|
-
|
134
|
-
should 'let you specify a proc' do
|
135
|
-
setup_slugs! :convertor => proc { |r| r.reverse.upcase }
|
136
|
-
assert_equal "RESU EMOSEWA", User.create(:name => "Awesome User").to_slug
|
137
|
-
end
|
138
|
-
|
139
|
-
should 'call to_url if available by default' do
|
140
|
-
setup_slugs!
|
141
|
-
original_value = StringWrapper.new("Awesome User")
|
142
|
-
assert_equal "my-demo-slug", User.create(:name => original_value).to_slug
|
143
|
-
end
|
144
|
-
|
145
|
-
end
|
146
|
-
|
147
|
-
should 'set the cached slug to nil if uuid is nil and the source value is blank' do
|
148
|
-
setup_slugs! :uuid => nil
|
149
|
-
record = User.create(:name => "")
|
150
|
-
assert_nil record.cached_slug
|
151
|
-
assert_equal record.id.to_s, record.to_slug
|
152
|
-
end
|
153
|
-
|
154
|
-
end
|
155
|
-
end
|