itrigga-param_fu 0.4.1 → 0.4.2

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.4.2
@@ -57,10 +57,12 @@ module Trigga
57
57
  end
58
58
 
59
59
  # Give this a hash per model in the format:
60
+ #
60
61
  # Model class => { param_name => { :operator=>(db operator - defaults to '='),
61
62
  # => :field_name=>(field_name in the database - defaults to param_name)
62
63
  # => }
63
64
  # => }
65
+ #
64
66
  # and it will return an ActiveRecord finder :conditions clause using any params which are present in the given :params
65
67
  # e.g. if you have params = { :created_date_from=>'2011-10-09 00:01:02', :status=>'A', :click_url=>'items.html' }
66
68
  # then calling:
@@ -78,8 +80,41 @@ module Trigga
78
80
  #
79
81
  # [ 'clicks.request_path like (?) AND clicks.status = ? AND clicks.created_date_from >= ?', '%items.html%', 'A', '2011-10-09 00:01:02' ]
80
82
  #
83
+ #
81
84
  # It will ignore any criteria given which are NOT in the given :params hash
82
85
  #
86
+ # Table Names
87
+ # ===========
88
+ # By default each field given in a model class key is automatically scoped by the table name - e.g.
89
+ #
90
+ # Person => { :status=>{} }
91
+ #
92
+ # results in a where clause of
93
+ #
94
+ # 'people.status = (?)'
95
+ #
96
+ # Sometimes you need to scope a field by another table name - e.g. when you have a joined table, or an aliased table
97
+ # If your fieldname contains a dot ('.') it will NOT be scoped by the table name, it will be left as given
98
+ #
99
+ # e.g.
100
+ #
101
+ # Writer => { :interested_in => { :operator => 'LIKE', :field_name=>['writer_interests.interest_notes'] }}
102
+ #
103
+ # gives
104
+ #
105
+ # 'writer_interests.interest_notes LIKE (?)'
106
+ #
107
+ # ORs
108
+ # ===
109
+ # You can combine two different fields into an OR on the same value by passing :fieldname=>[ "fieldname_1", "fieldname_2" ]
110
+ # e.g.
111
+ #
112
+ # Click => { :click_url_pattern=> {:operator=>"like", :field_name=>['request_path', 'http_referer']}}
113
+ #
114
+ # will generate:
115
+ #
116
+ # ['( clicks.request_path LIKE (?) OR clicks.http_referrer LIKE (?) )']
117
+ #
83
118
  def params_to_conditions( opts={} )
84
119
  require_param(opts, :params, :models)
85
120
 
@@ -96,7 +131,8 @@ module Trigga
96
131
 
97
132
  def model_conditions( opts, model_class, field_defs )
98
133
  h = {:where=>[], :values=>[]}
