dm-is-remixable 0.9.7 → 0.9.8

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/README.txt CHANGED
@@ -125,3 +125,46 @@ class Video
125
125
 
126
126
  #... methods, properties, etc ...#
127
127
  end
128
+
129
+
130
+ Further, remixables can namespace methods that should exist in the generated and remixing classes, if these
131
+ modules are present the are attached appropriately to the other classes.
132
+
133
+ module ExampleRemixable
134
+ include DataMapper::Resource
135
+ is :remixable
136
+
137
+ #... your properies ...
138
+
139
+ # Class methods that will be attached to class doing the remixing...
140
+ #
141
+ # These methods would be attached to the User class given:
142
+ # User.remixes n, :images
143
+ #
144
+ module RemixerClassMethods
145
+ end
146
+
147
+ # Instances methods that will be attached to objects of the class doing the remixing...
148
+ #
149
+ # These methods would be attached to User objects given:
150
+ # User.remixes n, :images
151
+ #
152
+ module RemixerInstanceMethods
153
+ end
154
+
155
+ # Class methods that will be attached to genereated remixed class
156
+ #
157
+ # These methods would be attached to the UserImage class given:
158
+ # User.remixes n, :images
159
+ #
160
+ module RemixeeClassMethods
161
+ end
162
+
163
+ # Instances methods that will be attached to objects of the genereated remixed class
164
+ #
165
+ # These methods would be attached to UserImage objects given:
166
+ # User.remixes n, :images
167
+ #
168
+ module RemixeeInstanceMethods
169
+ end
170
+ end
data/Rakefile CHANGED
@@ -10,12 +10,12 @@ AUTHOR = "Cory O'Daniel"
10
10
  EMAIL = "dm-is-remixable [a] coryodaniel [d] com"
11
11
  GEM_NAME = "dm-is-remixable"
12
12
  GEM_VERSION = DataMapper::Is::Remixable::VERSION
13
- GEM_DEPENDENCIES = [["dm-core", GEM_VERSION]]
13
+ GEM_DEPENDENCIES = [['dm-core', "~>#{GEM_VERSION}"]]
14
14
  GEM_CLEAN = ["log", "pkg"]
15
15
  GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO ] }
16
16
 
17
17
  PROJECT_NAME = "datamapper"
18
- PROJECT_URL = "http://github.com/sam/dm-more/tree/master/dm-remixes"
18
+ PROJECT_URL = "http://github.com/sam/dm-more/tree/master/dm-is-remixable"
19
19
  PROJECT_DESCRIPTION = PROJECT_SUMMARY = "dm-is-remixable allow you to create reusable data functionality"
20
20
 
21
21
  require ROOT.parent + 'tasks/hoe'
data/TODO CHANGED
@@ -14,17 +14,5 @@ TODO
14
14
  - Test nested remixing User remixes Photogenic; Photogenic Remixes comments
15
15
  - Test double+ remixing. User remixes Commentable; enhance Commentable remix Commentable
16
16
 
17
- - Harvest Class methods (including it into Remixed Model gets the instance methods, but not class methods...)
18
-
19
- - Squash protection;
20
- IF ClassA => remix ModuleB, :table_name => "squashme"
21
- AND ClassC => remix ModuleB, :table_name => "squashme" #SQUASHED THAT TABLE
22
-
23
17
  - Remixable.related(*remixed_models)
