dooly 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: