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 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
@@ -0,0 +1,3 @@
1
+ = ActsAsStatusFor
2
+
3
+ This project rocks and uses MIT-LICENSE.
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
@@ -0,0 +1,3 @@
1
+ module ActsAsStatusFor
2
+ VERSION = "0.0.1"
3
+ end
data/lib/status_for.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'status_for/version'
2
+ require 'status_for/acts_as_statusable_for'
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: []