\$\begingroup\$
\$\endgroup\$
Can someone please review my code:
# dup/ish -> //github.com/rails/rails/issues/5449
class Form
include Mongoid::Document
attr_accessor :source
def self.ish(prefix, suffix, &block)
klass_name = prefix.classify + suffix
dup.tap do |klass|
klass.class_eval do
define_singleton_method(:name) do
prefix.classify
end
end
klass.class_eval(&block)
Object.const_set(klass_name, klass)
end
end
def self.compose(klass_name, id, source)
mongoid_translate = {:models => {}, :attributes => {}}
form = ish(klass_name, id) do
translate = {}
source.flatten.each do |widget|
if widget.include?('validate')
validates *widget.values_at('name', 'validate')
translate.store *widget.values_at('name', 'translate')
end
if widget.include?('name')
if 'upload' == widget['type']
has_many(:attachments)
accepts_nested_attributes_for(:attachments)
elsif 'repeat' == widget['type']
part_klass = Form.compose(widget['name'], id, widget['parts'])
embeds_many(widget['name'].pluralize, :class_name => part_klass.class.to_s)
accepts_nested_attributes_for(widget['name'].pluralize)
end
end
end
mongoid_translate[:attributes][self.name.downcase.to_sym] = translate
end
I18n.backend.store_translations(:pt_BR, {:mongoid => mongoid_translate})
form.new.tap do |form|
form.source = source
end
end
def prepare
self.source.flatten.each do |widget|
if widget.include?('name')
if 'repeat' == widget['type']
parts = send("#{widget['name'].pluralize}")
if parts.empty?
parts.build
widget['parts'].each do |part|
parts[0].write_attribute(part['name'], nil)
end
end
elsif 'upload' == widget['type']
attachments.build if attachments.empty?
else
begin
send(widget['name'].to_sym)
rescue NoMethodError
write_attribute(widget['name'], nil)
end
end
end
end
end
end
200_success
145k22 gold badges190 silver badges478 bronze badges
asked May 15, 2013 at 14:10
1 Answer 1
\$\begingroup\$
\$\endgroup\$
2
Few things I have noted in your design are listed below. Beware all of this is purely from a design perspective rather than application.
- Source is defined as
attr_accessor
which essentially violates encapsulation. Inject it from outside in constructor call.(I am not able to understand why you have not gone forattr_reader
instead ofaccessor
. - Ideally
self.compose
can be split into different method calls. It is violating SRP by doing too many things at one place. That is same for other methods as well. - Speaking from a puritan view, the branched if condition is also a smell.
In general, metaprogramming is considered to be something which must be avoided unless you have enough justification to keep it.
answered Oct 21, 2015 at 10:36
-
\$\begingroup\$ Whoa I totally forgot I put this here. :P And yes I see very well all your points. It's actually something I knew had smells all over the place but wanted to check with other people (which I couldn't because I was the only programmer working on the project). Thanks for your time and effort! Have a great day. \$\endgroup\$Arthur Corenzan– Arthur Corenzan2016年01月07日 17:44:08 +00:00Commented Jan 7, 2016 at 17:44
-
\$\begingroup\$ my pleasure! there might be more smells. \$\endgroup\$Anony-mouse– Anony-mouse2016年04月14日 09:59:09 +00:00Commented Apr 14, 2016 at 9:59
Explore related questions
See similar questions with these tags.
lang-rb