99
- field_defs.each{ |field_name, definition|
134
+
135
+ field_defs.each{ |field_name, definition|
100
136
  parsed_field_def = parse_field_definition( opts, model_class, field_name, definition )
101
137
  h[:where] += parsed_field_def[:where]
102
138
  h[:values] += parsed_field_def[:values]
@@ -108,12 +144,20 @@ module Trigga
108
144
  c = {:where=>[], :values=>[]}
109
145
  if opts[param_name]
110
146
  unless opts[param_name].to_s.empty?
111
- c[:where] << "( #{model_class.table_name}.#{definition[:field_name] || param_name.to_s} #{definition[:operator] || '='} (?) )"
147
+ ors = Array(definition[:field_name] || param_name.to_s).map{ |field| scoped_field_name( model_class, field ) + " " + (definition[:operator] || '=') + " (?)" }
148
+
149
+ clause = "( " + ors.join(' OR ') + " )"
150
+ # "( #{ scoped_field_name( model_class, (definition[:field_name] || param_name.to_s) ) } #{definition[:operator] || '='} (?) )"
151
+ c[:where] << clause
112
152
  c[:values] << ( definition[:operator] =~ /\blike\b/i ? opts[param_name].to_active_record_condition : opts[param_name] )
113
153
  end
114
154
  end
115
155
  c
116
156
  end
157
+
158
+ def scoped_field_name( model_class, field_name )
159
+ field_name.include?('.') ? field_name : "#{model_class.table_name}.#{field_name}"
160
+ end
117
161
  end
118
162
  end
119
163
  end
@@ -188,32 +188,72 @@ describe ::Trigga::ParamFu do
188
188
  @inside_the_brackets = Tester.parse_field_definition( @params, @model_class, @param_name, @definition )[:where][0].gsub(/^\s*\((.*)\)\s*$/, '\1')
189
189
  end
190
190
 
191
- it "should start with the model_class's table name as a scope" do
192
- @inside_the_brackets.should =~ /\s*model_class_table_name\..*/
191
+ it "should call scoped_field_name " do
192
+ Tester.should_receive(:scoped_field_name).and_return('blart')
193
+ Tester.parse_field_definition( @params, @model_class, @param_name, @definition )
193
194
  end
194
-
195
- context "When the definition has a :fieldname" do
196
- before(:each) do
197
- @definition[:field_name] = 'field_name'
198
- @inside_the_brackets = Tester.parse_field_definition( @params, @model_class, @param_name, @definition )[:where][0].gsub(/^\s*\((.*)\)\s*$/, '\1')
195
+
196
+ describe "scoped_field_name args" do
197
+ it "should start with the model class" do
198
+ Tester.should_receive(:scoped_field_name) do |args|
199
+ args[0].should == @model_class
200
+ 'blart'
201
+ end
202
+ Tester.parse_field_definition( @params, @model_class, @param_name, @definition )
199
203
  end
204
+
205
+ context "When the definition has a :fieldname" do
206
+ before(:each) do
207
+ @definition[:field_name] = 'field_name'
208
+ end
200
209
 
201
- it "should use the :fieldname" do
202
- @inside_the_brackets.should =~ /\s*[^\.]+\.field_name.*/
210
+ it "should pass the given :field_name as the second arg" do
211
+ Tester.should_receive(:scoped_field_name) do |args|
212
+ args[1].should == 'field_name'
213
+ 'blart'
214
+ end
215
+ Tester.parse_field_definition( @params, @model_class, @param_name, @definition )
216
+ end
203
217
  end
204
- end
205
-
206
- context "When the definition has no :fieldname" do
207
- before(:each) do
208
- @definition[:field_name] = nil
209
- @inside_the_brackets = Tester.parse_field_definition( @params, @model_class, @param_name, @definition )[:where][0].gsub(/^\s*\((.*)\)\s*$/, '\1')
218
+
219
+ context "When the definition has no :fieldname" do
220
+ before(:each) do
221
+ @definition[:field_name] = nil
222
+ end
223
+
224
+ it "should pass the given param_name converted to a string as the second arg" do
225
+ Tester.should_receive(:scoped_field_name) do |args|
226
+ args[1].should == 'param_1'
227
+ 'blart'
228
+ end
229
+ Tester.parse_field_definition( @params, @model_class, @param_name, @definition )
230
+ end
210
231
  end
232
+
233
+ context "when the definitions fieldname is an array" do
234
+ before(:each) do
235
+ @definition[:field_name] = ["field_name_1", "other_table.field_name_2"]
236
+ end
211
237
 
212
- it "should use the given param_name converted to a string as the field name" do
213
- @inside_the_brackets.should =~ /\s*[^\.]+\.param_1.*/
238
+ it "should call scoped_field_name with each element" do
239
+ Tester.should_receive(:scoped_field_name) do |args|
240
+ args[1].should == 'field_name_1'
241
+ 'blart'
242
+ end
243
+ Tester.should_receive(:scoped_field_name) do |args|
244
+ args[1].should == 'other_table.field_name_2'
245
+ 'blart'
246
+ end
247
+ Tester.parse_field_definition( @params, @model_class, @param_name, @definition )
248
+ end
249
+
250
+ it "should join the fieldname conditions together with OR" do
251
+ Tester.parse_field_definition( @params, @model_class, @param_name, @definition )[:where][0].should == "( model_class_table_name.field_name_1 = (?) OR other_table.field_name_2 = (?) )"
252
+ end
214
253
  end
254
+
215
255
  end
216
-
256
+
217
257
  context "When the definition has a :operator" do
218
258
  before(:each) do
219
259
  @definition[:operator] = 'my_operator'
@@ -275,6 +315,28 @@ describe ::Trigga::ParamFu do
275
315
  end
276
316
  end
277
317
 
318
+ describe "scoped_field_name" do
319
+ before do
320
+ @model_class = mock("model class")
321
+ @model_class.stub!(:table_name).and_return( 'model_class_table_name' )
322
+ end
323
+
324
+ context "when the given field_name contains a ." do
325
+ it "should just return the given field_name" do
326
+ Tester.scoped_field_name(@model_class, 'blart.flange').should == 'blart.flange'
327
+ end
328
+ end
329
+ context "when the given field_name does not contain a ." do
330
+ it "should call table_name on the model_class" do
331
+ @model_class.should_receive(:table_name).and_return( 'model_class_table_name' )
332
+ Tester.scoped_field_name(@model_class, 'blart')
333
+ end
334
+ it "should return the given field_name" do
335
+ Tester.scoped_field_name(@model_class, 'flange').should == 'model_class_table_name.flange'
336
+ end
337
+ end
338
+ end
339
+
278
340
  describe "model_conditions" do
279
341
  before(:each) do
280
342
  @params = { :param_1 => 'param_1 value' }
@@ -320,14 +382,15 @@ describe ::Trigga::ParamFu do
320
382
  end
321
383
 
322
384
  it "should pass each field_name" do
323
- Tester.should_receive(:parse_field_definition) do |args|
324
- args[2].should == :field_name_1
325
- @mock_parsed_field_def_1
326
- end
385
+
327
386
  Tester.should_receive(:parse_field_definition) do |args|
328
387
  args[2].should == :field_name_2
329
388
  @mock_parsed_field_def_2
330
389
  end
390
+ Tester.should_receive(:parse_field_definition) do |args|
391
+ args[2].should == :field_name_1
392
+ @mock_parsed_field_def_1
393
+ end
331
394
  Tester.model_conditions( @params, @model_class, @definitions )
332
395
  end
333
396
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itrigga-param_fu
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 4
9
- - 1
10
- version: 0.4.1
9
+ - 2
10
+ version: 0.4.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Al Davidson
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-11-18 00:00:00 +00:00
19
+ date: 2011-12-02 00:00:00 +00:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency