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 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
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ .rvmrc
3
+ Gemfile.lock
4
+ store_method.sqlite3
5
+ spec/debug.log
data/CHANGELOG ADDED
File without changes
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cache_method.gemspec
4
+ gemspec
5
+
6
+ gem "database_cleaner", "1.0.1"
7
+ gem 'activerecord-jdbcsqlite3-adapter', :platforms => :jruby
8
+ gem 'sqlite3', :platforms => :ruby
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
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -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
@@ -0,0 +1,3 @@
1
+ module StoreMethod
2
+ VERSION = "0.1.0"
3
+ end
data/spec/database.yml ADDED
@@ -0,0 +1,3 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: store_method.sqlite3
@@ -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
@@ -0,0 +1,5 @@
1
+ ActiveRecord::Schema.define :version => 0 do
2
+ create_table :users, :force => true do |t|
3
+ t.string :name
4
+ end
5
+ end
@@ -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,12 @@
1
+ class User < ActiveRecord::Base
2
+ include StoreMethod
3
+ store_method :name
4
+
5
+ def process(s)
6
+ s * 2
7
+ end
8
+
9
+ def name(first_name = "John")
10
+ process(first_name)
11
+ end
12
+ end
@@ -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: