Skip to content

Commit

Permalink
Check attributes of schema.rb to decide whether to convert or not.
Browse files Browse the repository at this point in the history
  • Loading branch information
yonggu committed Oct 11, 2014
1 parent decf8b5 commit d482303
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 9 deletions.
31 changes: 24 additions & 7 deletions lib/rails/convert_dynamic_finders.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,23 @@
scoped_by_... => where(...)
find_or_initialize_by_... => find_or_initialize_by(...)
find_or_create_by_... => find_or_create_by(...)
But it keeps custom methods like dynamic finders intact.
EOF

attributes = ["id"]
within_file 'db/schema.rb' do
within_node type: 'block', caller: {type: 'send', message: 'create_table'} do
with_node type: 'send', receiver: 't' do
attributes << node.arguments.first.to_value
end
end
end

helper_method :dynamic_finder_to_hash do |prefix|
fields = node.message.to_s[prefix.length..-1].split("_and_")
fields = fields_of_dynamic_finder(prefix)
return nil if (fields & attributes) != fields

if fields.length == node.arguments.length && :hash != node.arguments.first.type
fields.length.times.map { |i|
fields[i] + ": " + node.arguments[i].to_source
Expand All @@ -21,13 +34,17 @@
end
end

helper_method :fields_of_dynamic_finder do |prefix|
node.message.to_s[prefix.length..-1].split("_and_")
end

if_gem 'rails', {gte: '3.0.0'}

within_files '**/*.rb' do
# find_all_by_... => where(...)
with_node type: 'send', message: /^find_all_by_/ do
hash_params = dynamic_finder_to_hash("find_all_by_")
replace_with add_receiver_if_necessary("where(#{hash_params})")
replace_with(add_receiver_if_necessary("where(#{hash_params})")) if hash_params
end

# find_by_... => where(...).first
Expand All @@ -36,20 +53,20 @@
replace_with add_receiver_if_necessary("where(id: {{arguments}}).first")
elsif :find_by_sql != node.message
hash_params = dynamic_finder_to_hash("find_by_")
replace_with add_receiver_if_necessary("where(#{hash_params}).first")
replace_with(add_receiver_if_necessary("where(#{hash_params}).first")) if hash_params
end
end

# find_last_by_... => where(...).last
with_node type: 'send', message: /^find_last_by_/ do
hash_params = dynamic_finder_to_hash("find_last_by_")
replace_with add_receiver_if_necessary("where(#{hash_params}).last")
replace_with(add_receiver_if_necessary("where(#{hash_params}).last")) if hash_params
end

# scoped_by_... => where(...)
with_node type: 'send', message: /^scoped_by_/ do
hash_params = dynamic_finder_to_hash("scoped_by_")
replace_with add_receiver_if_necessary("where(#{hash_params})")
replace_with(add_receiver_if_necessary("where(#{hash_params})")) if hash_params
end
end

Expand All @@ -59,13 +76,13 @@
# find_or_initialize_by_... => find_or_initialize_by(...)
with_node type: 'send', message: /^find_or_initialize_by_/ do
hash_params = dynamic_finder_to_hash("find_or_initialize_by_")
replace_with add_receiver_if_necessary("find_or_initialize_by(#{hash_params})")
replace_with(add_receiver_if_necessary("find_or_initialize_by(#{hash_params})")) if hash_params
end

# find_or_create_by_... => find_or_create_by(...)
with_node type: 'send', message: /^find_or_create_by_/ do
hash_params = dynamic_finder_to_hash("find_or_create_by_")
replace_with add_receiver_if_necessary("find_or_create_by(#{hash_params})")
replace_with(add_receiver_if_necessary("find_or_create_by(#{hash_params})")) if hash_params
end
end
end
39 changes: 37 additions & 2 deletions spec/rails/convert_dynamic_finders_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,70 +7,105 @@
end

describe 'with fakefs', fakefs: true do
let(:schema_content) {'
ActiveRecord::Schema.define(version: 20140211112752) do
create_table "users", force: true do |t|
t.integer "account_id", index: true
t.string "login"
t.string "email"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "role", default: 0, null: false
t.boolean "admin", default: false, null: false
t.boolean "active", default: false, null: false
end
end
'}

let(:post_model_content) {'
class Post < ActiveRecord::Base
def active_users
User.find_all_by_email_and_active(email, true)
User.find_all_by_label_and_active(label, true)
User.find_by_email_and_active(email, true)
User.find_by_label_and_active(label, true)
User.find_last_by_email_and_active(email, true)
User.find_last_by_label_and_active(label, true)
User.scoped_by_email_and_active(email, true)
User.scoped_by_label_and_active(label, true)
User.find_by_sql(["select * from users where email = ?", email])
User.find_by_id(id)
User.find_by_label
User.find_by_account_id(Account.find_by_email(account_email).id)
User.find_or_create_by_email_and_login(parmas)
User.find_or_create_by_label(label)
User.find_or_initialize_by_account_id(:account_id => account_id)
User.find_or_initialize_by_label(label)
end
def self.active_admins
find_all_by_role_and_active("admin", true)
User.find_all_by_role_and_active("admin", true)
end
end
'}
let(:post_model_rewritten_content) {'
class Post < ActiveRecord::Base
def active_users
User.where(email: email, active: true)
User.find_all_by_label_and_active(label, true)
User.where(email: email, active: true).first
User.find_by_label_and_active(label, true)
User.where(email: email, active: true).last
User.find_last_by_label_and_active(label, true)
User.where(email: email, active: true)
User.scoped_by_label_and_active(label, true)
User.find_by_sql(["select * from users where email = ?", email])
User.where(id: id).first
User.find_by_label
User.where(account_id: Account.where(email: account_email).first.id).first
User.find_or_create_by(parmas)
User.find_or_create_by_label(label)
User.find_or_initialize_by(:account_id => account_id)
User.find_or_initialize_by_label(label)
end
def self.active_admins
where(role: "admin", active: true)
User.where(role: "admin", active: true)
end
end
'}
let(:users_controller_content) {'
class UsersController < ApplicationController
def new
@user = User.find_or_initialize_by_login_and_email(params[:user][:login], params[:user][:email])
@user = User.find_or_initialize_by_label(params[:user][:label])
end
def create
@user = User.find_or_create_by_login_and_email(params[:user][:login], params[:user][:email])
@user = User.find_or_create_by_label(params[:user][:label])
end
end
'}
let(:users_controller_rewritten_content) {'
class UsersController < ApplicationController
def new
@user = User.find_or_initialize_by(login: params[:user][:login], email: params[:user][:email])
@user = User.find_or_initialize_by_label(params[:user][:label])
end
def create
@user = User.find_or_create_by(login: params[:user][:login], email: params[:user][:email])
@user = User.find_or_create_by_label(params[:user][:label])
end
end
'}

it 'converts' do
FileUtils.mkdir_p 'db'
FileUtils.mkdir_p 'app/models'
FileUtils.mkdir_p 'app/controllers'
File.write 'db/schema.rb', schema_content
File.write 'app/models/post.rb', post_model_content
File.write 'app/controllers/users_controller.rb', users_controller_content
@rewriter.process
Expand Down

0 comments on commit d482303

Please sign in to comment.