status_for 0.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.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +31 -0
- data/lib/status_for/acts_as_statusable_for.rb +176 -0
- data/lib/status_for/version.rb +3 -0
- data/lib/status_for.rb +2 -0
- metadata +101 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
begin
|
9
|
+
require 'rdoc/task'
|
10
|
+
rescue LoadError
|
11
|
+
require 'rdoc/rdoc'
|
12
|
+
require 'rake/rdoctask'
|
13
|
+
RDoc::Task = Rake::RDocTask
|
14
|
+
end
|
15
|
+
|
16
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'ActsAsStatusFor'
|
19
|
+
rdoc.options << '--line-numbers'
|
20
|
+
rdoc.rdoc_files.include('README.rdoc')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
23
|
+
|
24
|
+
RSpec::Core::RakeTask.new(:spec)
|
25
|
+
|
26
|
+
|
27
|
+
task :default => :spec
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
Bundler::GemHelper.install_tasks
|
@@ -0,0 +1,176 @@
|
|
1
|
+
module StatusFor
|
2
|
+
def self.included(base)
|
3
|
+
base.extend StatusFor
|
4
|
+
end
|
5
|
+
|
6
|
+
module StatusFor
|
7
|
+
|
8
|
+
# Include initialize_status_for in the model class that you want the status_for to exists.
|
9
|
+
# Step 1:
|
10
|
+
# Example: Defining a deleted_for in Message model
|
11
|
+
# In message.rb, include "initialize_status_for (Object)" where subject is the status for
|
12
|
+
# in question, like a user.
|
13
|
+
# Example: initialize_status_for User
|
14
|
+
|
15
|
+
# Step 2:
|
16
|
+
# In a migration, include a 'status_for' column in the model of interest.
|
17
|
+
# This looks something like add_column :messages, :deleted_for, "integer[]"
|
18
|
+
# The postgres extension intarray is needed for this, so you may need to add the line
|
19
|
+
# execute "CREATE EXTENSION IF NOT EXISTS intarray"
|
20
|
+
# in the correct migration
|
21
|
+
def initialize_status_for(subject)
|
22
|
+
cattr_accessor :status_for_subject
|
23
|
+
if !subject.is_a? Class
|
24
|
+
raise "Subject must be defined as a proper class!"
|
25
|
+
else
|
26
|
+
self.status_for_subject = subject.name
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def method_missing(method_id, subject)
|
31
|
+
# This creates a method for self called 'status_for(subject)' that finds all the
|
32
|
+
# self items with the 'status_for' with the subject id.
|
33
|
+
# Example: Message.deleted_for(user)
|
34
|
+
# Returns array of messages which contains user.id in the message's 'deleted_for'
|
35
|
+
if method_id.to_s =~ /^([a-z]+)_for$/
|
36
|
+
run_find_status_for($1, subject)
|
37
|
+
|
38
|
+
# This creates a method for self called 'not_status_for(subject)' that finds all the
|
39
|
+
# self items with the 'status_for' THAT DOES NOT HAVE the subject id.
|
40
|
+
# Example: Message.deleted_for(user)
|
41
|
+
# Returns array of messages which DOES NOT contain user.id in the message's 'deleted_for'
|
42
|
+
elsif method_id.to_s =~ /^not_([a-z]+)_for$/
|
43
|
+
run_find_not_status_for($1, subject)
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Ensuring the method created for the class exists
|
50
|
+
def respond_to?(method_id, include_private = false)
|
51
|
+
if method_id.to_s =~ /^([a-z]+)_for$/ || method_id.to_s =~ /^not_([a-z]+)_for$/
|
52
|
+
true
|
53
|
+
else
|
54
|
+
super
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# The action performed when calling Message.status_for(subject). Uses a postgres-extension
|
59
|
+
# query
|
60
|
+
def run_find_status_for(method_id, subject)
|
61
|
+
unless subject.class.name == self.status_for_subject
|
62
|
+
raise "Acts_as_status_for is not defined for #{subject.class.name}"
|
63
|
+
end
|
64
|
+
self.where("idx(#{self.table_name}.#{method_id}_for, #{subject.id})::boolean")
|
65
|
+
end
|
66
|
+
|
67
|
+
# The action performed when calling Message.not_status_for(subject). Uses a postgres-extension
|
68
|
+
# query
|
69
|
+
def run_find_not_status_for(method_id, subject)
|
70
|
+
unless subject.class.name == self.status_for_subject
|
71
|
+
raise "Acts_as_status_for is not defined for #{subject.class.name}"
|
72
|
+
end
|
73
|
+
self.where("idx(#{self.table_name}.#{method_id}_for, #{subject.id}) <> 1")
|
74
|
+
end
|
75
|
+
include Status_For_Utils
|
76
|
+
include StatusInstanceMethods
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
module Status_For_Utils
|
81
|
+
# Some conversion is needed to save arrays into the postgresql database tables.
|
82
|
+
def status_for_psql_array_to_array(psql_group)
|
83
|
+
if psql_group
|
84
|
+
eval(psql_group.gsub('NULL', '').gsub('{', '[').gsub('}', ']'))
|
85
|
+
else
|
86
|
+
[]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def status_for_array_to_psql_array(group)
|
91
|
+
mgroup = group.kind_of?(Array) ? group : [group]
|
92
|
+
mgroup.to_s.gsub('[', '{').gsub(']', '}')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
module StatusInstanceMethods
|
97
|
+
|
98
|
+
def method_missing(method_id, subject_ids)
|
99
|
+
# This creates a method for instanced object called 'mark_as_status_for(subject)' that
|
100
|
+
# adds the subject id into relevant database column.
|
101
|
+
# Example: @message.mark_as_deleted_for(user)
|
102
|
+
# Returns a message with the deleted_for containing the subject id
|
103
|
+
if method_id.to_s =~ /^mark_as_([a-z]+)_for\!$/
|
104
|
+
run_mark_as_status_for!($1, subject_ids)
|
105
|
+
# This creates a method for instanced object called 'mark_as_not_ status_for(subject)' that
|
106
|
+
# removes the subject id into relevant database column.
|
107
|
+
# Example: @message.mark_as_not_deleted_for(user)
|
108
|
+
# Returns a message with the subject_id in the deleted_for column removed.
|
109
|
+
elsif method_id.to_s =~ /^mark_as_not_([a-z]+)_for\!$/
|
110
|
+
run_mark_as_not_status_for!($1, subject_ids)
|
111
|
+
# This creates a method for instanced object called 'check_status_for(subject)' that
|
112
|
+
# checks if the subject id is contained in the object.
|
113
|
+
# Example: @message.check_deleted_for(user)
|
114
|
+
# Returns true or false
|
115
|
+
elsif method_id.to_s =~ /^check_([a-z]+)_for\?$/
|
116
|
+
run_check_status_for($1, subject_ids)
|
117
|
+
else
|
118
|
+
super
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Ensuring the method created for the instanced class exists
|
123
|
+
def respond_to?(method_id, include_private = false)
|
124
|
+
if method_id.to_s =~ /^mark_as_([a-z]+)_for\!$/ || method_id.to_s =~ /^mark_as_not_([a-z]+)_for\!$/ || method_id.to_s =~ /^check_([a-z]+)_for\?$/
|
125
|
+
true
|
126
|
+
else
|
127
|
+
super
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# The action performed when calling @object.mark_as_status_for(subject). Uses a postgres-extension
|
132
|
+
# query
|
133
|
+
def run_mark_as_status_for!(method_id, subject_ids)
|
134
|
+
if !self.class.column_names.include?(method_id + '_for')
|
135
|
+
raise "need to include the #{method_id}_for column in #{self.class.table_name} table"
|
136
|
+
end
|
137
|
+
if subject_ids.is_a? Integer
|
138
|
+
subject_ids = [subject_ids]
|
139
|
+
end
|
140
|
+
status_for_subjects = status_for_psql_array_to_array(self.send ((method_id +'_for').to_sym))
|
141
|
+
status_for_subjects = (status_for_subjects + subject_ids).flatten.uniq
|
142
|
+
self.update_attribute(method_id + '_for', status_for_array_to_psql_array(status_for_subjects))
|
143
|
+
self
|
144
|
+
end
|
145
|
+
|
146
|
+
# The action performed when calling @object.mark_as_not_status_for(subject). Uses a postgres-extension
|
147
|
+
# query
|
148
|
+
def run_mark_as_not_status_for!(method_id, subject_ids)
|
149
|
+
if !self.class.column_names.include?(method_id + '_for')
|
150
|
+
raise "need to include the #{method_id}_for column in #{self.class.table_name} table"
|
151
|
+
end
|
152
|
+
if subject_ids.is_a? Integer
|
153
|
+
subject_ids = [subject_ids]
|
154
|
+
end
|
155
|
+
status_for_subjects = status_for_psql_array_to_array(self.send ((method_id +'_for').to_sym))
|
156
|
+
status_for_subjects = (status_for_subjects - subject_ids).flatten.uniq
|
157
|
+
self.update_attribute(method_id + '_for', status_for_array_to_psql_array(status_for_subjects))
|
158
|
+
self
|
159
|
+
end
|
160
|
+
|
161
|
+
# The action performed when calling @object.check_status_for(subject). Uses a postgres-extension
|
162
|
+
# query
|
163
|
+
def run_check_status_for(method_id, subject_id)
|
164
|
+
if !self.class.column_names.include?(method_id + '_for')
|
165
|
+
raise "need to include the #{method_id}_for column in #{self.class.table_name} table"
|
166
|
+
end
|
167
|
+
unless subject_id.is_a? Integer
|
168
|
+
raise "subject_id must be an Integer!"
|
169
|
+
end
|
170
|
+
return status_for_psql_array_to_array(self.send ((method_id +'_for').to_sym)).include?(subject_id)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
ActiveRecord::Base.send :include, StatusFor
|
data/lib/status_for.rb
ADDED
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: status_for
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- David Leung
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.2.8
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.2.8
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: pg
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec-rails
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.0'
|
62
|
+
description: Include this in the module which will allow you to search for status
|
63
|
+
for a class.
|
64
|
+
email:
|
65
|
+
- davleun@gmail.com
|
66
|
+
executables: []
|
67
|
+
extensions: []
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
70
|
+
- lib/status_for/version.rb
|
71
|
+
- lib/status_for/acts_as_statusable_for.rb
|
72
|
+
- lib/status_for.rb
|
73
|
+
- MIT-LICENSE
|
74
|
+
- Rakefile
|
75
|
+
- README.rdoc
|
76
|
+
homepage: ''
|
77
|
+
licenses: []
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 1.8.24
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: Allows tailored status like 'read' or 'deleted' for a class, like a user
|
100
|
+
or message.
|
101
|
+
test_files: []
|