Class: Railscheck::Test::RailsDeprecations

Inherits:
Railscheck::TestCase show all
Defined in:
lib/test/tc_rails_deprecations.rb

Instance Method Summary collapse

Methods inherited from Railscheck::TestCase

#default_test

Instance Method Details

#test_deprecationsObject

Adapted from code by Mislav Marohnić (pastie.caboo.se/private/krcevozww61drdeza13e3a) merged with code from deprecated plugin by Geoffrey Grosenbach (topfunky.net/svn/plugins/deprecated/) and added my own file deprecation support, simplified reporting, a version-specification and a explicit RAILS-ROOT etc.

TODO: Move yaml specifications into sperate file (regular expressions will have to be updated).



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/test/tc_rails_deprecations.rb', line 13

def test_deprecations      
  specs = YAML::load <<YML
  rhtml:
    pattern: '\\.rhtml'
    where: filename  
    info: '*.rhtml file extensions are deprecated in favor of *.erb'
    solution: 'Rename your rhtml files'
    version: 2.0

  rxml:
    pattern: '\\.rxml'
    where: filename
    info: '*.rxml file extensions are deprecated in favor of *.builder'
    solution: 'Rename your rxml files'
    version: 2.0

  params instance:
    pattern: '@params\\b'
    where: controllers
    info: 'Build-in instance variables has been removed in favor of accessors'
    solution: 'Use params[] instead'
    version: 1.1

  session instance:
    pattern: '@session\\b'
    where: controllers
    info: 'Build-in instance variables has been removed in favor of accessors'
    solution: 'Use session[] instead'
    version: 1.1

  flash instance:
    pattern: '@flash\\b'
    where: controllers
    info: 'Build-in instance variables has been removed in favor of accessors'
    solution: 'Use flash[] instead'
    version: 1.1

  request instance:
    pattern: '@request\\b'
    where: controllers
    info: 'Build-in instance variables has been removed in favor of accessors'
    solution: 'Use request[] instead'
    version: 1.1

  env instance:
    pattern: '@env\\b'
    where: controllers
    info: 'Build-in instance variables has been removed in favor of accessors'
    solution: 'Use env[] instead'
    version: 1.1

  render partial:
    pattern: '\\brender_partial\\b'
    where: controllers
    info: 'Similar render methods has been combined'
    solution: 'Use render :partial instead'
    version: 1.1

  component:
    pattern: 'components\\b'
    where: filename
    info: 'Use of components are frowned upon'
    version: 1.1            

  start_form_tag:
    pattern: 'start_form_tag\\b'
    where: views
    info: 'start_form_tag has been removed'
    solution: 'Use form_for instead'
    version: 1.1            

  start_form_tag:
    pattern: 'end_form_tag\\b'
    where: views
    info: 'end_form_tag has been removed'
    solution: 'Use form_for instead'
    version: 1.1

  post option:
    pattern: ':post\\s*=>\\s*true\\b'
    info: 'post option has been deprecated'
    solution: 'Use :method => :post instead'
    version: 1.1

  breakpoint server:
    pattern: '\\bbreakpoint_server\\b'
    where: config
    info: 'The configuration option has been removed in favor of the better ruby-debug library.'
    gem: ruby-debug
    solution: 'Remove the line(s) from configuration since the setting has no effect anymore.  Instead, start `script/server` with the "-u" or "--debugger" option (or "-h" to see all the options).'
    changeset: 6627
    version: 2.0

  with_scope:
    pattern: '[A-Z]\\w+\\.with_scope\\b'
    info: 'This class method has been declared private to model classes.'
    solution: "Don't use it directly.  You can only use it internally from the model class itself."
    changeset: 6909
    version: 2.0
    
  singular resources:
    pattern: "\\\\.resource\\\\s+[:\\"'](\\w+)"
    eval: "File.exist?('app/controllers/' + $1 + '_controller.rb') and line !~ /:controller\\\\b/"
    where: routes
    info: "Singular resources map to pluralized controllers now (ie. map_resource(:post) maps to PostsController)."
    solution: "Rename your singular controller(s) to plural or use the :controller option in `map.resource` to override the controller name it maps to."
    changeset: 6922
    version: 2.0
    
  pagination:
    pattern: '[^.\\w](paginate|(?:find|count)_collection_for_pagination|pagination_links(?:_each)?)\\b'
    where: controllers, views
    changeset: 6992
    info: "Pagination has been extracted from Rails core."
    solution: "Alternative: you can replace your pagination calls with will_paginate (find it on http://rock.errtheblog.com/)."
    plugin: svn://errtheblog.com/svn/plugins/classic_pagination
    version: 2.0
    
  push_with_attributes:
    pattern: '\\.push_with_attributes\\b'
    info: This method on associations has been removed from Rails.
    solution: "If you need attributes on associations, use has_many :through."
    changeset: 6997
    version: 2.0
    
  find_first or find_all:
    pattern: '\\b(find_first|[A-Z]\\w+\\.find_all)\\b'
    where: models, controllers
    info: "AR::Base `find_first` and `find_all` class methods have been removed.  (If you're in fact using `find_all` method of Enumerable, ignore this warning.)"
    solution: "Use `find(:first)` or `find(:all)`."
    changeset: 6998
    version: 2.0
    
  Hash.create_from_xml:
    pattern: '\\bHash.create_from_xml\\b'
    info: "`Hash.create_from_xml` has been renamed to `from_xml`."
    changeset: 7085
    version: 2.0
    
  nested resource named routes:
    pattern: '\\b\\w+_(new|edit)_\\w+_(url|path)\\b'
    where: controllers, views
    info: "Nested resource named routes are now prefixed by their action name."
    solution: "Rename your calls to such named routes from ie. 'group_new_user_path' to 'new_group_user_path'.  Same applies for 'edit' paths."
    changeset: 7138
    version: 2.0
    
  belongs_to foreign key assumption:
    pattern: '\\bbelongs_to\\b.+:class_name\\b'
    eval: 'line !~ /:foreign_key\\b/'
    where: models
    info: "The foreign key name is no longer inferred from the explicit class name, but from the association name."
    solution: "Make sure the foreign key for your association is in the form of '{association_name}_id'.  (See the changeset for an example)."
    changeset: 7188
    version: 2.0
    
  old association dependencies:
    pattern: ':dependent\\s*=>\\s*true|:exclusively_dependent\\b'
    where: models
    info: "Specifying dependencies in associations has a new form and the old API has been removed."
    solution: "Change ':dependent => true' to ':dependent => :destroy' and ':exclusively_dependent' to ':dependent => :delete_all'."
    changeset: 7402
    version: 2.0
    
  old render methods:
    pattern: '\\brender_(action|with(out)?_layout|file|text|template)\\b'
    where: controllers
    info: "The old `render_{something}` API has been removed."
    solution: "Change `render_action` to `render :action`, `render_text` to `render :text` (and so on) in your controllers."
    changeset: 7403
    version: 2.0
    
  template root:
    pattern: '\\btemplate_root\\b'
    info: "`template_root` has been dropped in favor of `view_paths` array."
    solution: 'Replace `template_root = "some/dir"` with `view_paths = "some/dir"`.'
    changeset: 7426
    version: 2.0
    
  expire matched fragments:
    pattern: '\\bexpire_matched_fragments\\b'
    where: controllers
    info: "`expire_matched_fragments` has been superseded by `expire_fragment`."
    solution: "Simply call `expire_fragment` with a regular expression."
    changeset: 7427
    version: 2.0
    
  expire matched fragments:
    pattern: '\\bkeep_flash\\b'
    where: controllers
    info: "`keep flash` has been superseded by `flash.keep`."
    changeset: 7428
    version: 2.0
    
  dynamic scaffold:
    pattern: '\\bscaffold\\b'
    where: controllers
    plugin: scaffolding
    info: "Dynamic scaffolding has gone the way of the dinosaurs."
    solution: "Don't use it.  Use the 'scaffold' generator to generate scaffolding for RESTful resources."
    changeset: 7429
    version: 2.0
    
  image tag without extension:
    pattern: "\\\\bimage_tag\\s*(\\(\\s*)?('[^'.]+'|\\"[^\\".]+\\")"
    where: views
    info: ".png is no longer the default extension for images."
    solution: "Explicitly set the image extension when using `image_tag`: instead of just `image_tag 'logo'`, use 'logo.png'."
    changeset: 7432
    version: 2.0
    
  cookie:
    pattern: ^\\s*cookie\\b
    where: controllers
    info: "The `cookie` writer method was removed from controllers."
    solution: "Use `cookies[name] = value` instead."
    changeset: 7434
    version: 2.0
    
  javascript in-place editor:
    pattern: \\b(in_place_editor_field|in_place_edit_for)\\b
    where: views, controllers
    plugin: in_place_editing
    info: "The in-place editor has been extracted from Rails core."
    changeset: 7442
    version: 2.0
    
  javascript autocompleter:
    pattern: \\b(auto_complete_field|auto_complete_for)\\b
    where: views, controllers
    plugin: auto_complete
    info: "The autocompleter has been extracted from Rails core."
    changeset: 7450
    version: 2.0
    
  acts_as_list:
    pattern: \\bacts_as_list\\b
    where: models
    plugin: acts_as_list
    info: "acts_as_list has been extracted from Rails core."
    changeset: 7444
    version: 2.0
    
  acts_as_nested_set:
    pattern: \\bacts_as_nested_set\\b
    where: models
    plugin: acts_as_nested_set
    info: "acts_as_nested_set has been extracted from Rails core."
    changeset: 7453
    version: 2.0
    
  acts_as_tree:
    pattern: \\bacts_as_tree\\b
    where: models
    plugin: acts_as_tree
    info: "acts_as_tree has been extracted from Rails core."
    changeset: 7454
    version: 2.0
    
  reloadable:
    pattern: \\binclude\\s+Reloadable\\b
    info: "Reloadable module is removed from Rails."
    solution: "Don't include the module anymore. Dependencies code is smart enough to reload classes if they're not in 'load_once' paths."
    changeset: 7473
    version: 2.0
YML
   
  for props in specs.values
    next unless props['pattern']
    props['pattern'] = Regexp.new props['pattern']
  end
  
  files = (Dir["#{RAILS_ROOT}/{app,config,db/migrate,lib,test}/**/*.rb"] + Dir["#{RAILS_ROOT}/app/views/**/*.{rhtml,rxml,erb,builder,haml}"]).sort
  files -= ["#{RAILS_ROOT}/config/boot.rb"]
  files -= version_control_excludes

  plugins = Dir["#{RAILS_ROOT}/vendor/plugins/*"].map{ |p| File.basename p }.sort

  files.each do |filename|
    #puts "Checking "+filename
    for props in specs.values
      if props['where']=='filename' && filename =~ props['pattern'] and (props['eval'].nil? or eval(props['eval']))
        warn "Rails v#{props['version']} deprecation found at #{filename} #{props['info']}. #{props['solution']}"
      end
    end
 
    File.open(filename).each_with_index do |line, ln|
      next if line =~ /^\s*#/ # skip commented lines
      for props in specs.values
        # puts "Checking "+props['pattern'].to_s
        if props['where']
          where = props['where'].scan /\w+/
          next unless where.any? do |place|
            case place
              when 'filename'
                false
              when 'controllers', 'models'
                filename.index("#{RAILS_ROOT}/app/#{place}/") == 0
              when 'views'
                filename.index("#{RAILS_ROOT}/app/views/") == 0  || filename.index("#{RAILS_ROOT}/app/helpers/") == 0
              when 'routes'
                filename == "#{RAILS_ROOT}/config/routes.rb"
              else
                filename.index("#{RAILS_ROOT}/#{place}/") == 0
              end
            end
        end

        if line =~ props['pattern'] and (props['eval'].nil? or eval(props['eval']))
          warn "Rails v#{props['version']} deprecation found at #{filename}:#{ln + 1}: #{props['info']}. #{props['solution']}"
        end
      end
    end
  end        
end