24
- Taggable.related(Article, JobPostings)
25
-
26
-
27
- CONSIDERATIONS
28
- ==============
29
- - Customizing Assocations (http://datamapper.org/docs/associations.html)
30
- - Adding Conditions to Associations (http://datamapper.org/docs/associations.html)
18
+ Taggable.related(Article, JobPostings)
@@ -55,6 +55,7 @@ module DataMapper
55
55
  extend DataMapper::Is::Remixable::RemixeeClassMethods
56
56
  include DataMapper::Is::Remixable::RemixeeInstanceMethods
57
57
  @is_remixable = true
58
+
58
59
  # support clean suffixes for nested modules
59
60
  default_suffix = Extlib::Inflection.demodulize(self.name).singular.snake_case
60
61
  suffix(options.delete(:suffix) || default_suffix)
@@ -93,7 +94,8 @@ module DataMapper
93
94
  # This is the class that will be created from the Remixable Module
94
95
  # The storage_name can be changed via 'enhance' in the class that is remixing
95
96
  # Default: self.name.downcase + "_" + remixable.suffix.pluralize
96
- # :as <String> Alias to access associated data
97
+ # :as <String> Alters the name that the remixable items will be available through, this WILL NOT
98
+ # create the standard accessor
97
99
  # Default: tableize(:class_name)
98
100
  # :for|:on <String> Class name to join to through Remixable
99
101
  # This will create a M:M relationship THROUGH the remixable, rather than
@@ -114,7 +116,7 @@ module DataMapper
114
116
  #
115
117
  # Tables: users, user_addresses
116
118
  # Classes: User, UserAddress
117
- # User.user_addresses << UserAddress.new
119
+ # User.user_addresses << UserAddress.new => Raise No Method Exception since it was alias with :as
118
120
  # User.addresses << UserAddress.new
119
121
  # --------------------------------------------
120
122
  # --------------------------------------------
@@ -175,6 +177,15 @@ module DataMapper
175
177
  remixable_key = Extlib::Inflection.demodulize(remixable_module.name).snake_case.to_sym
176
178
  populate_remixables_mapping(model, options.merge(:remixable_key => remixable_key))
177
179
 
180
+ # attach RemixerClassMethods and RemixerInstanceMethods to remixer if defined by remixee
181
+ if Object.full_const_defined? "#{remixable_module}::RemixerClassMethods"
182
+ extend Object.full_const_get("#{remixable_module}::RemixerClassMethods")
183
+ end
184
+
185
+ if Object.full_const_defined? "#{remixable_module}::RemixerInstanceMethods"
186
+ include Object.full_const_get("#{remixable_module}::RemixerInstanceMethods")
187
+ end
188
+
178
189
  #Create relationships between Remixer and remixed class
179
190
  if options[:other_model]
180
191
  # M:M Class-To-Class w/ Remixable Module as intermediate table
@@ -185,9 +196,6 @@ module DataMapper
185
196
  # has n and belongs_to (or One-To-Many)
186
197
  remix_one_to_many cardinality, model, options
187
198
  end
188
-
189
- #Add accessor alias
190
- attach_accessor(options) unless options[:as].nil?
191
199
  else
192
200
  DataMapper.logger.warn "#{__FILE__}:#{__LINE__} warning: already remixed constant #{options[:class_name]}"
193
201
  end
@@ -232,7 +240,6 @@ module DataMapper
232
240
  # belongs_to :bot
233
241
  # belongs_to :tag
234
242
  # end
235
-
236
243
  def enhance(remixable,remixable_model=nil, &block)
237
244
  # always use innermost singular snake_cased constant name
238
245
  remixable_name = remixable.to_s.singular.snake_case.to_sym
@@ -253,18 +260,6 @@ module DataMapper
253
260
 
254
261
  private
255
262
 
256
- # - attach_accessor
257
- # ==== Description
258
- # Creates additional alias for r/w accessor
259
- # ==== Parameters
260
- # options <Hash> options hash
261
- def attach_accessor(options)
262
- self.class_eval(<<-EOS, __FILE__, __LINE__ + 1)
263
- alias #{options[:as].to_sym} #{options[:table_name].to_sym}
264
- alias #{options[:as].to_sym}= #{options[:table_name].to_sym}=
265
- EOS
266
- end
267
-
268
263
  # - populate_remixables_mapping
269
264
  # ==== Description
270
265
  # Populates the Hash of remixables with information about the remixable
@@ -290,7 +285,7 @@ module DataMapper
290
285
  # model <Class> remixed model that 'self' is relating to
291
286
  # options <Hash> options hash
292
287
  def remix_one_to_many(cardinality, model, options)
293
- self.has cardinality, options[:table_name].intern
288
+ self.has cardinality, (options[:as] || options[:table_name]).to_sym, :class_name => model.name
294
289
  model.property Extlib::Inflection.foreign_key(self.name).intern, Integer, :nullable => false
295
290
  model.belongs_to Extlib::Inflection.tableize(self.name).intern
296
291
  end
@@ -311,7 +306,7 @@ module DataMapper
311
306
 
312
307
  # Is M:M between two different classes or the same class
313
308
  unless self.name == options[:other_model].name
314
- self.has cardinality, options[:table_name].intern
309
+ self.has cardinality, (options[:as] || options[:table_name]).to_sym, :class_name => model.name
315
310
  options[:other_model].has cardinality, options[:table_name].intern
316
311
 
317
312
  model.belongs_to Extlib::Inflection.tableize(self.name).intern
@@ -319,7 +314,7 @@ module DataMapper
319
314
  else
320
315
  raise Exception, "options[:via] must be specified when Remixing a module between two of the same class" unless options[:via]
321
316
 
322
- self.has cardinality, options[:table_name].intern
317
+ self.has cardinality, (options[:as] || options[:table_name]).to_sym, :class_name => model.name
323
318
  model.belongs_to Extlib::Inflection.tableize(self.name).intern
324
319
  model.belongs_to options[:via].intern, :class_name => options[:other_model].name, :child_key => ["#{options[:via]}_id".intern]
325
320
  end
@@ -350,6 +345,15 @@ module DataMapper
350
345
  model.property(prop.name, prop.type, prop.options)
351
346
  end
352
347
 
348
+ # attach remixed model access to RemixeeClassMethods and RemixeeInstanceMethods if defined
349
+ if Object.full_const_defined? "#{remixable}::RemixeeClassMethods"
350
+ model.send :extend, Object.full_const_get("#{remixable}::RemixeeClassMethods")
351
+ end
352
+
353
+ if Object.full_const_defined? "#{remixable}::RemixeeInstanceMethods"
354
+ model.send :include, Object.full_const_get("#{remixable}::RemixeeInstanceMethods")
355
+ end
356
+
353
357
  model
354
358
  end
355
359
 
@@ -358,7 +362,7 @@ module DataMapper
358
362
  # - RemixeeClassMethods
359
363
  # ==== Description
360
364
  # Methods available to any model that is :remixable
361
- module RemixeeClassMethods
365
+ module RemixeeClassMethods
362
366
  # - suffix
363
367
  # ==== Description
364
368
  # modifies the storage name suffix, which is by default based on the Remixable Module name
@@ -1,7 +1,7 @@
1
1
  module DataMapper
2
2
  module Is
3
3
  module Remixable
4
- VERSION = "0.9.7"
4
+ VERSION = "0.9.8"
5
5
  end
6
6
  end
7
7
  end
@@ -7,4 +7,5 @@ module Commentable
7
7
  property :id, Integer, :key => true, :serial => true
8
8
  property :comment, String
9
9
  property :created_at, DateTime
10
+
10
11
  end
@@ -6,4 +6,40 @@ module Image
6
6
  property :id, Integer, :key => true, :serial => true
7
7
  property :description, String
8
8
  property :path, String
9
+
10
+ # These methods will be available to the class remixing this module
11
+ # If 'User' remixes 'Images', these methods will be available to a User class
12
+ #
13
+ module RemixerClassMethods
14
+ def test_remixer_class_method
15
+ 'CLASS METHOD FOR REMIXER'
16
+ end
17
+ end
18
+
19
+ # These methods will be available to instantiated objects of the remixing this module
20
+ # If 'User' remixes 'Images', these methods will be available to a User object
21
+ #
22
+ module RemixerInstanceMethods
23
+ def test_remixer_instance_method
24
+ 'INSTANCE METHOD FOR REMIXER'
25
+ end
26
+ end
27
+
28
+ # These methods will be available to the Generated Remixed Class
29
+ # If 'User' remixes 'Images', these methods will be available to UserImage class
30
+ #
31
+ module RemixeeClassMethods
32
+ def test_remixee_class_method
33
+ 'CLASS METHOD FOR REMIXEE'
34
+ end
35
+ end
36
+
37
+ # These methods will be available to an instantiated Generated Remixed Class
38
+ # If 'User' remixes 'Images', these methods will be available to a UserImage object
39
+ #
40
+ module RemixeeInstanceMethods
41
+ def test_remixee_instance_method
42
+ 'INSTANCE METHOD FOR REMIXEE'
43
+ end
44
+ end
9
45
  end
@@ -33,7 +33,7 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
33
33
 
34
34
  it "should not allow enhancements of modules that aren't remixed" do
35
35
  lambda {
36
- User.enhance Image
36
+ User.enhance :images
37
37
  }.should raise_error
38
38
  end
39
39
 
@@ -135,7 +135,6 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
135
135
  it "should allow creating an accessor alias" do
136
136
  article = Article.new
137
137
  article.should respond_to("pics")
138
- article.should respond_to("article_images")
139
138
  end
140
139
 
141
140
  it "should copy properties from the Remixable Module to the Remixed Model" do
@@ -196,8 +195,10 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
196
195
  article.pics.path.should == image2.path
197
196
  end
198
197
 
198
+ # Example:
199
+ # Users are Commentable by many Users
200
+ #
199
201
  it "should allow M:M unary relationships through the Remixable Module" do
200
- #User => Commentable => User
201
202
  user = User.new
202
203
  user.first_name = "Tester"
203
204
  user2 = User.new
@@ -206,16 +207,20 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
206
207
  comment = UserComment.new
207
208
  comment.comment = "YOU SUCK!"
208
209
  comment.commentor = user2
209
- user.user_comments << comment
210
210
 
211
- user2.user_comments.length.should be(0)
211
+ user.comments << comment
212
+
213
+ user2.comments.length.should be(0)
212
214
 
213
215
  comment.commentor.first_name.should == "Testy"
214
- user.user_comments.length.should be(1)
216
+
217
+ user.comments.length.should be(1)
215
218
  end
216
219
 
220
+ # Example:
221
+ # Articles are Commentable by many Users
222
+ #
217
223
  it "should allow M:M relationships through the Remixable Module" do
218
- #Article => Commentable => User
219
224
  user = User.new
220
225
  article = Article.new
221
226
 
@@ -235,5 +240,89 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
235
240
  article.comments.first.should be(ac)
236
241
  user.article_comments.first.should be(ac)
237
242
  end
243
+
244
+ # Example:
245
+ # Remixable Image add functionality to any class that remixes it
246
+ # Image::RemixerClassMethods defines a method called 'total_images' that counts the total number of images for the class
247
+ # Image::RemixerInstanceMethods defines a method called 'most_viewed_image' that find the most viewed image for an object
248
+ #
249
+ # User.remixes n, :images
250
+ # User.total_images => count of all images owned by all users
251
+ # User.first.most_viewed_image => would return the most viewed image
252
+ #
253
+ it "should add a remixables' 'RemixerClassMethods' modules to the remixing class" do
254
+ Article.respond_to?(:test_remixer_class_method).should be(true)
255
+ Article.test_remixer_class_method.should == 'CLASS METHOD FOR REMIXER'
256
+ end
257
+
258
+ it "should add a remixables' 'RemixerInstanceMethods' modules to the remixing class" do
259
+ Article.new.respond_to?(:test_remixer_instance_method).should be(true)
260
+ Article.new.test_remixer_instance_method.should == 'INSTANCE METHOD FOR REMIXER'
261
+ end
262
+
263
+ # Example:
264
+ # Remixable Image add functionality to any class that remixes it
265
+ # Image::RemixeeClassMethods defines a method called 'damaged_files' would return a list of all images with invalid checksums (or whatev)
266
+ # Image::RemixeeInstanceMethods defines a method called 'mime_type' that find the mime type of the particular image
267
+ #
268
+ # Article.remixes n, :images
269
+ # # => yields and ArticleImage Class
270
+ # ArticleImage.damaged_files => list of all images with invalid checksums
271
+ # ArticleImage.first.mime_type => would return the mime type of that image
272
+ #
273
+ it "should add a remixables' 'RemixeeClassMethods' modules to the generated remixed class" do
274
+ ArticleImage.respond_to?(:test_remixee_class_method).should be(true)
275
+ ArticleImage.test_remixee_class_method.should == 'CLASS METHOD FOR REMIXEE'
276
+ end
277
+
278
+ it "should add a remixables' 'RemixeeInstanceMethods' modules to the generated remixed class" do
279
+ ArticleImage.new.respond_to?(:test_remixee_instance_method).should be(true)
280
+ ArticleImage.new.test_remixee_instance_method.should == 'INSTANCE METHOD FOR REMIXEE'
281
+ end
282
+
283
+ # Example:
284
+ # User.remixes n, :images, :as => "pics"
285
+ # User.first.pics would be the acessor for images
286
+ # User.first.user_images should raise method not found
287
+ #
288
+ it 'should remove the original attribute accessor when attaching an optional one' do
289
+ Article.new.respond_to?(:pics).should be(true)
290
+ User.new.respond_to?(:user_addresses).should be(true)
291
+ end
292
+
293
+ # Currently:
294
+ # Submission.remixes n, :comments
295
+ # SubmissionComment.new.user = User.first => throws exception, accessor name is 'users' instead
296
+ #
297
+ # Example:
298
+ # User.remix 1, :images
299
+ # # => User.image & UserImage.user
300
+ #
301
+ # User.remix n, :images
302
+ # # => User.images & UserImage.user
303
+ #
304
+ # User.remix n, :comments, :for => 'User', :via => 'commentor'
305
+ # # => User.comments & UserComment.user & UserComment.commentor
306
+ #
307
+ it 'should pluralize accessor names with respect to cardinality' do
308
+ pending
309
+ end
310
+
311
+ # Note:
312
+ # Currently the :via flag allows one to specify another name for the field, but it always appends _id
313
+ #
314
+ # Example:
315
+ # User w/ PK being 'login_name'
316
+ # User.remixes n, :comments, :for => 'User', :via => 'commentor'
317
+ #
318
+ # Comment Table:
319
+ # * id
320
+ # * text
321
+ # * user_login_name
322
+ # * commentor_id #=> should be able to specify it to be commentor_login_name
323
+ #
324
+ it 'should allow the primary and child field names to be specified while remixing' do
325
+ pending
326
+ end
238
327
  end
239
328
  end
@@ -3,7 +3,7 @@ gem 'rspec', '>=1.1.3'
3
3
  require 'spec'
4
4
  require 'pathname'
5
5
  require Pathname(__FILE__).dirname.expand_path.parent + 'lib/dm-is-remixable'
6
- require "ruby-debug"
6
+
7
7
  def load_driver(name, default_uri)
8
8
  return false if ENV['ADAPTER'] != name.to_s
9
9
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-is-remixable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cory O'Daniel
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-11-18 00:00:00 -08:00
12
+ date: 2008-12-09 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -18,19 +18,9 @@ dependencies:
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
20
20
  requirements:
21
- - - "="
21
+ - - ~>
22
22
  - !ruby/object:Gem::Version
23
- version: 0.9.7
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: hoe
27
- type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 1.8.2
23
+ version: 0.9.8
34
24
  version:
35
25
  description: dm-is-remixable allow you to create reusable data functionality
36
26
  email:
@@ -69,7 +59,7 @@ files:
69
59
  - spec/spec.opts
70
60
  - spec/spec_helper.rb
71
61
  has_rdoc: true
72
- homepage: http://github.com/sam/dm-more/tree/master/dm-remixes
62
+ homepage: http://github.com/sam/dm-more/tree/master/dm-is-remixable
73
63
  post_install_message:
74
64
  rdoc_options:
75
65
  - --main