select_extra_columns 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,12 +1,17 @@
1
- 2010-04-11
1
+ 2010-03-11
2
+ ==========
3
+ * Added support for `find_by_sql`.
4
+ * Exposed `find_extra_columns_class` method.
5
+
6
+ 2010-03-10
2
7
  ==========
3
8
  * Added support for sharing `extra_columns` definition across finders
4
9
 
5
- 2010-04-09
10
+ 2010-03-09
6
11
  ==========
7
12
  * Changed cloning to inheritance.
8
13
 
9
- 2010-04-09
14
+ 2010-03-09
10
15
  ==========
11
16
  * Added stricter validation for :extra_columns input.
12
17
 
@@ -60,7 +60,16 @@ Getting Started
60
60
  users.first.street # returns the street
61
61
  users.first.active # returns true/false
62
62
 
63
-
63
+ users = User.find_by_sql("SELECT A.*, count(B.id) as post_count
64
+ FROM users A, posts B
65
+ WHERE A.id = B.user_id AND B.ptype = 'public'
66
+ GROUP BY A.id
67
+ UNION
68
+ SELECT A.*, count(B.id) as post_count
69
+ FROM users A, customer_posts B
70
+ WHERE A.id = B.user_id AND B.ptype = 'private'
71
+ GROUP BY A.id",
72
+ :extra_columns => :post_count)
64
73
  Dynamically added column fields are read only. Any value set to these fields are ignored during save.
65
74
 
66
75
  user = User.first(:joins => :address, :select => "*, addresses.street as street",
@@ -127,12 +136,12 @@ You can declare the extra columns in your model and use them across finders
127
136
 
128
137
  Now `:user_info` and `:post_info` can be used in finders.
129
138
 
130
- users = User.find(:all, :joins => :posts, :select => "users.*, count(posts.id) as post_count, max(posts.created_at) as last_post_at",
131
- :extra_columns => :post_info)
132
-
133
- user = User.first(:joins => :address, :select => "users.*, addresses.street as street, addresses.city as city",
134
- :extra_columns => :address_info )
139
+ users = User.all(:joins => :posts, :extra_columns => :post_info
140
+ :select => "users.*, count(posts.id) as post_count, max(posts.created_at) as last_post_at")
135
141
 
142
+ user = User.first(:joins => :address, :extra_columns => :address_info,
143
+ :select => "users.*, addresses.street as street, addresses.city as city")
144
+
136
145
  ## Naming conflicts
137
146
  When a symbol/string is passed as input to `:extra_columns` option, the finder uses cached `extra_columns` definition by the given name.
138
147
  If no definition is found, then finder creates a new `extra_columns` definition with the input as a column.
@@ -143,10 +152,13 @@ If no definition is found, then finder creates a new `extra_columns` definition
143
152
  extra_columns :post_count, [:post_count, :integer], :last_post_at => :datetime
144
153
  end
145
154
 
146
- The finder call below, `post_count` maps on to a column in the select list and a `extra_columns` definition. Finder chooses the `extra_columns` definition.
147
- users = User.find(:all, :joins => :posts, :select => "users.*, count(posts.id) as post_count, max(posts.created_at) as last_post_at",
155
+ In the `finder` call below, `post_count` maps on to a column name and a `extra_columns` definition name. Finder chooses the `extra_columns` definition.
156
+ users = User.all(:joins => :posts, :select => "users.*, count(posts.id) as post_count, max(posts.created_at) as last_post_at",
148
157
  :extra_columns => :post_count)
149
158
 
159
+ ## Accessing the extra column model
160
+ The gem creates and caches a model for every unique `extra_column` configuration. This model can be accessed using the `find_extra_columns_class` method.
161
+ User.find_extra_columns_class(:post_count).find_by_sql("")
150
162
 
151
163
  ## Valid data types for column fields in `:extra_columns`
152
164
  :binary
@@ -5,38 +5,71 @@ module SelectExtraColumns
5
5
  end
6
6
 
7
7
  module ClassMethods
8
- def self.extended(active_record_class)
8
+ def self.extended(active_record_class) #:nodoc:
9
9
  class << active_record_class
10
10
  alias_method_chain :find_every, :extra_columns
11
+ alias_method_chain :find_by_sql,:extra_columns
11
12
  end
12
13
  active_record_class.class_inheritable_array(:klasses_with_extra_columns)
13
14
  active_record_class.klasses_with_extra_columns ||= []
14
15
  end
15
16
 
16
- def find_every_with_extra_columns options
17
+ def find_every_with_extra_columns options #:nodoc:
17
18
  extra_columns = options.delete(:extra_columns)
18
- return find_every_without_extra_columns options if extra_columns.nil?
19
- klass_with_extra_columns(extra_columns).send(:find_every, options)
19
+ return find_every_without_extra_columns(options) if extra_columns.nil?
20
+ find_or_create_extra_columns_class(extra_columns).send(:find_every, options)
20
21
  end
21
22
 
22
- def validate_find_options(options)
23
+ def find_by_sql_with_extra_columns sql, options={}
24
+ extra_columns = options.delete(:extra_columns)
25
+ return find_by_sql_without_extra_columns(sql) if extra_columns.nil?
26
+ find_or_create_extra_columns_class(extra_columns).send(:find_by_sql, sql)
27
+ end
28
+
29
+ def validate_find_options(options) #:nodoc:
23
30
  extra_columns = options.delete(:extra_columns)
24
31
  super
25
32
  ensure
26
33
  options[:extra_columns]= extra_columns if extra_columns
27
34
  end
28
35
 
29
- def klass_with_extra_columns extra_columns
36
+ def find_or_create_extra_columns_class extra_columns #:nodoc:
30
37
  # look for the class in the cache.
31
- (
32
- [String, Symbol].include?(extra_columns.class) ?
33
- self.klasses_with_extra_columns.find{|k| k.extra_columns_key == extra_columns.to_s} :
34
- self.klasses_with_extra_columns.find{|k| k.extra_columns == extra_columns}
35
- ) or extra_columns_class(extra_columns)
38
+ find_extra_columns_class(extra_columns) || create_extra_columns_class(extra_columns)
36
39
  end
37
40
 
38
- def extra_columns_class extra_columns, extra_columns_key=nil
39
- extra_column_definitions = prepare_extra_column_definitions(extra_columns)
41
+ # Returns cached extra_column model. The argument can take two forms:
42
+ #
43
+ # * extra_column key - Key used to register the model using the call to extra_columns
44
+ # * extra_column key - Definition used in a prior query.
45
+ #
46
+ # ==== Examples
47
+ # class Person < ActiveRecord::Base
48
+ # select_extra_column
49
+ # extra_column :address_info, :street, :city, :zip
50
+ # end
51
+ # klass = Person.find_extra_columns_class(:address_info)
52
+ # Person.find(:joins => :address, :select => "people.*, addresses.street, addresses.city, addresses.zip",
53
+ # :extra_columns = [:street, :city, :zip])
54
+ # ...
55
+ # ...
56
+ # klass = Person.find_extra_columns_class([:street, :city, :zip])
57
+ # klass.find_by_sql("..")
58
+ def find_extra_columns_class extra_columns
59
+ # look for the class in the cache.
60
+ [String, Symbol].include?(extra_columns.class) ?
61
+ self.klasses_with_extra_columns.find{|k| k.extra_columns_key == extra_columns.to_s} :
62
+ self.klasses_with_extra_columns.find{|k| k.extra_columns == extra_columns}
63
+ end
64
+
65
+ # Creates and caches an extra_column model.
66
+ #
67
+ def extra_columns extra_columns_key, *args
68
+ create_extra_columns_class args.concat(args.extract_options!.to_a), extra_columns_key
69
+ end
70
+
71
+ def create_extra_columns_class extra_columns, extra_columns_key=nil #:nodoc:
72
+ extra_column_definitions = create_extra_columns(extra_columns)
40
73
  return self if extra_column_definitions.empty?
41
74
  read_only_attrs = extra_column_definitions.collect{|cd| ":#{cd.name}" }.join(",")
42
75
  klass_name = "#{self.name}#{Time.now.to_i}#{extra_columns.hash.abs}"
@@ -57,11 +90,7 @@ module SelectExtraColumns
57
90
  end
58
91
  end
59
92
 
60
- def extra_columns extra_columns_key, *args
61
- extra_columns_class args.concat(args.extract_options!.to_a), extra_columns_key
62
- end
63
-
64
- def prepare_extra_column_definitions extra_columns
93
+ def create_extra_columns extra_columns #:nodoc:
65
94
  extra_columns = [extra_columns] if extra_columns.is_a?(Symbol) or extra_columns.is_a?(String)
66
95
  extra_columns = extra_columns.to_a if extra_columns.is_a?(Hash)
67
96
  return [] unless extra_columns.is_a?(Array)
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 6
9
- version: 0.0.6
8
+ - 7
9
+ version: 0.0.7
10
10
  platform: ruby
11
11
  authors:
12
12
  - Kandada Boggu
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-10 00:00:00 -08:00
17
+ date: 2010-03-11 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies: []
20
20