attr_publish 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +4 -0
- data/README.md +136 -0
- data/lib/attr_publish.rb +3 -0
- data/lib/attr_publish/active_record.rb +1 -0
- data/lib/attr_publish/attr_publish.rb +226 -0
- data/lib/attr_publish/version.rb +16 -0
- metadata +79 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 987c18de5f5bed476683cae2628e4742c069e130
|
4
|
+
data.tar.gz: 87a8c39cedb1bbc000ccc711f044fe5d2d8d1c54
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c941855591f4af93280483bf83f97f2f066b5b6819e1fd0fb86b158b1870011b4d4c17bb21ad72a100345dbb513487141ccee1bbc1de8137b40efbd2f1c6b232
|
7
|
+
data.tar.gz: a2df86692d6996fd2d8ed6d040fc34729a721b82615cd953f5cde710b5e5e05ce23e08db15e1b4dbc8a21f4d25b59ac376ca1388c3acf585cf5142504ed68d88
|
data/CHANGELOG.md
ADDED
data/README.md
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
# AttrPublish
|
2
|
+
|
3
|
+
Provides scopes for finding published and unpublished items, and (for date/datetime published columns) for returning recent or upcoming items. Also provides a set of convenient instance methods for publishing and unpublishing a record.
|
4
|
+
|
5
|
+
Allows a given boolean, date, or datetime column to indicate whether a model object is published. A boolean published column is just an on/off flag. A date/datetime column requires the value of published column to be before "current" for the object to be published.
|
6
|
+
|
7
|
+
AttrPublish is extracted from the Brightcommerce platform and is in use by several projects.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
To install add the line to your Gemfile:
|
12
|
+
|
13
|
+
``` ruby
|
14
|
+
gem 'attr_publish'
|
15
|
+
```
|
16
|
+
|
17
|
+
And `bundle install`.
|
18
|
+
|
19
|
+
## How To Use
|
20
|
+
|
21
|
+
To add AttrPublish to a model, include the concern:
|
22
|
+
|
23
|
+
``` ruby
|
24
|
+
class Post < ActiveRecord::Base
|
25
|
+
include AttrPublish
|
26
|
+
|
27
|
+
attr_publish
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
This will automatically default to look for a column named ':published'.
|
32
|
+
|
33
|
+
To autoload AttrPublish for all models, add the following to an initializer:
|
34
|
+
|
35
|
+
``` ruby
|
36
|
+
require 'attr_publish/active_record'
|
37
|
+
```
|
38
|
+
|
39
|
+
You then don't need to `include AttrPublish` in any model, but you still need to add the `attr_publish` class method.
|
40
|
+
|
41
|
+
### Class Methods
|
42
|
+
|
43
|
+
AttrPublish adds the following scopes to your model (using the previous example model `Post`):
|
44
|
+
|
45
|
+
``` ruby
|
46
|
+
Post.published
|
47
|
+
Post.unpublished
|
48
|
+
```
|
49
|
+
|
50
|
+
By default these scopes uses the current date or current time to limit the query. However, you can pass any date or datetime to these scopes to limit the records it returns:
|
51
|
+
|
52
|
+
``` ruby
|
53
|
+
Post.published(DateTime.yesterday)
|
54
|
+
```
|
55
|
+
|
56
|
+
If the published column is of type `:date` or `:datetime` the following additional scopes are provided:
|
57
|
+
|
58
|
+
``` ruby
|
59
|
+
Post.recent
|
60
|
+
Post.upcoming
|
61
|
+
```
|
62
|
+
|
63
|
+
By default these scopes return all matching records. You can limit the number of records returned by passing a number to the scope:
|
64
|
+
|
65
|
+
``` ruby
|
66
|
+
Post.recent(10) # returns the 10 most recent published posts (ordered by date or datetime)
|
67
|
+
Post.upcoming(3) # returns 3 next unpublished posts (ordered by date or datetime)
|
68
|
+
```
|
69
|
+
|
70
|
+
### Instance Methods
|
71
|
+
|
72
|
+
AttrPublish automatically provides the following class instance methods:
|
73
|
+
|
74
|
+
- `published?`
|
75
|
+
- `unpublished?`
|
76
|
+
- `publish`
|
77
|
+
- `publish!`
|
78
|
+
- `unpublish`
|
79
|
+
- `unpublish!`
|
80
|
+
|
81
|
+
If the column type is specified as a Date or Time, you can pass a datetime parameter to the `publish` and `publish!` instance methods. `publish` and `unpublish` methods will change the instance's publish value, but won't save the object. Using the `publish!` and `unpublish!` bang methods will call save (commit) after changing the value.
|
82
|
+
|
83
|
+
### Setup
|
84
|
+
|
85
|
+
Add the model attribute you want to use with AttrPublish in your migration:
|
86
|
+
|
87
|
+
``` ruby
|
88
|
+
class CreatePosts < ActiveRecord::Migration[5.2]
|
89
|
+
def change
|
90
|
+
create_table :posts do |table|
|
91
|
+
table.column :published, :datetime
|
92
|
+
table.timestamps
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
You can change the column used by AttrPublish by adding the column name to the `attr_publish` class method:
|
99
|
+
|
100
|
+
``` ruby
|
101
|
+
class Post < ApplicationRecord
|
102
|
+
include AttrPublish
|
103
|
+
|
104
|
+
attr_publish :published_on
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
## Dependencies
|
109
|
+
|
110
|
+
AttrPublish gem has the following runtime dependencies:
|
111
|
+
- activerecord >= 5.1.4
|
112
|
+
- activesupport >= 5.1.4
|
113
|
+
|
114
|
+
## Compatibility
|
115
|
+
|
116
|
+
Tested with MRI 2.4.2 against Rails 5.2.2.
|
117
|
+
|
118
|
+
## Contributing
|
119
|
+
|
120
|
+
1. Fork it
|
121
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
122
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
123
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
124
|
+
5. Create new Pull Request
|
125
|
+
|
126
|
+
## Credit
|
127
|
+
|
128
|
+
This gem was written and is maintained by [Jurgen Jocubeit](https://github.com/JurgenJocubeit), CEO and President Brightcommerce, Inc.
|
129
|
+
|
130
|
+
## License
|
131
|
+
|
132
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
133
|
+
|
134
|
+
## Copyright
|
135
|
+
|
136
|
+
Copyright 2018 Brightcommerce, Inc.
|
data/lib/attr_publish.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ActiveRecord::Base.send :include, AttrPublish
|
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module AttrPublish
|
4
|
+
extend ::ActiveSupport::Concern
|
5
|
+
|
6
|
+
class_methods do
|
7
|
+
def attr_publish(column)
|
8
|
+
return unless table_exists?
|
9
|
+
|
10
|
+
column_name = column.to_sym || :published
|
11
|
+
|
12
|
+
# Silently ignore a missing column - since bombing on a missing
|
13
|
+
# column can make re-running migrations very hard.
|
14
|
+
return unless self.columns_hash[column_name.to_s].present?
|
15
|
+
|
16
|
+
column_type = self.columns_hash[column_name.to_s].type
|
17
|
+
|
18
|
+
if respond_to?(:scope)
|
19
|
+
# Define published/unpublished scope.
|
20
|
+
case column_type
|
21
|
+
when :date
|
22
|
+
scope :published, lambda { |*args|
|
23
|
+
on_date = args[0] || Date.current
|
24
|
+
where(arel_table[column_name].not_eq(nil)).where(arel_table[column_name].lteq(on_date))
|
25
|
+
}
|
26
|
+
|
27
|
+
scope :unpublished, lambda { |*args|
|
28
|
+
on_date = args[0] || Date.current
|
29
|
+
where(arel_table[column_name].not_eq(nil)).where(arel_table[column_name].gt(on_date))
|
30
|
+
}
|
31
|
+
|
32
|
+
when :datetime
|
33
|
+
scope :published, lambda { |*args|
|
34
|
+
at_time = args[0] || Time.now
|
35
|
+
where(arel_table[column_name].not_eq(nil)).where(arel_table[column_name].lteq(at_time.utc))
|
36
|
+
}
|
37
|
+
|
38
|
+
scope :unpublished, lambda { |*args|
|
39
|
+
at_time = args[0] || Time.now
|
40
|
+
where(arel_table[column_name].not_eq(nil)).where(arel_table[column_name].gt(at_time.utc))
|
41
|
+
}
|
42
|
+
|
43
|
+
when :boolean
|
44
|
+
scope :published, lambda {
|
45
|
+
where(column_name => true)
|
46
|
+
}
|
47
|
+
|
48
|
+
scope :unpublished, lambda {
|
49
|
+
where(column_name => false)
|
50
|
+
}
|
51
|
+
|
52
|
+
else
|
53
|
+
raise ::ActiveRecord::ConfigurationError,
|
54
|
+
"Invalid column_type #{column_type} for Publishable column on model #{self.name}"
|
55
|
+
end
|
56
|
+
|
57
|
+
# Define recent/upcoming scopes.
|
58
|
+
if [:date, :datetime].include?(column_type)
|
59
|
+
scope :recent, lambda { |*args|
|
60
|
+
how_many = args[0] || nil
|
61
|
+
col_name = arel_table[column_name].name
|
62
|
+
published.limit(how_many).order("#{col_name} DESC")
|
63
|
+
}
|
64
|
+
|
65
|
+
scope :upcoming, lambda { |*args|
|
66
|
+
how_many = args[0] || nil
|
67
|
+
col_name = arel_table[column_name].name
|
68
|
+
unpublished.limit(how_many).order("#{col_name} ASC")
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
case column_type
|
74
|
+
when :datetime
|
75
|
+
class_eval <<-EVIL, __FILE__, __LINE__ + 1
|
76
|
+
def published?(_when = Time.current)
|
77
|
+
#{column_name} ? #{column_name} <= _when : false
|
78
|
+
end
|
79
|
+
def unpublished?(_when = Time.current)
|
80
|
+
!published?(_when)
|
81
|
+
end
|
82
|
+
def publish(_when = Time.current)
|
83
|
+
self.#{column_name} = _when unless published?(_when)
|
84
|
+
end
|
85
|
+
def publish!(_when = Time.current)
|
86
|
+
publish(_when) && (!respond_to?(:save) || save)
|
87
|
+
end
|
88
|
+
def unpublish()
|
89
|
+
self.#{column_name} = nil
|
90
|
+
true
|
91
|
+
end
|
92
|
+
def unpublish!()
|
93
|
+
unpublish() && (!respond_to?(:save) || save)
|
94
|
+
end
|
95
|
+
EVIL
|
96
|
+
|
97
|
+
when :date
|
98
|
+
class_eval <<-EVIL, __FILE__, __LINE__ + 1
|
99
|
+
def published?(_when = Date.current)
|
100
|
+
#{column_name} ? #{column_name} <= _when : false
|
101
|
+
end
|
102
|
+
def unpublished?(_when = Date.current)
|
103
|
+
!published?(_when)
|
104
|
+
end
|
105
|
+
def publish(_when = Date.current)
|
106
|
+
self.#{column_name} = _when unless published?(_when)
|
107
|
+
end
|
108
|
+
def publish!(_when = Date.current)
|
109
|
+
publish(_when) && (!respond_to?(:save) || save)
|
110
|
+
end
|
111
|
+
def unpublish()
|
112
|
+
self.#{column_name} = nil
|
113
|
+
end
|
114
|
+
def unpublish!()
|
115
|
+
unpublish() && (!respond_to?(:save) || save)
|
116
|
+
end
|
117
|
+
EVIL
|
118
|
+
|
119
|
+
when :boolean
|
120
|
+
class_eval <<-EVIL, __FILE__, __LINE__ + 1
|
121
|
+
def published?()
|
122
|
+
#{column_name}
|
123
|
+
end
|
124
|
+
def unpublished?()
|
125
|
+
!published?()
|
126
|
+
end
|
127
|
+
def publish()
|
128
|
+
self.#{column_name} = true
|
129
|
+
end
|
130
|
+
def publish!()
|
131
|
+
publish()
|
132
|
+
save if respond_to?(:save)
|
133
|
+
end
|
134
|
+
def unpublish()
|
135
|
+
self.#{column_name} = false
|
136
|
+
end
|
137
|
+
def unpublish!()
|
138
|
+
unpublish()
|
139
|
+
save if respond_to?(:save)
|
140
|
+
end
|
141
|
+
EVIL
|
142
|
+
|
143
|
+
else
|
144
|
+
raise ::ActiveRecord::ConfigurationError,
|
145
|
+
"Invalid column_type #{column_type} for AttrPublish column on model #{self.name}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# @!group Query scopes added to publishable models
|
150
|
+
|
151
|
+
# @!method published
|
152
|
+
# Query scope added to publishables that can be used to find published records. For Date/DateTime publishables,
|
153
|
+
# you can pass a specific date on which the results should be published.
|
154
|
+
# @example Find only records that are currently published
|
155
|
+
# published_posts = Post.published
|
156
|
+
# @example Find only records that will be published in two days
|
157
|
+
# future_posts = Post.published(Date.current + 2.days)
|
158
|
+
# @param [Date, Time, nil] when Specify a date/time for Date/DateTime publishables - defaults to the current date/time
|
159
|
+
# @!scope class
|
160
|
+
|
161
|
+
# @!method unpublished
|
162
|
+
# Query scope added to publishables that can be used find records which are not published. For Date/DateTime
|
163
|
+
# publishables, you can pass a specific date on which the results should not have been published.
|
164
|
+
# @example Find only records that are not currently published
|
165
|
+
# unpublished_posts = Post.unpublished
|
166
|
+
# @param [Date, Time, nil] when Specify a date/time for Date/DateTime publishables - defaults to the current date/time
|
167
|
+
# @!scope class
|
168
|
+
|
169
|
+
# @!method recent
|
170
|
+
# Query scope added to publishables that can be used to lookup records which are currently published. The results
|
171
|
+
# are returned in descending order based on the published date/time.
|
172
|
+
# @example Get the 10 most recently-published records
|
173
|
+
# recent_posts = Post.recent(10)
|
174
|
+
# @param [Integer, nil] how_many Specify how many records to return
|
175
|
+
# @!scope class
|
176
|
+
|
177
|
+
# @!method upcoming
|
178
|
+
# Query scope added to publishables that can be used to lookup records which are not currently published. The
|
179
|
+
# results are returned in ascending order based on the published date/time.
|
180
|
+
# @example Get all posts that will be published in the future
|
181
|
+
# upcoming_posts = Post.upcoming
|
182
|
+
# @param [Integer, nil] how_many Specify how many records to return
|
183
|
+
# @!scope class
|
184
|
+
|
185
|
+
# @!endgroup
|
186
|
+
|
187
|
+
# @!group Instance methods added to publishable models
|
188
|
+
|
189
|
+
# @!method published?
|
190
|
+
# Is this object published?
|
191
|
+
# @param [Date, Time, nil] when For Date/DateTime publishables, a date/time can be passed to determine if the
|
192
|
+
# object was / will be published on the given date.
|
193
|
+
# @return [Boolean] true if published, false if not published.
|
194
|
+
# @!scope instance
|
195
|
+
|
196
|
+
# @!method unpublished?
|
197
|
+
# Is this object not published?
|
198
|
+
# @param [Date, Time, nil] when For Date/DateTime publishables, a date/time can be passed to determine if the
|
199
|
+
# object was not / will not be published on the given date.
|
200
|
+
# @return [Boolean] false if published, true if not published.
|
201
|
+
# @!scope instance
|
202
|
+
|
203
|
+
# @!method publish
|
204
|
+
# Publish this object. For a Boolean publish field, the field is set to true; for a Date/DateTime field, the
|
205
|
+
# field is set to the given Date/Time or to the current date/time.
|
206
|
+
# @param [Date, Time, nil] when For Date/DateTime publishables, a date/time can be passed to specify when the
|
207
|
+
# record will be published. Defaults to +Date.current+ or +Time.now+.
|
208
|
+
# @!scope instance
|
209
|
+
|
210
|
+
# @!method publish!
|
211
|
+
# Publish this object, then immediately save it to the database.
|
212
|
+
# @param [Date, Time, nil] when
|
213
|
+
# @!scope instance
|
214
|
+
|
215
|
+
# @!method unpublish
|
216
|
+
# Un-publish this object, i.e. set it to not be published. For a Boolean publish field, the field is set to
|
217
|
+
# false; for a Date/DateTime field, the field is cleared.
|
218
|
+
# @!scope instance
|
219
|
+
|
220
|
+
# @!method unpublish!
|
221
|
+
# Un-publish this object, then immediately save it to the database.
|
222
|
+
# @!scope instance
|
223
|
+
|
224
|
+
# @!endgroup
|
225
|
+
end
|
226
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module AttrPublish
|
2
|
+
module Version
|
3
|
+
Major = 1
|
4
|
+
Minor = 0
|
5
|
+
Revision = 0
|
6
|
+
Prerelease = nil
|
7
|
+
Compact = [Major, Minor, Revision, Prerelease].compact.join('.')
|
8
|
+
Summary = "AttrPublish v#{Compact}"
|
9
|
+
Description = "ActiveRecord convenience methods and scopes for publishing and finding published, unpublished and returning recent or upcoming items."
|
10
|
+
Author = "Jurgen Jocubeit"
|
11
|
+
Email = "support@brightcommerce.com"
|
12
|
+
Homepage = "https://github.com/brightcommerce/attr_publish"
|
13
|
+
Metadata = {'copyright' => 'Copyright 2018 Brightcommerce, Inc. All Rights Reserved.'}
|
14
|
+
License = "MIT"
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: attr_publish
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jurgen Jocubeit
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-12-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.1.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.1.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 5.1.4
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 5.1.4
|
41
|
+
description: ActiveRecord convenience methods and scopes for publishing and finding
|
42
|
+
published, unpublished and returning recent or upcoming items.
|
43
|
+
email: support@brightcommerce.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- CHANGELOG.md
|
49
|
+
- README.md
|
50
|
+
- lib/attr_publish.rb
|
51
|
+
- lib/attr_publish/active_record.rb
|
52
|
+
- lib/attr_publish/attr_publish.rb
|
53
|
+
- lib/attr_publish/version.rb
|
54
|
+
homepage: https://github.com/brightcommerce/attr_publish
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
metadata:
|
58
|
+
copyright: Copyright 2018 Brightcommerce, Inc. All Rights Reserved.
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2.3'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 2.6.13
|
76
|
+
signing_key:
|
77
|
+
specification_version: 4
|
78
|
+
summary: AttrPublish v1.0.0
|
79
|
+
test_files: []
|