has 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/has/has.rb +87 -0
  2. metadata +2 -1
data/lib/has/has.rb ADDED
@@ -0,0 +1,87 @@
1
+ class << ActiveRecord::Base
2
+
3
+ def has(*xs)
4
+ opt = xs.extract_options!
5
+ name = xs.pop if xs.last.kind_of?(Symbol)
6
+
7
+ argument_name_for = { Range => :range, Fixnum => :count }
8
+ while x = xs.shift
9
+ opt[argument_name_for[x.class]] = x
10
+ end
11
+
12
+ if key = (opt.keys & [ :attributed, :nested ]).first
13
+ send "has_#{key}", opt.delete(key), opt
14
+ else
15
+ has_associated name, opt
16
+ end
17
+ end
18
+
19
+ def has_attributed(name, opt = {})
20
+ opt[:include] = true if opt[:include].nil?
21
+ opt[:conditions] ||= {}
22
+ opt[:conditions][:attribute_name] = name.to_s
23
+ opt[:orderable] = :attribute_ordinal if opt[:orderable] == true
24
+ opt[:as] = :attributable
25
+
26
+ has_nested name, opt
27
+ end
28
+
29
+ def has_nested(name, opt = {})
30
+ opt[:dependent] = :destroy if opt[:dependent].nil?
31
+ allow_destroy = opt[:dependent] == :destroy
32
+ default_include = opt.delete(:include) == true
33
+ if orderable = opt.delete(:orderable)
34
+ opt[:order] = orderable
35
+ end
36
+
37
+ has_associated name, opt
38
+
39
+ accepts_nested_attributes_for name, allow_destroy: allow_destroy
40
+ default_scope includes(name) if default_include
41
+
42
+ if orderable
43
+ setter = instance_method setter_name = "#{name}_attributes="
44
+
45
+ define_method setter_name do |attr|
46
+ attr = attr.values if attr.is_a? Hash
47
+ attr.each_with_index{ |e, i| e[orderable] = i }
48
+ setter.bind(self).call attr
49
+ send(name).sort_by! &orderable
50
+ end
51
+
52
+ before_save do
53
+ send(name).each_with_index{ |e, i| e[orderable] = i }
54
+ end
55
+ end
56
+ end
57
+
58
+ def has_associated(name, opt = {})
59
+ range = opt.delete :range
60
+ count = opt.delete :count
61
+ inf = 1.0/0
62
+ min = opt.keys.find{ |k| Integer === k }
63
+ max = opt.delete min if min
64
+ max = inf if max == :many
65
+
66
+ range ||= if count then count .. count
67
+ elsif min && max then min .. max
68
+ else
69
+ name_s = name.to_s
70
+ is_plural = name_s.pluralize == name_s
71
+ is_singular = name_s.singularize == name_s
72
+
73
+ raise ArgumentError.new "`has` can't determine whether \"#{name_s}\" is plural or singular. Please supply a count or range, or define an inflection." if is_plural == is_singular
74
+
75
+ 0 .. (is_plural ? inf : 1)
76
+ end
77
+
78
+ if range.end == 1 then has_one name, opt
79
+ else
80
+ opt[:limit] = range.end unless range.end == inf
81
+ has_many name, opt
82
+ end
83
+
84
+ validates_presence_of name if range.begin > 0
85
+ end
86
+
87
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: has
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.0.1
5
+ version: 1.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Alex Goldsmith
@@ -34,6 +34,7 @@ extensions: []
34
34
  extra_rdoc_files: []
35
35
 
36
36
  files:
37
+ - lib/has/has.rb
37
38
  - lib/has.rb
38
39
  - Rakefile
39
40
  - README.rdoc