store_method 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/CHANGELOG +0 -0
- data/Gemfile +8 -0
- data/README.markdown +84 -0
- data/Rakefile +7 -0
- data/lib/store_method.rb +59 -0
- data/lib/version.rb +3 -0
- data/spec/database.yml +3 -0
- data/spec/lib/store_method_spec.rb +62 -0
- data/spec/schema.rb +5 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/user.rb +12 -0
- data/store_method.gemspec +23 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5703250dc3600052cdd2e94d6398ff4fca22869e
|
4
|
+
data.tar.gz: efae7bf1cddb58c243efd6fab692a36c4211a4af
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ff2d98a02deecc13e60facc13b2131237fb9f985c1693d59b2f1d5951e3246a07fd59b9aa28da3404e264465cfed98dab5e317cdb74af9726a855019adcf56d9
|
7
|
+
data.tar.gz: f9ac267230d2ac56f9087ef31a39aa68fcb31bcacd299c4aee60cc9f295ae52761f7380fa992b5052124ac9bd0b49bbfb4ceec183617a1b77e1b6362da4e813a
|
data/.gitignore
ADDED
data/CHANGELOG
ADDED
File without changes
|
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# store_method
|
2
|
+
|
3
|
+
This gem offers very simple approach to cache heavy ActiveRecord instance methods in the database. You just add corresponding field to the database, add store_method line and then just drink your coffee, no other changes needed!
|
4
|
+
|
5
|
+
Heavy methods are methods which consume some time and resources to compute their returned value. If that value does not change over time, storing it to the database is a good idea. Actually this functionality is very similar to existing cachethod, cache_method and method_cacheable gems, but all those gems are using Rails.cache to store computed values. In case if you don't want to bother with Rails.cache, use store_method to store computed values right in the database, it's clean and simple!
|
6
|
+
|
7
|
+
## Install
|
8
|
+
|
9
|
+
In Gemfile
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'store_method', github: 'fomichov/store_method'
|
13
|
+
```
|
14
|
+
|
15
|
+
Then run
|
16
|
+
|
17
|
+
```
|
18
|
+
bundle install
|
19
|
+
```
|
20
|
+
|
21
|
+
## Basic Usage
|
22
|
+
|
23
|
+
Consider gravatar_url instance method which fetches corresponding Gravatar URL for User. This method always takes some time to request www.gravatar.com API so let's store its returned value in the corresponding database field.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
class User < ActiveRecord::Base
|
27
|
+
def gravatar_url
|
28
|
+
...
|
29
|
+
end
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
First create corresponding database field
|
34
|
+
```
|
35
|
+
rails g migration AddGravatarURLToUsers gravatar_url:string
|
36
|
+
```
|
37
|
+
|
38
|
+
(Notice that database column type should match the type that our method returns, any valid column type is supported)
|
39
|
+
|
40
|
+
Then include **StoreMethod** module to our model class, and add store_method call with a method name
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
class User < ActiveRecord::Base
|
44
|
+
include StoreMethod
|
45
|
+
store_method :gravatar_url
|
46
|
+
|
47
|
+
def gravatar_url
|
48
|
+
...
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
Passing multiple method names is also supported:
|
54
|
+
```ruby
|
55
|
+
store_methods :gravatar_url, :friends_count
|
56
|
+
```
|
57
|
+
|
58
|
+
## Refreshing value
|
59
|
+
In case if you need to refresh stored value, call stored method with "refresh_" prefix like this:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
user = User.first
|
63
|
+
user.refresh_gravatar_url
|
64
|
+
SQL (5.7ms) UPDATE `users` SET `users`.`avatar_url` = 'http://www.gravatar.com/avatar/fc383b8294226d72f3a7828eeef86987?d=https%3A%2F%2Fidenticons.github.com%2Ffc383b8294226d72f3a7828eeef86987.png&s=42' WHERE `users`.`id` = 1
|
65
|
+
=> "http://www.gravatar.com/avatar/fc383b8294226d72f3a7828eeef86987?d=https%3A%2F%2Fidenticons.github.com%2Ffc383b8294226d72f3a7828eeef86987.png&s=42"
|
66
|
+
```
|
67
|
+
|
68
|
+
|
69
|
+
## Caveats
|
70
|
+
|
71
|
+
Arguments are also supported
|
72
|
+
|
73
|
+
## Contributing to store_method
|
74
|
+
|
75
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
76
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
77
|
+
* Fork the project
|
78
|
+
* Implement your fix or feature
|
79
|
+
* Add tests for your changes and make sure that all tests are passing
|
80
|
+
* Post a pull request
|
81
|
+
|
82
|
+
## License
|
83
|
+
|
84
|
+
This library is distributed under the Beerware license.
|
data/Rakefile
ADDED
data/lib/store_method.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module StoreMethod
|
2
|
+
def self.included base
|
3
|
+
base.extend ClassMethods
|
4
|
+
end
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def store_method *names
|
8
|
+
@methods_to_store ||= {}
|
9
|
+
|
10
|
+
names.each do |name|
|
11
|
+
if instance_methods.include?(name.to_sym)
|
12
|
+
store_method_create(name)
|
13
|
+
else
|
14
|
+
@methods_to_store[name.to_sym] = true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
alias_method :store_methods, :store_method
|
20
|
+
|
21
|
+
def method_added name
|
22
|
+
super
|
23
|
+
return if @methods_to_store.nil? || @methods_to_store[name].nil?
|
24
|
+
@methods_to_store.delete(name)
|
25
|
+
store_method_create(name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def store_method_create name
|
29
|
+
alias_method "#{name}_orig", name
|
30
|
+
|
31
|
+
define_method(name) do |*args|
|
32
|
+
if args.empty?
|
33
|
+
val = attributes[name.to_s]
|
34
|
+
unless val
|
35
|
+
val = send("#{name}_orig")
|
36
|
+
if new_record?
|
37
|
+
assign_attributes({name.to_sym => val})
|
38
|
+
else
|
39
|
+
update_column(name.to_sym, val)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
return val
|
43
|
+
else
|
44
|
+
return send("#{name}_orig", *args)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
define_method("refresh_#{name}") do |*args|
|
49
|
+
val = send("#{name}_orig")
|
50
|
+
if new_record?
|
51
|
+
assign_attributes({name.to_sym => val})
|
52
|
+
else
|
53
|
+
update_column(name.to_sym, val)
|
54
|
+
end
|
55
|
+
return val
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/version.rb
ADDED
data/spec/database.yml
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "StoreMethod" do
|
4
|
+
context "new record" do
|
5
|
+
let(:user) { User.new }
|
6
|
+
it "should actually call the process method once" do
|
7
|
+
expect(user).to receive(:process).and_return("JohnJohn").once
|
8
|
+
2.times { expect(user.name).to eq("JohnJohn") }
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should create _orig method" do
|
12
|
+
expect(user.name_orig).to eq("JohnJohn")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should support refresh method" do
|
16
|
+
expect(user.name).to eq("JohnJohn")
|
17
|
+
expect(user).to receive(:process).and_return("AdamAdam")
|
18
|
+
expect(user.refresh_name).to eq("AdamAdam")
|
19
|
+
expect(user.attributes["name"]).to eq("AdamAdam")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should pass attributes" do
|
23
|
+
expect(user.name).to eq("JohnJohn")
|
24
|
+
expect(user.name("Adam")).to eq("AdamAdam")
|
25
|
+
expect(user.attributes["name"]).to eq("JohnJohn")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should save valid record" do
|
29
|
+
expect(user.name).to eq("JohnJohn")
|
30
|
+
expect { user.save }.to change{User.count}.by(1)
|
31
|
+
expect(user.read_attribute(:name)).to eq("JohnJohn")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "existing record" do
|
36
|
+
before(:each) do
|
37
|
+
@user = User.create!
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should actually call the process method once" do
|
41
|
+
expect(@user).to receive(:process).and_return("JohnJohn").once
|
42
|
+
2.times { expect(@user.name).to eq("JohnJohn") }
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should create _orig method" do
|
46
|
+
expect(@user.name_orig).to eq("JohnJohn")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should support refresh method" do
|
50
|
+
expect(@user.name).to eq("JohnJohn")
|
51
|
+
expect(@user).to receive(:process).and_return("AdamAdam")
|
52
|
+
expect(@user.refresh_name).to eq("AdamAdam")
|
53
|
+
expect(@user.attributes["name"]).to eq("AdamAdam")
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should pass attributes" do
|
57
|
+
expect(@user.name).to eq("JohnJohn")
|
58
|
+
expect(@user.name("Adam")).to eq("AdamAdam")
|
59
|
+
expect(@user.attributes["name"]).to eq("JohnJohn")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/spec/schema.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'logger'
|
4
|
+
require 'rspec'
|
5
|
+
require 'active_record'
|
6
|
+
require 'database_cleaner'
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
|
9
|
+
require 'store_method'
|
10
|
+
|
11
|
+
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/debug.log')
|
12
|
+
ActiveRecord::Base.configurations = YAML::load_file(File.dirname(__FILE__) + '/database.yml')
|
13
|
+
ActiveRecord::Base.establish_connection(:sqlite3)
|
14
|
+
|
15
|
+
load(File.dirname(__FILE__) + '/schema.rb')
|
16
|
+
load(File.dirname(__FILE__) + '/user.rb')
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.filter_run :focus => true
|
20
|
+
config.run_all_when_everything_filtered = true
|
21
|
+
config.filter_run_excluding :exclude => true
|
22
|
+
|
23
|
+
config.mock_with :rspec
|
24
|
+
|
25
|
+
config.before(:suite) do
|
26
|
+
DatabaseCleaner.strategy = :truncation
|
27
|
+
DatabaseCleaner.clean
|
28
|
+
end
|
29
|
+
|
30
|
+
config.after(:each) do
|
31
|
+
DatabaseCleaner.clean
|
32
|
+
end
|
33
|
+
end
|
data/spec/user.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path("../lib/version", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "store_method"
|
5
|
+
s.version = StoreMethod::VERSION
|
6
|
+
s.authors = ["Vitaly Fomichov"]
|
7
|
+
s.email = ["fomichov@gmail.com"]
|
8
|
+
s.homepage = "https://github.com/fomichov/store_method"
|
9
|
+
s.summary = %q{Simple ActiveRecord extension to store calculated values in the corresponding database fields}
|
10
|
+
s.description = %q{Simple ActiveRecord extension to store calculated values in the corresponding database fields}
|
11
|
+
|
12
|
+
# s.rubyforge_project = "store_method"
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
|
18
|
+
s.add_dependency "activerecord", ['>= 3.0']
|
19
|
+
s.add_development_dependency "bundler", ['>= 1.0.0', '<= 1.4']
|
20
|
+
s.add_development_dependency 'rspec', ["= 3.1.0"]
|
21
|
+
s.add_development_dependency "database_cleaner", "1.0.1"
|
22
|
+
s.add_development_dependency "rake", ">= 0.9.2"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: store_method
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vitaly Fomichov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-25 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: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0
|
34
|
+
- - <=
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '1.4'
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.0.0
|
44
|
+
- - <=
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.4'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - '='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 3.1.0
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - '='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 3.1.0
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: database_cleaner
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - '='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.0.1
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - '='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 1.0.1
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rake
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.9.2
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 0.9.2
|
89
|
+
description: Simple ActiveRecord extension to store calculated values in the corresponding
|
90
|
+
database fields
|
91
|
+
email:
|
92
|
+
- fomichov@gmail.com
|
93
|
+
executables: []
|
94
|
+
extensions: []
|
95
|
+
extra_rdoc_files: []
|
96
|
+
files:
|
97
|
+
- .gitignore
|
98
|
+
- CHANGELOG
|
99
|
+
- Gemfile
|
100
|
+
- README.markdown
|
101
|
+
- Rakefile
|
102
|
+
- lib/store_method.rb
|
103
|
+
- lib/version.rb
|
104
|
+
- spec/database.yml
|
105
|
+
- spec/lib/store_method_spec.rb
|
106
|
+
- spec/schema.rb
|
107
|
+
- spec/spec_helper.rb
|
108
|
+
- spec/user.rb
|
109
|
+
- store_method.gemspec
|
110
|
+
homepage: https://github.com/fomichov/store_method
|
111
|
+
licenses: []
|
112
|
+
metadata: {}
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options: []
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
requirements: []
|
128
|
+
rubyforge_project:
|
129
|
+
rubygems_version: 2.2.2
|
130
|
+
signing_key:
|
131
|
+
specification_version: 4
|
132
|
+
summary: Simple ActiveRecord extension to store calculated values in the corresponding
|
133
|
+
database fields
|
134
|
+
test_files:
|
135
|
+
- spec/database.yml
|
136
|
+
- spec/lib/store_method_spec.rb
|
137
|
+
- spec/schema.rb
|
138
|
+
- spec/spec_helper.rb
|
139
|
+
- spec/user.rb
|
140
|
+
has_rdoc:
|