Skip to content
Permalink
Browse files

Merge pull request #2477 from ekylibre/feature/superable-restfullies

Made ManageRestfully generate modules dynamically
  • Loading branch information...
Aquaj committed Mar 31, 2019
2 parents d04ff2d + 78567a7 commit 233bed6986fc2e2429d77fe0eb1ec1284d648e7f
@@ -6,15 +6,15 @@ module ClassMethods
def manage_restfully(defaults = {})
name = controller_name
path = controller_path
options = defaults.extract!(:t3e, :creation_t3e, :redirect_to, :xhr, :destroy_to, :subclass_inheritance, :partial, :multipart, :except, :only, :cancel_url, :scope, :identifier, :continue)
options = defaults.extract!(:t3e, :creation_t3e, :redirect_to, :xhr, :destroy_to, :subclass_inheritance, :partial, :multipart, :except, :only, :cancel_url, :scope, :identifier, :continue, :model_name)
after_save_url = options[:redirect_to]
after_destroy_url = options[:destroy_to] || :index
actions = %i[index show new create edit update destroy]
actions &= [options[:only]].flatten if options[:only]
actions -= [options[:except]].flatten if options[:except]

record_name = name.to_s.singularize
model_name = name.to_s.classify
model_name = options[:model_name] || name.to_s.classify
model = model_name.constantize
columns = model.columns_definition.keys

@@ -72,8 +72,9 @@ def manage_restfully(defaults = {})
creation_t3e = options[:creation_t3e].is_a?(TrueClass)

code = ''
class_code = ''

code << "respond_to :html, :xml, :json\n"
class_code << "respond_to :html, :xml, :json\n"
# code << "respond_to :pdf, :odt, :ods, :csv, :docx, :xlsx, :only => [:show, :index]\n"

if actions.include?(:index)
@@ -127,10 +128,10 @@ def manage_restfully(defaults = {})

if options[:subclass_inheritance]
if self != Backend::BaseController
code << "def self.inherited(subclass)\n"
class_code << "def self.inherited(subclass)\n"
# TODO: inherit from superclass parameters (superclass.manage_restfully_options)
code << " subclass.manage_restfully(#{options.inspect})\n"
code << "end\n"
class_code << " subclass.manage_restfully(#{options.inspect})\n"
class_code << "end\n"
end
end

@@ -244,11 +245,12 @@ def manage_restfully(defaults = {})
file = Rails.root.join('tmp', 'code', 'manage_restfully', "#{controller_path}.rb")
FileUtils.mkdir_p(file.dirname)
File.open(file, 'wb') do |f|
f.write class_code
f.write code
end
end

class_eval(code)
insert_module(code, class_code)
end

# Build standard actions to manage records of a model
@@ -259,6 +261,7 @@ def manage_restfully_list(order_by = :id)
records = model.name.underscore.pluralize
raise ArgumentError, "Unknown column for #{model.name}" unless model.columns_definition[order_by]
code = ''
class_code = ''

sort = ''
position = "#{record_name}_position_column"
@@ -287,7 +290,7 @@ def manage_restfully_list(order_by = :id)
code << "end\n"

# list = code.split("\n"); list.each_index{|x| puts((x+1).to_s.rjust(4)+": "+list[x])}
class_eval(code)
insert_module(code, class_code, name: :list)
end

# Build standard actions to manage records of a model
@@ -297,6 +300,7 @@ def manage_restfully_incorporation
model = name.to_s.singularize.classify.constantize
records = model.name.underscore.pluralize
code = ''
class_code = ''

columns = model.columns_definition.keys
columns = columns.delete_if { |c| %i[depth rgt lft id lock_version updated_at updater_id creator_id created_at].include?(c.to_sym) }
@@ -328,14 +332,15 @@ def manage_restfully_incorporation
code << " render 'pick'\n"
code << "end\n"

class_eval(code)
insert_module(code, class_code, name: :incorporation)
end

#
def manage_restfully_picture
name = controller_name
record_name = name.to_s.singularize
code = ''
class_code = ''
code << "def picture\n"
code << " return unless #{record_name} = find_and_check(:#{record_name})\n"
code << " if #{record_name}.picture.file?\n"
@@ -344,7 +349,31 @@ def manage_restfully_picture
code << " head :not_found\n"
code << " end\n"
code << "end\n"
class_eval(code)

insert_module(code, class_code, name: :picture)
end

private

def name_module(mod, kind)
# Ensure we don't collide with other controllers but still don't need
# intermediate namespacing modules
unique_controller_name = controller_path.camelize.simpleize
kind_name = kind.to_s.classify
mod_name = "#{unique_controller_name}#{kind_name}Actions"
RestfullyManageable.const_set mod_name, mod
end

def insert_module(code, class_code, name: '')
restful_module = Module.new
name_module(restful_module, name)
restful_module.class_eval(code)
restful_module.extend ActiveSupport::Concern
restful_module.send(:included) do
eval class_code
end
include restful_module
self
end
end
end
@@ -0,0 +1,46 @@
require 'test_helper'

class RestfullyManageableTest < ActionController::TestCase
Model = Class.new do
def self.columns_definition
{ 'id' => "whatever" }
end
end

setup do
if defined? ModelController
RestfullyManageableTest.send :remove_const, :ModelController
end
if defined? RestfullyManageable::Model
RestfullyManageable.send :remove_const, :Model
end

class ModelController < ActionController::Base
include RestfullyManageable
end
@kontroller = ModelController.new
end

test 'restfully_manageable doesn\'t define the actions' do
initial_methods = ModelController.new.methods(false)
ModelController.send(:manage_restfully, only: :index, model_name: 'RestfullyManageableTest::Model')
after_restfully_methods = ModelController.new.methods(false)
assert_equal after_restfully_methods, initial_methods
end

test 'restfully_manageable inserts a new module in the controller' do
initial_parents = ModelController.ancestors
ModelController.send(:manage_restfully, only: :index, model_name: 'RestfullyManageableTest::Model')
after_restfully_parents = ModelController.ancestors
difference = after_restfully_parents - initial_parents
assert_equal difference.count, 1
assert_equal difference.first.class, Module
end

test 'restfully_manageable does define controller methods' do
controller = ModelController.new
assert_not controller.respond_to? :index
ModelController.send(:manage_restfully, only: :index, model_name: 'RestfullyManageableTest::Model')
assert controller.respond_to? :index
end
end

0 comments on commit 233bed6

Please sign in to comment.
You can’t perform that action at this time.