require 'thor' module Scrivito class AttributeDefinitionMigrator include Thor::Actions include Thor::Base include Thor::Shell def initialize(path) self.destination_root = Rails.root.to_s self.options = {} @path = path.to_s end def self.migrate_application Dir[Rails.root + 'app/models/**/*.rb'].each do |model_path| new(model_path).migrate end end def migrate relative_path = path.gsub("#{Rails.root.to_s}/", '') if model_class && (page_model? || widget_model?) say_status :inspecting, relative_path if obj_class say_status :migrating, relative_path inject_attribute_definitions else with_padding do say %{[warning] Model "#{model_class}" has no corresponding ObjClass in published workspace. Ignore this message if it is an abstract class and should not have an ObjClass by design. Or maybe "#{model_class}" is not used anymore and file #{relative_path} can be removed? }, :yellow end say_status :skipping, relative_path end puts end end private attr_reader :path def model_class @model_class ||= class_name.constantize rescue NameError end def page_model? model_class.ancestors.include?(BasicObj) && model_class != ::Obj end def widget_model? model_class.ancestors.include?(BasicWidget) && model_class != ::Widget end def inject_attribute_definitions inject_into_class(path, model_class, "#{attribute_definitions.join}\n", verbose: false) end def class_name @class_name ||= path.gsub(/^.*\/app\/models/, '').gsub('.rb', '').classify end def attribute_definitions definitions = obj_class_attributes.map do |attr| attribute_definition = " attribute :#{attr.name}, :#{type_for(attr.name, attr.type)}" if attr.type == 'enum' || attr.type == 'multienum' attribute_definition << ", values: #{attr.values.to_s}" end attribute_definition << "\n" end if page_model? && obj_class.legacy_type? definitions << " attribute :title, :string\n" if obj_class.is_binary definitions << " attribute :blob, :binary\n" else definitions << " attribute :body, :html\n" end end definitions.uniq end def type_for(name, type) case type when 'text' then 'string' when 'widget' then 'widgetlist' else type end end def obj_class_attributes Workspace.published.as_current do obj_class.attributes.sort_by(&:name) end end def obj_class @obj_class = ObjClass.find(model_class.name) rescue Scrivito::ResourceNotFound end end end