dooly 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.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
data/Gemfile.lock ADDED
@@ -0,0 +1,87 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dooly (0.0.1)
5
+ activemodel
6
+ activesupport
7
+ rake
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activemodel (3.2.13)
13
+ activesupport (= 3.2.13)
14
+ builder (~> 3.0.0)
15
+ activesupport (3.2.13)
16
+ i18n (= 0.6.1)
17
+ multi_json (~> 1.0)
18
+ binding_of_caller (0.7.1)
19
+ debug_inspector (>= 0.0.1)
20
+ builder (3.0.4)
21
+ coderay (1.0.8)
22
+ columnize (0.3.6)
23
+ debug_inspector (0.0.2)
24
+ debugger (1.2.4)
25
+ columnize (>= 0.3.1)
26
+ debugger-linecache (~> 1.1.1)
27
+ debugger-ruby_core_source (~> 1.1.7)
28
+ debugger-linecache (1.1.2)
29
+ debugger-ruby_core_source (>= 1.1.1)
30
+ debugger-ruby_core_source (1.1.8)
31
+ guard (1.6.2)
32
+ listen (>= 0.6.0)
33
+ lumberjack (>= 1.0.2)
34
+ pry (>= 0.9.10)
35
+ terminal-table (>= 1.4.3)
36
+ thor (>= 0.14.6)
37
+ guard-test (0.7.0)
38
+ guard (>= 1.1)
39
+ test-unit (~> 2.2)
40
+ i18n (0.6.1)
41
+ listen (0.7.2)
42
+ lumberjack (1.0.2)
43
+ metaclass (0.0.1)
44
+ method_source (0.8.1)
45
+ mocha (0.13.2)
46
+ metaclass (~> 0.0.1)
47
+ multi_json (1.7.1)
48
+ pry (0.9.12)
49
+ coderay (~> 1.0.5)
50
+ method_source (~> 0.8)
51
+ slop (~> 3.4)
52
+ pry-debugger (0.2.1)
53
+ debugger (~> 1.2.0)
54
+ pry (~> 0.9.10)
55
+ pry-remote (0.1.6)
56
+ pry (~> 0.9)
57
+ slop (~> 3.0)
58
+ pry-stack_explorer (0.4.9)
59
+ binding_of_caller (>= 0.7)
60
+ pry (~> 0.9.11)
61
+ rake (10.0.4)
62
+ shoulda (3.3.2)
63
+ shoulda-context (~> 1.0.1)
64
+ shoulda-matchers (~> 1.4.1)
65
+ shoulda-context (1.0.2)
66
+ shoulda-matchers (1.4.1)
67
+ activesupport (>= 3.0.0)
68
+ slop (3.4.3)
69
+ terminal-table (1.4.5)
70
+ test-unit (2.5.4)
71
+ thor (0.17.0)
72
+
73
+ PLATFORMS
74
+ ruby
75
+
76
+ DEPENDENCIES
77
+ bundler (~> 1.0)
78
+ dooly!
79
+ guard
80
+ guard-test
81
+ mocha
82
+ pry
83
+ pry-debugger
84
+ pry-remote
85
+ pry-stack_explorer
86
+ shoulda
87
+ shoulda-context
data/MIT-LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013 Insoo Jung
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,164 @@
1
+ Dooly
2
+ ==========
3
+
4
+ _Dooly_ is a character of Korean animation. [둘리](http://ko.wikipedia.org/wiki/%EB%91%98%EB%A6%AC)
5
+
6
+ This gem offer an extension for Rails Serialization, and some helpful feature.
7
+
8
+
9
+ Installation
10
+ ============
11
+
12
+ $ gem install dooly
13
+
14
+
15
+
16
+ Usage
17
+ ==========
18
+
19
+
20
+ Attachment
21
+ ----------
22
+
23
+ By including Dooly::Attachment in your class, that class can attach some data to the instance
24
+
25
+ ```ruby
26
+ require 'dooly'
27
+
28
+ class User < ActiveRecord::Base
29
+ include Dooly::Attachment
30
+ make_attachable_as_json
31
+ end
32
+
33
+ user = User.first
34
+ user.attachment.add(:email, 'dooly@kogil.dong')
35
+ user.attachment.add(:friends) do |u|
36
+ u.friends
37
+ end
38
+ user.attachment.add(:address, {:city=>'seoul'}) do |u, addr_hash|
39
+ addr_hash.merge(:landlord=>'ko gil dong')
40
+ end
41
+
42
+ user.as_json
43
+ # {
44
+ # 'name'=>'dooly', ... ,
45
+ # 'email'=>'dooly@kogil.dong',
46
+ # 'friends'=>user.friends.as_json,
47
+ # 'address'=>{'city'=>'seoul', 'landlord'=>'ko gil dong'}
48
+ # }
49
+ ```
50
+
51
+ Also extended attachment class can be apply
52
+
53
+ ```ruby
54
+ class User < ActiveRecord::Base
55
+ include Dooly::Attachment
56
+
57
+ class Attachment < Dooly::Attachment::Base
58
+ def add_email
59
+ self[:email] = body.email
60
+ end
61
+ end
62
+
63
+ make_attachable_as_json User::Attachment
64
+ end
65
+
66
+ user = User.first
67
+ user.attachment.add_email
68
+ user.as_json #=> {..., 'email'=>'dooly@kogil.dong'}
69
+ ```
70
+
71
+
72
+ IdProxy
73
+ ----------
74
+
75
+ IdProxy is a simple idea for class method that need only model id.
76
+
77
+ ```ruby
78
+ class User < ActiveRecord::Base
79
+ def self.friends(id)
80
+ NoSQL.find_friends_of(id)
81
+ end
82
+
83
+ def friends
84
+ self.class.friends(self.id)
85
+ end
86
+ end
87
+ ```
88
+
89
+ using IdProxy...
90
+
91
+ ```ruby
92
+ class User < ActiveRecord::Base
93
+ include Dooly::IdProxy
94
+
95
+ class IdProxy < Dooly::IdProxy::Base
96
+ def friends
97
+ NoSQL.find_friends_of(id)
98
+ end
99
+ end
100
+
101
+ id_proxy_class IdProxy
102
+ id_proxy_delegate
103
+
104
+ def another_instance_method
105
+ end
106
+ end
107
+
108
+ User.id_proxy(1).friends
109
+ User.first.friends # instance of original class can call method of id_proxy
110
+ User.id_proxy(1).another_instance_method # id_proxy can call instance method of original class
111
+ ```
112
+
113
+ Collection
114
+ ----------
115
+
116
+ Fix as_json root option for collection classes. as-is,
117
+
118
+ ```ruby
119
+ User.where('id < 10').as_json(:root=>'users')
120
+ # [
121
+ # {"users"=>{"name"=>"dooly"}},
122
+ # {"users"=>{"name"=>"ddochi"}},
123
+ # ...
124
+ # ]
125
+ ```
126
+
127
+ fix this,
128
+
129
+ ```ruby
130
+ Dooly::Collection::Base.new(User.where('id < 10')).as_json(:root=>'users')
131
+ # {
132
+ # "users" => [
133
+ # {"name"=>"dooly"},
134
+ # {"name"=>"ddochi"}
135
+ # ]
136
+ # }
137
+ ```
138
+
139
+
140
+ Model Regulator
141
+ ---------------
142
+
143
+ Model Regulator can reduce effort of parameter validation.
144
+
145
+ ```ruby
146
+ class User < ActiveRecord::Base
147
+ include Dooly::ModelRegulator
148
+ end
149
+
150
+ class Friend < ActiveRecord::Base
151
+ # this methods can accept number id of user,
152
+ # number id's string of user, user instance, and id_proxy of user
153
+
154
+ def self.sample_method(user)
155
+ u = User.by(user)
156
+ # u is a user instance
157
+ end
158
+
159
+ def self.example_method(user)
160
+ uid = User.id(user)
161
+ # uid is a number id of user
162
+ end
163
+ end
164
+ ```
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ task :default => :test
5
+
6
+ require 'rake/testtask'
7
+
8
+ Rake::TestTask.new(:test) do |test|
9
+ test.libs << 'test'
10
+ test.verbose = true
11
+ end
data/dooly.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require 'dooly/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'dooly'
6
+ s.description = 'Some helpful feature for rails'
7
+ s.version = Dooly::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.date = '2013-07-23'
10
+ s.summary = 'Little dinosaur, Dooly'
11
+ s.homepage = 'http://github.com/insoul/dooly'
12
+ s.authors = ['Insoo Jung']
13
+ s.email = 'ensoul@empal.com'
14
+
15
+ s.files = Dir['**/*'].select{|f| File.file?(f)}
16
+ s.require_path = %w{lib}
17
+
18
+ s.add_dependency 'rake'
19
+ s.add_dependency 'activemodel'
20
+ s.add_dependency 'activesupport'
21
+
22
+ s.add_development_dependency 'bundler', '~> 1.0'
23
+ s.add_development_dependency 'pry'
24
+ s.add_development_dependency 'pry-remote'
25
+ s.add_development_dependency 'pry-stack_explorer'
26
+ s.add_development_dependency 'pry-debugger'
27
+ s.add_development_dependency 'mocha'
28
+ s.add_development_dependency 'shoulda'
29
+ s.add_development_dependency 'shoulda-context'
30
+ s.add_development_dependency 'guard'
31
+ s.add_development_dependency 'guard-test'
32
+ end
@@ -0,0 +1,107 @@
1
+ module Dooly
2
+ module Attachment
3
+ class Base < HashWithIndifferentAccess
4
+ attr_accessor :body
5
+
6
+ def add(k, value = nil, options = {})
7
+ if key?(k)
8
+ warn_duplicated(k); return fetch(k)
9
+ end
10
+
11
+ if value
12
+ store(k, value)
13
+ if block_given?
14
+ self.as_json_procs(k, &Proc.new)
15
+ end
16
+ elsif block_given?
17
+ store(k, Proc.new)
18
+ else
19
+ warn_unassigned_value(k)
20
+ end
21
+
22
+ if options[:as_json_options]
23
+ as_json_options(k, options[:as_json_options])
24
+ else
25
+ as_json_options(k, options) unless options.empty?
26
+ end
27
+ end
28
+
29
+ def as_json_options(k = nil, options = nil)
30
+ @as_json_options ||= HashWithIndifferentAccess.new
31
+ return @as_json_options if k.nil?
32
+ return @as_json_options[k] if options.nil?
33
+
34
+ @as_json_options[k] = options
35
+ end
36
+
37
+ def as_json_procs(k = nil)
38
+ @as_json_procs ||= HashWithIndifferentAccess.new
39
+ return @as_json_procs if k.nil?
40
+ return @as_json_procs[k] unless block_given?
41
+
42
+ @as_json_procs[k] = Proc.new
43
+ end
44
+
45
+ def as_json_procs_run(k = nil, value = nil)
46
+ @as_json_procs_run ||= HashWithIndifferentAccess.new
47
+ return @as_json_procs_run if k.nil?
48
+ return @as_json_procs_run[k] if value.nil?
49
+
50
+ @as_json_procs_run[k] = value
51
+ end
52
+
53
+ alias :to_hash_with_string :to_hash
54
+
55
+ def to_hash
56
+ to_hash_with_string.symbolize_keys
57
+ end
58
+
59
+ def [](key)
60
+ value = fetch(key, nil)
61
+ return nil if value.nil?
62
+
63
+ if Proc === value
64
+ value = value.call(body)
65
+ store(key, value)
66
+ end
67
+
68
+ fetch(key)
69
+ end
70
+
71
+ def as_json
72
+ self.each_pair do |k, v|
73
+ if self.as_json_procs(k) and !as_json_procs_run(k)
74
+ v = self.as_json_procs(k).call(body, v)
75
+ self.as_json_procs_run(k, true)
76
+ end
77
+
78
+ if Proc === v
79
+ self[k] = v.call(body).as_json
80
+ elsif v.respond_to?(:as_json)
81
+ if as_json_options(k)
82
+ self[k] = v.as_json(as_json_options(k)).as_json
83
+ else
84
+ self[k] = v.as_json
85
+ end
86
+ else
87
+ self[k] = v.as_json
88
+ end
89
+ end
90
+ self
91
+ end
92
+
93
+ private
94
+ def warn_unassigned_value(key)
95
+ message = ["Attachment has been tried to add with none value, #{self.class.name}/#{key}"]
96
+ message += caller if Rails.env.development?
97
+ Configuration.logger.warn(message.join("\n"))
98
+ end
99
+
100
+ def warn_duplicated(key)
101
+ message = ["Attachment has been tried to add repeatedly about key, #{self.class.name}/#{key}."]
102
+ message += caller if Rails.env.development?
103
+ Configuration.logger.warn(message.join("\n"))
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,48 @@
1
+ module Dooly
2
+ module Attachment
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :attachment_klass
7
+ self.attachment_klass = Dooly::Attachment::Base
8
+ end
9
+
10
+ module ClassMethods
11
+ def make_attachable_as_json(klass = nil)
12
+ klass = Dooly::Attachment::Base if klass.nil?
13
+ unless klass <= Dooly::Attachment::Base
14
+ raise "Attachment class must inherit Dooly::Attachment::Base: #{klass}"
15
+ end
16
+ self.attachment_klass = klass
17
+
18
+ if self.instance_methods.include?(:as_json)
19
+ self.class_eval do
20
+ alias :as_json_exclude_attachment :as_json
21
+ define_method(:as_json) do |options = {}, &block|
22
+ js = if block
23
+ as_json_exclude_attachment(options, &block)
24
+ else
25
+ as_json_exclude_attachment(options)
26
+ end
27
+
28
+ js.class <= Hash ? js.merge(attachment.as_json) : js
29
+ end
30
+ end
31
+ else
32
+ self.class_eval do
33
+ define_method(:as_json) do |options = {}|
34
+ attachment.as_json
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def attachment
42
+ return @attachment if @attachment
43
+ am = self.attachment_klass.new
44
+ am.body = self
45
+ @attachment = am
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,53 @@
1
+ module Dooly
2
+ module Collection
3
+ class Base
4
+ include ActiveModel::Serializers::JSON
5
+
6
+ extend Forwardable
7
+ def_delegators :@collection, *Enumerable.instance_methods
8
+ def_delegators :@collection, :each
9
+
10
+ include Dooly::Attachment
11
+
12
+ attr_reader :collection
13
+
14
+ class_attribute :include_root_in_json
15
+
16
+ def initialize(*args)
17
+ if args.first.respond_to?(:each)
18
+ args = args.first
19
+ end
20
+ @collection = args
21
+ end
22
+
23
+ def as_json(options = {})
24
+ root = options.delete(:root) || self.include_root_in_json
25
+ jsons = block_given? ? self.as_jsons(options, &Proc.new) : self.as_jsons(options)
26
+ if root
27
+ if root == true
28
+ root = begin
29
+ @collection[0].class.model_name.element.pluralize
30
+ rescue
31
+ self.class.name.underscore.split('/')[-2].pluralize rescue 'collection'
32
+ end
33
+ end
34
+ {root => jsons}
35
+ else
36
+ jsons
37
+ end
38
+ end
39
+
40
+ def as_jsons(options = {})
41
+ @collection.map do |member|
42
+ if block_given?
43
+ member.as_json(options, &Proc.new)
44
+ else
45
+ member.as_json(options)
46
+ end
47
+ end
48
+ end
49
+
50
+ make_attachable_as_json
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,23 @@
1
+ module Dooly
2
+ module Collection
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :collection_klass
7
+ self.collection_klass = Dooly::Collection::Base
8
+ end
9
+
10
+ module ClassMethods
11
+ def collection_class(klass)
12
+ unless klass <= Dooly::Collection::Base
13
+ raise "Collection class must inherit Dooly::Colletion::Base: #{klass}"
14
+ end
15
+ self.collection_klass = klass
16
+ end
17
+
18
+ def collection(*args)
19
+ self.collection_klass.new(*args)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ module Dooly
2
+ class Configuration
3
+ class << self
4
+ def logger(lg = nil)
5
+ if lg.nil?
6
+ return @logger if @logger
7
+ return Rails.logger if Rails.defined?
8
+ raise 'logger undefined'
9
+ end
10
+ @logger = lg
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,52 @@
1
+ module Dooly
2
+ module IdProxy
3
+ class Base
4
+ class << self
5
+ attr_accessor :model
6
+ attr_reader :finders
7
+
8
+ def finders=(*args)
9
+ if args[0].is_a? Array
10
+ @finders = args[0]
11
+ else
12
+ @finders = args
13
+ end
14
+ end
15
+ alias :finder :finders
16
+ alias :finder= :finders=
17
+ end
18
+
19
+ attr_reader :id
20
+
21
+ def initialize(id)
22
+ raise 'idea must have id' if id.blank?
23
+ @id = id
24
+ end
25
+
26
+ def record
27
+ return @record if @record
28
+
29
+ self.class.finders.each do |finder|
30
+ f = finder.to_sym
31
+ if self.class.model.respond_to?(f)
32
+ @record = self.class.model.send(f, self.id)
33
+ end
34
+ end
35
+
36
+ unless @record
37
+ @record = self.class.model.find(self.id)
38
+ end
39
+
40
+ @record
41
+ end
42
+
43
+ def respond_to?(name)
44
+ self.record.respond_to?(name) || super
45
+ end
46
+
47
+ def method_missing(name, *args, &block)
48
+ self.record.send(name, *args, &block)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,57 @@
1
+ module Dooly
2
+ module IdProxy
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :id_proxy_klass, :id_proxy_options
7
+ self.id_proxy_klass = Dooly::IdProxy::Base
8
+ end
9
+
10
+ module ClassMethods
11
+ def id_proxy_class(klass, options = {})
12
+ raise "Id Proxy class must inherit Dooly::IdProxyBase: #{klass}" unless klass <= Dooly::IdProxy::Base
13
+ self.id_proxy_klass = klass
14
+ self.id_proxy_klass.model = self
15
+ finders = options[:finders] || options[:finder]
16
+ self.id_proxy_klass.finders = finders if finders
17
+ end
18
+
19
+ def id_proxy_delegate
20
+ self.extend Forwardable
21
+ self.def_delegators 'self.id_proxy', *self.id_proxy_klass.instance_methods(false)
22
+ end
23
+
24
+ def id_proxy(*args)
25
+ options = args.extract_options!
26
+
27
+ if args.length > 1
28
+ return args.map {|arg| id(arg, options)}
29
+ end
30
+
31
+ value = args[0]
32
+ begin
33
+ return value.idx if value.is_a? self
34
+ return self.id_proxy_klass.new(value) if value.is_a? Integer
35
+ return self.id_proxy_klass.new(Integer(value)) if value.is_a? String
36
+ return value if Dooly::IdProxy::Base === value
37
+
38
+ if options[:relate]
39
+ fn = options[:relate] == true ? "#{self.name.underscore}_id".to_sym : options[:relate].to_sym
40
+ return self.id_proxy_klass.new(value.send(fn)) if value.respond_to?(fn)
41
+ end
42
+ rescue => e
43
+ raise "Cannot make id_proxy from #{self.name} with #{value.to_s}: #{e}"
44
+ else
45
+ raise "Cannot make id_proxy from #{self.name} with #{value.to_s}"
46
+ end
47
+ end
48
+ alias :idx :id_proxy
49
+ end
50
+
51
+ def id_proxy
52
+ return nil unless self.id
53
+ @id_proxy ||= self.id_proxy_klass.new(self.id)
54
+ end
55
+ alias :idx :id_proxy
56
+ end
57
+ end
@@ -0,0 +1,58 @@
1
+ module Dooly
2
+ module ModelRegulator
3
+ def model_regulator_finder(finder = nil)
4
+ return (@model_regulator_finder || :find) if finder.nil?
5
+ @model_regulator_finder = finder.to_sym
6
+ end
7
+
8
+ def by(*args)
9
+ options = args.extract_options!
10
+
11
+ if args.length > 1
12
+ return args.map {|arg| by(arg, options)}
13
+ end
14
+
15
+ value = args[0]
16
+ begin
17
+ return value if value.is_a? self
18
+ return self.send(model_regulator_finder, value) if value.is_a? Integer
19
+ return self.send(model_regulator_finder, Integer(value)) if value.is_a? String
20
+ return value.record if Dooly::IdProxy::Base === value
21
+
22
+ if options[:relate]
23
+ fn = options[:relate] == true ? "#{self.name.underscore}_id".to_sym : options[:relate].to_sym
24
+ return self.send(model_regulator_finder, value.send(fn)) if value.respond_to?(fn)
25
+ end
26
+ rescue => e
27
+ raise "Cannot find record from #{self.name} with #{value.to_s}: #{e}"
28
+ else
29
+ raise "Cannot find record from #{self.name} with #{value.to_s}"
30
+ end
31
+ end
32
+
33
+ def id(*args)
34
+ options = args.extract_options!
35
+
36
+ if args.length > 1
37
+ return args.map {|arg| id(arg, options)}
38
+ end
39
+
40
+ value = args[0]
41
+ begin
42
+ return value.id if value.is_a? self
43
+ return value if value.is_a? Integer
44
+ return Integer(value) if value.is_a? String
45
+ return value.id if Dooly::IdProxy::Base === value
46
+
47
+ if options[:relate]
48
+ fn = options[:relate] == true ? "#{self.name.underscore}_id".to_sym : options[:relate].to_sym
49
+ return value.send(fn) if value.respond_to?(fn)
50
+ end
51
+ rescue => e
52
+ raise "Cannot find id from #{self.name} with #{value.to_s}: #{e}"
53
+ else
54
+ raise "Cannot find id from #{self.name} with #{value.to_s}"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module Dooly
2
+ VERSION = '0.1.0'
3
+ end
data/lib/dooly.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'forwardable'
2
+ require 'active_support'
3
+ require 'active_support/core_ext/hash/indifferent_access'
4
+ require 'active_support/core_ext/class/attribute'
5
+ require 'active_support/concern'
6
+ require 'active_support/hash_with_indifferent_access'
7
+ require 'active_model/serialization'
8
+ require 'active_model/naming'
9
+ require 'active_model/serializers/json'
10
+ require 'dooly/version'
11
+ require 'dooly/attachment'
12
+ require 'dooly/attachment/base'
13
+ require 'dooly/collection'
14
+ require 'dooly/collection/base'
15
+ require 'dooly/id_proxy'
16
+ require 'dooly/id_proxy/base'
17
+ require 'dooly/model_regulator'
18
+
19
+ module Dooly
20
+ end
@@ -0,0 +1,74 @@
1
+ require 'test_helper'
2
+
3
+ module Dooly
4
+ class TestAttachment < Test::Unit::TestCase
5
+
6
+ class ModelSample
7
+ include ActiveModel::Serializers::JSON
8
+ self.include_root_in_json = false
9
+ include Dooly::Attachment
10
+
11
+ attr_accessor :name
12
+
13
+ def attributes
14
+ {'name' => name}
15
+ end
16
+
17
+ make_attachable_as_json
18
+ end
19
+
20
+ class ValueSample
21
+ attr_accessor :value
22
+ end
23
+
24
+ class DefaultSample
25
+ include Dooly::Attachment
26
+ end
27
+
28
+ def setup
29
+ super
30
+ end
31
+
32
+ context 'attachment' do
33
+ setup do
34
+ @model = ModelSample.new
35
+ @model.name = 'ddochi'
36
+ end
37
+
38
+ should 'simply' do
39
+ assert_equal({'name'=>'ddochi'}, @model.as_json)
40
+ end
41
+
42
+ should 'defalut attachment class' do
43
+ assert_equal(Dooly::Attachment::Base, DefaultSample.new.attachment.class)
44
+ end
45
+
46
+ should 'attach key-value' do
47
+ @model.attachment.add(:friend, 'donor')
48
+ assert_equal({'name'=>'ddochi', 'friend'=>'donor'}, @model.as_json)
49
+ end
50
+
51
+ should 'attach key-block' do
52
+ @model.attachment.add(:friend) do |body|
53
+ body.name + " and donor"
54
+ end
55
+ assert_equal({'name'=>'ddochi', 'friend'=>'ddochi and donor'}, @model.as_json)
56
+
57
+ # block must be called only once
58
+ assert_equal({'name'=>'ddochi', 'friend'=>'ddochi and donor'}, @model.as_json)
59
+ end
60
+
61
+ should 'attach key-value with block' do
62
+ v = ValueSample.new
63
+ v.value = 'donor'
64
+ @model.attachment.add(:friend, v) do |body, value|
65
+ "#{body.name} #{value.value}"
66
+ end
67
+ assert_equal({'name'=>'ddochi', 'friend'=>'ddochi donor'}, @model.as_json)
68
+
69
+ # block must be called only once
70
+ assert_equal({'name'=>'ddochi', 'friend'=>'ddochi donor'}, @model.as_json)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,57 @@
1
+ module Dooly
2
+ class TestCollection < Test::Unit::TestCase
3
+ class ModelSample
4
+ attr_accessor :name
5
+ include Dooly::Collection
6
+ include ActiveModel::Serializers::JSON
7
+ self.include_root_in_json = false
8
+ include Dooly::Attachment
9
+
10
+ def initialize(name)
11
+ @name = name
12
+ end
13
+
14
+ def attributes
15
+ {'name' => name}
16
+ end
17
+
18
+ def as_json(options = {})
19
+ js = super
20
+ js = yield(js) if block_given?
21
+ js
22
+ end
23
+ make_attachable_as_json
24
+ end
25
+
26
+ context 'collection' do
27
+ setup do
28
+ @ddochi = ModelSample.new('ddochi')
29
+ @donor = ModelSample.new('donor')
30
+ @friends = ModelSample.collection(@ddochi, @donor)
31
+ @friends.attachment.add(:total, 2)
32
+ end
33
+
34
+ should 'simply' do
35
+ assert_equal([{"name"=>"ddochi"}, {"name"=>"donor"}], @friends.as_json)
36
+ assert_equal({
37
+ 'friends' => [{"name"=>"ddochi"}, {"name"=>"donor"}],
38
+ 'total' => 2
39
+ }, @friends.as_json(:root => 'friends'))
40
+ assert_equal('ddochi', @friends.to_a[0].name)
41
+ end
42
+
43
+ should 'block call by member' do
44
+ assert_equal([
45
+ {'name'=>'ddochi', 'friend_of'=>'dooly'},
46
+ {'name'=>'donor', 'friend_of'=>'dooly'}
47
+ ],@friends.as_json {|f| f.merge('friend_of' => 'dooly')})
48
+ end
49
+
50
+ should 'just using base class' do
51
+ assert_equal({
52
+ 'friends' => [{"name"=>"ddochi"}, {"name"=>"donor"}]
53
+ }, Dooly::Collection::Base.new([@ddochi, @donor]).as_json(:root=>'friends'))
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,12 @@
1
+ ENV['DEBUG'] = 'true'
2
+
3
+ require 'test/unit'
4
+ require 'shoulda-context'
5
+ require 'pry'
6
+ require 'pry-remote'
7
+ require 'pry-stack_explorer'
8
+ require 'pry-debugger'
9
+
10
+ require 'rubygems'
11
+ require 'bundler/setup'
12
+ require 'dooly'
@@ -0,0 +1,48 @@
1
+ module Dooly
2
+ class TestIdProxy < Test::Unit::TestCase
3
+ class ModelSample
4
+ attr_accessor :id
5
+
6
+ class IdProxyClass < Dooly::IdProxy::Base
7
+ def proxy_method_sample(arg)
8
+ ['class', arg, self.id.to_s].join(' ')
9
+ end
10
+ end
11
+
12
+ include Dooly::IdProxy
13
+ id_proxy_class IdProxyClass, :finder => :get_cache
14
+ id_proxy_delegate
15
+
16
+ def instance_method_sample(arg)
17
+ ['instance', arg, @id.to_s].join(' ')
18
+ end
19
+
20
+ def self.get_cache(id)
21
+ instance = self.new
22
+ instance.id = id
23
+ instance
24
+ end
25
+ end
26
+
27
+ class DefaultSample
28
+ attr_accessor :id
29
+ include Dooly::IdProxy
30
+ end
31
+
32
+ context 'id_proxy' do
33
+ setup do
34
+ @model = ModelSample.new
35
+ @model.id = 11
36
+ end
37
+
38
+ should 'simply' do
39
+ assert_equal('class simply 11', @model.proxy_method_sample('simply'))
40
+ assert_equal('instance simply 11', ModelSample.id_proxy(11).instance_method_sample('simply'))
41
+ end
42
+
43
+ should 'default id proxy class' do
44
+ assert_equal(Dooly::IdProxy::Base, DefaultSample.idx(11).class)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,60 @@
1
+ require 'test_helper'
2
+
3
+ module Dooly
4
+ class TestModelRegulator < Test::Unit::TestCase
5
+ class ModelSample
6
+ attr_accessor :id
7
+ extend Dooly::ModelRegulator
8
+
9
+ def self.find(id)
10
+ instance = self.new
11
+ instance.id = id
12
+ instance
13
+ end
14
+ end
15
+
16
+ class CacheSample
17
+ attr_accessor :id
18
+ extend Dooly::ModelRegulator
19
+ model_regulator_finder :get_cache
20
+
21
+ def self.get_cache(id)
22
+ instance = self.new
23
+ instance.id = id
24
+ instance
25
+ end
26
+ end
27
+
28
+ def setup
29
+ super
30
+ end
31
+
32
+ context 'model_regulator' do
33
+ setup do
34
+
35
+ end
36
+
37
+ should 'simply' do
38
+ instance = ModelSample.new
39
+ instance.id = 11
40
+ assert_equal(11, ModelSample.by(instance).id)
41
+ assert_equal(11, ModelSample.id(instance))
42
+ assert_equal(11, ModelSample.by(11).id)
43
+ assert_equal(11, ModelSample.id(11))
44
+ assert_equal(11, ModelSample.by('11').id)
45
+ assert_equal(11, ModelSample.id('11'))
46
+ end
47
+
48
+ should 'simple cache' do
49
+ instance = CacheSample.new
50
+ instance.id = 11
51
+ assert_equal(11, CacheSample.by(instance).id)
52
+ assert_equal(11, CacheSample.id(instance))
53
+ assert_equal(11, CacheSample.by(11).id)
54
+ assert_equal(11, CacheSample.id(11))
55
+ assert_equal(11, CacheSample.by('11').id)
56
+ assert_equal(11, CacheSample.id('11'))
57
+ end
58
+ end
59
+ end
60
+ end
metadata ADDED
@@ -0,0 +1,210 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dooly
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Insoo Jung
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &70342471631920 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70342471631920
25
+ - !ruby/object:Gem::Dependency
26
+ name: activemodel
27
+ requirement: &70342471631080 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70342471631080
36
+ - !ruby/object:Gem::Dependency
37
+ name: activesupport
38
+ requirement: &70342471629800 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70342471629800
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: &70342471629000 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70342471629000
58
+ - !ruby/object:Gem::Dependency
59
+ name: pry
60
+ requirement: &70342471628260 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70342471628260
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-remote
71
+ requirement: &70342471626760 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70342471626760
80
+ - !ruby/object:Gem::Dependency
81
+ name: pry-stack_explorer
82
+ requirement: &70342471626100 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70342471626100
91
+ - !ruby/object:Gem::Dependency
92
+ name: pry-debugger
93
+ requirement: &70342471625040 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70342471625040
102
+ - !ruby/object:Gem::Dependency
103
+ name: mocha
104
+ requirement: &70342471623840 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: *70342471623840
113
+ - !ruby/object:Gem::Dependency
114
+ name: shoulda
115
+ requirement: &70342471623320 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: *70342471623320
124
+ - !ruby/object:Gem::Dependency
125
+ name: shoulda-context
126
+ requirement: &70342471622660 !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: *70342471622660
135
+ - !ruby/object:Gem::Dependency
136
+ name: guard
137
+ requirement: &70342471621900 !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: *70342471621900
146
+ - !ruby/object:Gem::Dependency
147
+ name: guard-test
148
+ requirement: &70342471658400 !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ type: :development
155
+ prerelease: false
156
+ version_requirements: *70342471658400
157
+ description: Some helpful feature for rails
158
+ email: ensoul@empal.com
159
+ executables: []
160
+ extensions: []
161
+ extra_rdoc_files: []
162
+ files:
163
+ - dooly-0.1.0.gem
164
+ - dooly.gemspec
165
+ - Gemfile
166
+ - Gemfile.lock
167
+ - lib/dooly/attachment/base.rb
168
+ - lib/dooly/attachment.rb
169
+ - lib/dooly/collection/base.rb
170
+ - lib/dooly/collection.rb
171
+ - lib/dooly/configuration.rb
172
+ - lib/dooly/id_proxy/base.rb
173
+ - lib/dooly/id_proxy.rb
174
+ - lib/dooly/model_regulator.rb
175
+ - lib/dooly/version.rb
176
+ - lib/dooly.rb
177
+ - MIT-LICENSE
178
+ - Rakefile
179
+ - README.markdown
180
+ - test/test_attachment.rb
181
+ - test/test_collection.rb
182
+ - test/test_helper.rb
183
+ - test/test_id_proxy.rb
184
+ - test/test_model_regulator.rb
185
+ homepage: http://github.com/insoul/dooly
186
+ licenses: []
187
+ post_install_message:
188
+ rdoc_options: []
189
+ require_paths:
190
+ - - lib
191
+ required_ruby_version: !ruby/object:Gem::Requirement
192
+ none: false
193
+ requirements:
194
+ - - ! '>='
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ required_rubygems_version: !ruby/object:Gem::Requirement
198
+ none: false
199
+ requirements:
200
+ - - ! '>='
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ requirements: []
204
+ rubyforge_project:
205
+ rubygems_version: 1.8.17
206
+ signing_key:
207
+ specification_version: 3
208
+ summary: Little dinosaur, Dooly
209
+ test_files: []
210
+ has_rdoc: