pseudocephalopod 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile DELETED
@@ -1,20 +0,0 @@
1
- source :gemcutter
2
-
3
- # Setup gems
4
- gem "activerecord", "= 3.0.0"
5
- gem "reversible_data"
6
- gem "uuid"
7
- gem "sqlite3-ruby", :require => "sqlite3"
8
-
9
- gem "shoulda", :require => nil
10
- gem "redgreen", :require => nil if RUBY_VERSION < "1.9"
11
- gem "rcov", :require => nil
12
- gem "reek", :require => nil
13
- gem "roodi", :require => nil
14
- gem "flay", :require => nil
15
- gem "flog", :require => nil
16
- gem "rake", :require => nil
17
- gem "Saikuro", :require => nil
18
- gem "jeweler", :require => nil
19
-
20
- gem 'ruby-debug', :require => nil
@@ -1,82 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- Saikuro (1.1.0)
5
- activemodel (3.0.0)
6
- activesupport (= 3.0.0)
7
- builder (~> 2.1.2)
8
- i18n (~> 0.4.1)
9
- activerecord (3.0.0)
10
- activemodel (= 3.0.0)
11
- activesupport (= 3.0.0)
12
- arel (~> 1.0.0)
13
- tzinfo (~> 0.3.23)
14
- activesupport (3.0.0)
15
- arel (1.0.1)
16
- activesupport (~> 3.0.0)
17
- builder (2.1.2)
18
- columnize (0.3.1)
19
- flay (1.4.1)
20
- ruby_parser (~> 2.0)
21
- sexp_processor (~> 3.0)
22
- flog (2.5.0)
23
- ruby_parser (~> 2.0)
24
- sexp_processor (~> 3.0)
25
- gemcutter (0.6.1)
26
- git (1.2.5)
27
- i18n (0.4.1)
28
- jeweler (1.4.0)
29
- gemcutter (>= 0.1.0)
30
- git (>= 1.2.5)
31
- rubyforge (>= 2.0.0)
32
- json_pure (1.4.6)
33
- linecache (0.43)
34
- macaddr (1.0.0)
35
- rake (0.8.7)
36
- rcov (0.9.9)
37
- redgreen (1.2.2)
38
- reek (1.2.8)
39
- ruby2ruby (~> 1.2)
40
- ruby_parser (~> 2.0)
41
- sexp_processor (~> 3.0)
42
- reversible_data (0.1.0)
43
- roodi (2.1.0)
44
- ruby_parser
45
- ruby-debug (0.10.3)
46
- columnize (>= 0.1)
47
- ruby-debug-base (~> 0.10.3.0)
48
- ruby-debug-base (0.10.3)
49
- linecache (>= 0.3)
50
- ruby2ruby (1.2.5)
51
- ruby_parser (~> 2.0)
52
- sexp_processor (~> 3.0)
53
- ruby_parser (2.0.5)
54
- sexp_processor (~> 3.0)
55
- rubyforge (2.0.4)
56
- json_pure (>= 1.1.7)
57
- sexp_processor (3.0.5)
58
- shoulda (2.11.3)
59
- sqlite3-ruby (1.3.1)
60
- tzinfo (0.3.23)
61
- uuid (2.3.1)
62
- macaddr (~> 1.0)
63
-
64
- PLATFORMS
65
- ruby
66
-
67
- DEPENDENCIES
68
- Saikuro
69
- activerecord (= 3.0.0)
70
- flay
71
- flog
72
- jeweler
73
- rake
74
- rcov
75
- redgreen
76
- reek
77
- reversible_data
78
- roodi
79
- ruby-debug
80
- shoulda
81
- sqlite3-ruby
82
- uuid
@@ -1,24 +0,0 @@
1
- module Pseudocephalopod
2
- module Generators
3
- class SlugMigrationGenerator < Rails::Generators::NamedBase
4
- include Rails::Generators::Migration
5
-
6
- def self.source_root
7
- @_ps_source_root ||= File.expand_path("templates", File.dirname(__FILE__))
8
- end
9
-
10
- def self.next_migration_number(dirname) #:nodoc:
11
- if ActiveRecord::Base.timestamped_migrations
12
- Time.now.utc.strftime("%Y%m%d%H%M%S")
13
- else
14
- "%.3d" % (current_migration_number(dirname) + 1)
15
- end
16
- end
17
-
18
- def create_migration_file
19
- migration_template "migration.erb", "db/migrate/add_cached_slug_to_#{table_name}.rb"
20
- end
21
-
22
- end
23
- end
24
- end
@@ -1,12 +0,0 @@
1
- class <%= migration_class_name %> < ActiveRecord::Migration
2
-
3
- def self.up
4
- add_column <%= table_name.to_sym.inspect %>, :cached_slug, :string
5
- add_index <%= table_name.to_sym.inspect %>, :cached_slug
6
- end
7
-
8
- def self.down
9
- remove_column <%= table_name.to_sym.inspect %>, :cached_slug
10
- end
11
-
12
- end
@@ -1,24 +0,0 @@
1
- module Pseudocephalopod
2
- module Generators
3
- class SlugsGenerator < Rails::Generators::Base
4
- include Rails::Generators::Migration
5
-
6
- def self.source_root
7
- @_ps_source_root ||= File.expand_path("templates", File.dirname(__FILE__))
8
- end
9
-
10
- def self.next_migration_number(dirname) #:nodoc:
11
- if ActiveRecord::Base.timestamped_migrations
12
- Time.now.utc.strftime("%Y%m%d%H%M%S")
13
- else
14
- "%.3d" % (current_migration_number(dirname) + 1)
15
- end
16
- end
17
-
18
- def create_migration_file
19
- migration_template "migration.erb", "db/migrate/create_pseudocephalopod_slugs.rb"
20
- end
21
-
22
- end
23
- end
24
- end
@@ -1,20 +0,0 @@
1
- class CreatePseudocephalopodSlugs < ActiveRecord::Migration
2
-
3
- def self.up
4
- create_table :slugs do |t|
5
- t.string :scope
6
- t.string :slug
7
- t.integer :record_id
8
- t.datetime :created_at
9
- end
10
- add_index :slugs, [:scope, :slug]
11
- add_index :slugs, [:scope, :record_id]
12
- add_index :slugs, [:scope, :slug, :created_at]
13
- add_index :slugs, [:scope, :record_id, :created_at]
14
- end
15
-
16
- def self.down
17
- drop_table :slugs
18
- end
19
-
20
- end
@@ -1,112 +0,0 @@
1
- module Pseudocephalopod
2
- module ActiveRecordMethods
3
- AR_CLASS_ATTRIBUTE_NAMES = %w(cached_slug_column slug_source slug_convertor_proc default_uuid_slug use_slug_history sync_slugs slug_scope use_slug_cache use_slug_to_param).map(&:to_sym)
4
-
5
- def is_sluggable(source = :name, options = {})
6
- options.symbolize_keys!
7
- class_attribute *AR_CLASS_ATTRIBUTE_NAMES
8
- attr_accessor :found_via_slug
9
- # Load extensions
10
- extend ClassMethods
11
- include InstanceMethods
12
- extend Pseudocephalopod::Scopes
13
- extend Pseudocephalopod::Finders
14
- self.slug_source = source.to_sym
15
- set_slug_options options
16
- alias_method :to_param, :to_slug if use_slug_to_param
17
- include Pseudocephalopod::SlugHistory if use_slug_history
18
- include Pseudocephalopod::Caching if use_slug_cache
19
- before_save :autogenerate_slug
20
- end
21
-
22
- module InstanceMethods
23
-
24
- def to_slug
25
- cached_slug.present? ? cached_slug : id.to_s
26
- end
27
-
28
- def generate_slug
29
- slug_value = send(self.slug_source)
30
- slug_value = self.slug_convertor_proc.call(slug_value) if slug_value.present?
31
- if slug_value.present?
32
- scope = self.class.other_than(self).slug_scope_relation(self)
33
- slug_value = Pseudocephalopod.next_value(scope, slug_value)
34
- write_attribute self.cached_slug_column, slug_value
35
- elsif self.default_uuid_slug
36
- write_attribute self.cached_slug_column, Pseudocephalopod.generate_uuid_slug
37
- else
38
- write_attribute self.cached_slug_column, nil
39
- end
40
- end
41
-
42
- def generate_slug!
43
- generate_slug
44
- save :validate => false
45
- end
46
-
47
- def autogenerate_slug
48
- generate_slug if should_generate_slug?
49
- end
50
-
51
- def should_generate_slug?
52
- send(self.cached_slug_column).blank? || (self.sync_slugs && send(:"#{self.slug_source}_changed?"))
53
- end
54
-
55
- def has_better_slug?
56
- found_via_slug.present? && found_via_slug != to_slug
57
- end
58
-
59
- def slug_scope_key(nested_scope = [])
60
- self.class.slug_scope_key(nested_scope)
61
- end
62
-
63
- end
64
-
65
- module ClassMethods
66
-
67
- def update_all_slugs!
68
- find_each { |r| r.generate_slug! }
69
- end
70
-
71
- def slug_scope_key(nested_scope = [])
72
- ([table_name, slug_scope] + Array(nested_scope)).flatten.compact.join("|")
73
- end
74
-
75
- def slug_scope_relation(record)
76
- has_slug_scope? ? where(slug_scope => record.send(slug_scope)) : scoped
77
- end
78
-
79
- protected
80
-
81
- def has_slug_scope?
82
- self.slug_scope.present?
83
- end
84
-
85
- def set_slug_options(options)
86
- set_slug_convertor options[:convertor]
87
- self.cached_slug_column = (options[:slug_column] || :cached_slug).to_sym
88
- self.slug_scope = options[:scope]
89
- self.default_uuid_slug = !!options.fetch(:uuid, true)
90
- self.sync_slugs = !!options.fetch(:sync, true)
91
- self.use_slug_cache = !!options.fetch(:use_cache, true)
92
- self.use_slug_to_param = !!options.fetch(:to_param, true)
93
- self.use_slug_history = !!options.fetch(:history, Pseudocephalopod::Slug.usable?)
94
- end
95
-
96
- def set_slug_convertor(convertor)
97
- if convertor.present?
98
- unless convertor.respond_to?(:call)
99
- convertor_key = convertor.to_sym
100
- convertor = proc { |r| r.try(convertor_key) }
101
- end
102
- self.slug_convertor_proc = convertor
103
- else
104
- self.slug_convertor_proc = proc do |slug|
105
- slug.respond_to?(:to_url) ? slug.to_url : ActiveSupport::Multibyte::Chars.new(slug.to_s).parameterize
106
- end
107
- end
108
- end
109
-
110
- end
111
- end
112
- end
@@ -1,87 +0,0 @@
1
- require 'digest/sha2'
2
-
3
- module Pseudocephalopod
4
- # Mixin for adding simple caching support to models using pseudocephalod.
5
- # Usually included by passing the :cache option as true (by default it is
6
- # true, you can disable by passing :cache as false or nil).
7
- module Caching
8
- extend ActiveSupport::Concern
9
-
10
- mattr_accessor :cache_expires_in
11
- # Cache for 10 minutes by default.
12
- self.cache_expires_in = 600
13
-
14
- included do
15
- after_save :globally_cache_slug
16
- end
17
-
18
- module InstanceMethods
19
- # Automatically called in after_save, will cache this records id
20
- # with to match the current records slug / scope
21
- def globally_cache_slug
22
- return unless send(:"#{self.cached_slug_column}_changed?")
23
- value = self.to_slug
24
- self.class.cache_slug_lookup!(value, self) if value.present?
25
- unless use_slug_history
26
- value = send(:"#{self.cached_slug_column}_was")
27
- self.class.cache_slug_lookup!(value, nil)
28
- end
29
- end
30
-
31
- # Wraps remove_slug_history! to remove each of the slugs
32
- # recording in this models slug history.
33
- def remove_slug_history!
34
- previous_slugs.each { |s| self.class.cache_slug_lookup!(s, nil) }
35
- super
36
- end
37
-
38
- end
39
-
40
- module ClassMethods
41
-
42
- # Wraps find_using_slug to look in the cache.
43
- def find_using_slug(slug, options = {})
44
- # First, attempt to load an id and then record from the cache.
45
- if (cached_id = lookup_cached_id_from_slug(slug)).present?
46
- return find(cached_id, options).tap { |r| r.found_via_slug = slug }
47
- end
48
- # Otherwise, fallback to the normal approach.
49
- super.tap do |record|
50
- cache_slug_lookup!(slug, record) if record.present?
51
- end
52
- end
53
-
54
- # Returns a slug cache key for a given slug.
55
- def slug_cache_key(slug)
56
- [Pseudocephalopod.cache_key_prefix, slug_scope_key(Digest::SHA256.hexdigest(slug.to_s.strip))].compact.join("/")
57
- end
58
-
59
- def has_cache_for_slug?(slug)
60
- lookup_cached_id_from_slug(slug).present?
61
- end
62
-
63
- # Modify the cache for a given slug. If record is nil, it will
64
- # delete the item from the slug cache, otherwise it will store
65
- # the records id.
66
- def cache_slug_lookup!(slug, record)
67
- return if Pseudocephalopod.cache.blank?
68
- cache = Pseudocephalopod.cache
69
- key = slug_cache_key(slug)
70
- # Set an expires in option for caching.
71
- caching_options = Hash.new.tap do |hash|
72
- expiry = Pseudocephalopod::Caching.cache_expires_in
73
- hash[:expires_in] = expiry.to_i if expiry.present?
74
- end
75
- record.nil? ? cache.delete(key) : cache.write(key, record.id, caching_options)
76
- end
77
-
78
- protected
79
-
80
- def lookup_cached_id_from_slug(slug)
81
- Pseudocephalopod.cache && Pseudocephalopod.cache.read(slug_cache_key(slug))
82
- end
83
-
84
- end
85
-
86
- end
87
- end
@@ -1,19 +0,0 @@
1
- module Pseudocephalopod
2
- module Finders
3
-
4
- def find_using_slug(slug, options = {})
5
- slug = slug.to_s
6
- value = nil
7
- value ||= find_by_id(slug.to_i, options) if slug =~ /\A\d+\Z/
8
- value ||= with_cached_slug(slug).first(options)
9
- value ||= find_using_slug_history(slug, options) if use_slug_history
10
- value.found_via_slug = slug if value.present?
11
- value
12
- end
13
-
14
- def find_using_slug!(slug, options = {})
15
- find_using_slug(slug, options) or raise ActiveRecord::RecordNotFound
16
- end
17
-
18
- end
19
- end
@@ -1,29 +0,0 @@
1
- module Pseudocephalopod
2
- # Implements a simple cache store that uses the
3
- # current processes memory. This makes is primarily
4
- # used for testing purposes in the situations where
5
- # caching is used.
6
- class MemoryCache
7
-
8
- def self.write(key, value, options = {})
9
- cache[key.to_s] = value
10
- end
11
-
12
- def self.read(key)
13
- cache[key.to_s]
14
- end
15
-
16
- def self.delete(key)
17
- cache.delete key.to_s
18
- end
19
-
20
- def self.reset!
21
- @cache = nil
22
- end
23
-
24
- def self.cache
25
- @cache ||= {}
26
- end
27
-
28
- end
29
- end
@@ -1,9 +0,0 @@
1
- module Pseudocephalopod
2
- class Railtie < Rails::Railtie
3
-
4
- initializer "pseudocephalopod.initialize_cache" do
5
- Pseudocephalopod.cache = Rails.cache if Rails.cache.present?
6
- end
7
-
8
- end
9
- end