mor 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 65cbde4e429fed57d447b4cc8389063afceda07d
4
+ data.tar.gz: 38ce870a914c548b64fd51d45d6c76ccb8a9092f
5
+ SHA512:
6
+ metadata.gz: 6deeea91d489e2b544f2760b385a9ff0d6886e4da1cf4c8530ffe7b4d4c4c0e1b954a117136c4e0adf35537f3ae541ee5b9dcb31b775ebe8f4dc9d1dadc43ad9
7
+ data.tar.gz: 48711dc97dcd8f2e682b7f90e2c5698ed0630a75c5589541bd388d2a651eb54f246a68541b01483faf41807d45c1df4cbc8a47ee7773c34a15696723416e01f7
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mor.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Onur Uyar
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Mor
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'mor'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install mor
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( http://github.com/<my-github-username>/mor/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'spec'
6
+ t.libs << 'spec/support'
7
+ t.pattern = "spec/**/*_spec.rb"
8
+ end
9
+
10
+ desc "Run tests"
11
+ task :default => :test
@@ -0,0 +1,20 @@
1
+ development:
2
+ compress: true
3
+ threadsafe: true
4
+ namespace: mor:development
5
+ servers: localhost:11211
6
+ async: true
7
+ test:
8
+ compress: true
9
+ threadsafe: true
10
+ namespace: mor:test
11
+ servers: localhost:11211
12
+ async: true
13
+ production:
14
+ compress: true
15
+ threadsafe: true
16
+ namespace: mor
17
+ servers: <%= ENV['MEMCACHIER_SERVERS'] %>
18
+ password: <%= ENV['MEMCACHIER_PASSWORD'] %>
19
+ username: <%= ENV['MEMCACHIER_USERNAME'] %>
20
+ async: true
@@ -0,0 +1,13 @@
1
+ # real time stdout
2
+ $stdout.sync = true
3
+
4
+ %w(. lib).each do |dir|
5
+ path = File.expand_path( "../../#{dir}", __FILE__)
6
+ $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
7
+ end
8
+
9
+ require 'bundler/setup'
10
+ Bundler.setup
11
+
12
+ require 'i18n'
13
+ I18n.enforce_available_locales = false
@@ -0,0 +1,147 @@
1
+ require 'yaml'
2
+ require 'erb'
3
+ require 'dalli'
4
+ require 'active_model'
5
+ require 'active_model/callbacks'
6
+ require 'active_support/hash_with_indifferent_access'
7
+ require 'active_support/concern'
8
+ module Mor
9
+
10
+ def self.env
11
+ ENV['RACK_ENV'] ||= "development"
12
+ end
13
+
14
+ def self.cache=cache
15
+ @@cache=cache
16
+ end
17
+
18
+ def self.cache
19
+ @@cache ||= begin
20
+ config = YAML::load(ERB.new(File.read("config/cache.yml")).result)[Mor.env]
21
+ @instance = Dalli::Client.new config.delete("servers").split(","), config
22
+ end
23
+ end
24
+
25
+ extend ActiveSupport::Concern
26
+ extend ActiveModel::Callbacks
27
+
28
+ module ClassMethods
29
+
30
+ def attr_accessor *attrs
31
+ super(*attrs)
32
+ attrs.delete_if{ |a| a == :attributes }.each { |attr|
33
+ define_method(:"#{attr}="){|val| self.attributes[attr]=val}
34
+ define_method(attr){ self.attributes[attr] }
35
+ }
36
+ end
37
+
38
+ def key id = primary_key
39
+ :"#{self.name.downcase}:#{id}"
40
+ end
41
+
42
+ def primary_key
43
+ :id
44
+ end
45
+
46
+ def create attributes = {}
47
+ instance = self.new(attributes)
48
+ instance.save
49
+ instance
50
+ end
51
+
52
+ end
53
+
54
+ included do
55
+ include ActiveModel::Model
56
+ extend ActiveModel::Callbacks
57
+ include ActiveModel::Validations::Callbacks
58
+ define_model_callbacks :create, :update, :destroy
59
+ after_create :add_to_index
60
+ after_destroy :remove_from_index
61
+ validates_presence_of :id
62
+ validate :validate_uniqueness_of_id
63
+ end
64
+
65
+ def attributes
66
+ @attributes ||= ActiveSupport::HashWithIndifferentAccess.new
67
+ end
68
+
69
+ def initialize attributes = {}
70
+ self.attributes ||= ActiveSupport::HashWithIndifferentAccess.new(attributes)
71
+ end
72
+
73
+ def update attributes={}
74
+ self.attributes.update attributes
75
+ save
76
+ end
77
+
78
+ def save
79
+ if self.valid?
80
+ if self.persisted?
81
+ run_callbacks :update do
82
+ cache.set(self.key,self)
83
+ end
84
+ else
85
+ run_callbacks :create do
86
+ cache.set(self.key,self)
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ def destroy
93
+ run_callbacks :destroy do
94
+ cache.delete key
95
+ end
96
+ end
97
+
98
+ def key
99
+ self.class.key self.id
100
+ end
101
+
102
+ def persisted?
103
+ self.indexed?
104
+ end
105
+
106
+ def id
107
+ self.attributes[self.class.primary_key]
108
+ end
109
+
110
+ # index
111
+
112
+ def indexed?
113
+ @indexed ||= index.include?(self.id)
114
+ end
115
+
116
+ def index
117
+ @index ||= begin
118
+ cache.get(self.class.key) || (self.index=[])
119
+ end
120
+ end
121
+
122
+ def index=index
123
+ @index = begin
124
+ cache.set(self.class.key,index) ? index : []
125
+ end
126
+ end
127
+
128
+ private
129
+
130
+ def add_to_index
131
+ self.index = index.push(self.id)
132
+ end
133
+
134
+ def remove_from_index
135
+ self.index = index.tap{ |index| index.delete(self.id) }
136
+ end
137
+
138
+ def validate_uniqueness_of_id
139
+ self.errors.add(:id, :taken) if indexed?
140
+ end
141
+
142
+ def cache
143
+ Mor.cache
144
+ end
145
+
146
+
147
+ end
@@ -0,0 +1,12 @@
1
+ require 'mor/version'
2
+ require 'mor/client'
3
+
4
+ module Mor
5
+
6
+ def self.env
7
+ ENV['RACK_ENV'] ||= "development"
8
+ end
9
+
10
+ extend Client
11
+
12
+ end
@@ -0,0 +1,16 @@
1
+ require 'yaml'
2
+ require 'erb'
3
+ require 'dalli'
4
+
5
+ module Mor
6
+ module Client
7
+
8
+ def cache
9
+ @@cache ||= begin
10
+ config = YAML::load(ERB.new(File.read("config/cache.yml")).result)[Mor.env]
11
+ @instance = Dalli::Client.new config.delete("servers").split(","), config
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,134 @@
1
+ require 'active_model'
2
+ require 'active_support/concern'
3
+ require 'active_support/hash_with_indifferent_access'
4
+
5
+ module Mor
6
+ module Model
7
+
8
+ module ClassMethods
9
+
10
+ def attr_accessor *attrs
11
+ super(*attrs)
12
+ attrs.delete_if{ |a| a == :attributes }.each { |attr|
13
+ define_method(:"#{attr}="){|val| self.attributes[attr]=val}
14
+ define_method(attr){ self.attributes[attr] }
15
+ }
16
+ end
17
+
18
+ def key primary_key=self.primary_key
19
+ :"#{self.name}:#{primary_key}"
20
+ end
21
+
22
+ def primary_key
23
+ :id
24
+ end
25
+
26
+ def create attributes = {}
27
+ instance = self.new(attributes)
28
+ instance.save
29
+ instance
30
+ end
31
+
32
+ def index
33
+ Mor.cache.get(self.key) || (self.index=[])
34
+ end
35
+
36
+ def index=index
37
+ Mor.cache.set(self.key,index) ? index : []
38
+ end
39
+
40
+ def find id
41
+ Mor.cache.get(key(id))
42
+ end
43
+
44
+ def all
45
+ self.index.map{|id| find(id) }
46
+ end
47
+
48
+ end
49
+
50
+ extend ActiveSupport::Concern
51
+
52
+ included do
53
+
54
+ include ActiveModel::Model
55
+
56
+ define_model_callbacks :create, :update, :destroy
57
+ validates_presence_of :id
58
+ validate :validate_uniqueness_of_id, unless: "persisted?"
59
+ after_create :add_to_index
60
+ after_destroy :remove_from_index
61
+
62
+ def persisted?
63
+ self.id.nil? ? false : self.class.index.include?(self.id)
64
+ end
65
+
66
+ end
67
+
68
+ def attributes
69
+ @attributes ||= ActiveSupport::HashWithIndifferentAccess.new
70
+ end
71
+
72
+ def attributes= attributes
73
+ @attributes = ActiveSupport::HashWithIndifferentAccess.new(attributes)
74
+ end
75
+
76
+ def key
77
+ self.class.key(self.id)
78
+ end
79
+
80
+ def id
81
+ self.attributes[self.class.primary_key]
82
+ end
83
+
84
+ def id=val
85
+ self.attributes[self.class.primary_key]=val
86
+ end
87
+
88
+ # CRUD
89
+
90
+ def update attributes = {}
91
+ self.attributes.update attributes
92
+ self.save
93
+ end
94
+
95
+ def save
96
+ if self.valid?
97
+ save_or_update
98
+ end
99
+ end
100
+
101
+ def destroy
102
+ run_callbacks :destroy do
103
+ Mor.cache.delete(self.key)
104
+ end
105
+ end
106
+
107
+ private
108
+
109
+ def validate_uniqueness_of_id
110
+ errors.add(:id, :taken) if self.class.index.include?(self.id)
111
+ end
112
+
113
+ def save_or_update
114
+ if self.persisted?
115
+ run_callbacks :update do
116
+ Mor.cache.set(self.key,self)
117
+ end
118
+ else
119
+ run_callbacks :create do
120
+ Mor.cache.set(self.key,self)
121
+ end
122
+ end
123
+ end
124
+
125
+ def add_to_index
126
+ self.class.index = self.class.index.push(self.id)
127
+ end
128
+
129
+ def remove_from_index
130
+ self.class.index = self.class.index.tap{ |ids| ids.delete(self.id) }
131
+ end
132
+
133
+ end
134
+ end
@@ -0,0 +1,3 @@
1
+ module Mor
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mor/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mor"
8
+ spec.version = Mor::VERSION
9
+ spec.authors = ["Onur Uyar"]
10
+ spec.email = ["me@onuruyar.com"]
11
+ spec.summary = %q{Basic CRUD functionalty over memcached}
12
+ spec.description = %q{Active Model extension for storing data in memcached}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "minitest"
24
+ spec.add_development_dependency "awesome_print"
25
+
26
+ spec.add_dependency "activemodel", "~> 4.0.2"
27
+ spec.add_dependency "dalli", "~> 2.7.0"
28
+ end
@@ -0,0 +1,51 @@
1
+ require 'minitest_helper'
2
+ require 'mor'
3
+ require 'mor/model'
4
+
5
+ class TestModel
6
+ include Mor::Model
7
+ attr_accessor :id,:title,:body
8
+
9
+ end
10
+
11
+ describe Mor::Model do
12
+
13
+ it "acts as active_model/model" do
14
+ instance = TestModel.new(title: "title", body: "test body")
15
+ instance.title.must_equal "title"
16
+ instance.body.must_equal "test body"
17
+ end
18
+
19
+ it "stores attribute data in @attributes instance var" do
20
+ instance = TestModel.new(title: "title", body: "test body")
21
+ instance.attributes[:title].must_equal "title"
22
+ instance.attributes[:body].must_equal "test body"
23
+ end
24
+
25
+ it "validates id as a primary key by default" do
26
+ instance = TestModel.new(title: "title", body: "test body")
27
+ instance.valid?.must_equal false
28
+ instance.id = "test-id"
29
+ instance.valid?.must_equal true
30
+ end
31
+
32
+ it "indexes record's id on save and unindexes on destroy" do
33
+ instance = TestModel.create(id: "test-id", title: "title", body: "test body")
34
+ TestModel.index.must_include "test-id"
35
+ instance.destroy
36
+ TestModel.index.must_be_empty
37
+ end
38
+
39
+ it "provides basic CRUD" do
40
+ instance = TestModel.create(id: "test-id", title: "title", body: "test body")
41
+ instance.valid?.must_equal true
42
+ instance.persisted?.must_equal true
43
+ TestModel.find("test-id").title.must_equal "title"
44
+ TestModel.all.collect(&:id).must_equal [instance.id]
45
+ instance.destroy
46
+ TestModel.all.must_be_empty
47
+ TestModel.index.must_be_empty
48
+ TestModel.find("test-id").must_be_nil
49
+ end
50
+
51
+ end
@@ -0,0 +1,10 @@
1
+ require 'minitest_helper'
2
+ require 'mor'
3
+
4
+ describe Mor do
5
+
6
+ it "should have a singleton dalli client" do
7
+ Mor.cache.class.must_equal Dalli::Client
8
+ end
9
+
10
+ end
@@ -0,0 +1,15 @@
1
+ ENV['RACK_ENV'] = "test"
2
+
3
+ require 'minitest/pride'
4
+ require 'minitest/autorun'
5
+ require 'awesome_print'
6
+
7
+ require_relative "../../config/env"
8
+
9
+ class MiniTest::Spec
10
+
11
+ after :each do
12
+ Mor.cache.flush
13
+ end
14
+
15
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Onur Uyar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: awesome_print
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activemodel
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 4.0.2
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 4.0.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: dalli
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.7.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.7.0
97
+ description: Active Model extension for storing data in memcached
98
+ email:
99
+ - me@onuruyar.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - Gemfile
106
+ - LICENSE.txt
107
+ - README.md
108
+ - Rakefile
109
+ - config/cache.yml
110
+ - config/env.rb
111
+ - lib/mor.old.rb
112
+ - lib/mor.rb
113
+ - lib/mor/client.rb
114
+ - lib/mor/model.rb
115
+ - lib/mor/version.rb
116
+ - mor.gemspec
117
+ - spec/model_spec.rb
118
+ - spec/mor_spec.rb
119
+ - spec/support/minitest_helper.rb
120
+ homepage: ''
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.2.0
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: Basic CRUD functionalty over memcached
144
+ test_files:
145
+ - spec/model_spec.rb
146
+ - spec/mor_spec.rb
147
+ - spec/support/minitest_helper.rb