<commit_before>require 'yaml'

module DM
  class Reader 
    attr_accessor :models_hash,
                  :options,
									:yaml_file

    def initialize(yaml_file, options = {})
      @models_hash = HashWithIndifferentAccess.new(YAML::load_file(yaml_file)).symbolize_keys!
      @options = options.merge(:yaml_file => yaml_file)
    end

    def models
      Model.add_options(options)
			@models ||= load_models(models_hash)
    end


    # The nested Model class is responsible for extracting all information for each model
    class Model
	
			class << self
				attr_reader :supported_associations, 
										:parent_associations,
										:supported_association_options,
										:view_templates,
										:yaml_file
				
				def add_options(options = {})
	        @supported_associations = options[:supported_associations] || []
	        @parent_associations = options[:parent_associations] || []
	        @supported_association_options = options[:supported_association_options] || []
					@view_templates = options[:view_templates] || []
					@yaml_file = options[:yaml_file]
				end
			end
			
			# Delegate class 
			delegate	 	:parent_associations,
									:supported_associations, 
									:supported_association_options,
									:view_templates,
									:yaml_file,
							:to => :parent
			
			def parent
				self.class
			end 
		
      attr_reader :attributes,
									:class_name,
                  :class_path,
                  :controller_class_name,
                  :controller_class_path,
                  :controller_class_nesting_depth,
                  :controller_file_path,
                  :controller_file_name,
                  :habtm_associations,
                  :model_hash,
                  :model_name,
									:namespaces,
									:plural_name,
									:singular_name,
                  :table_name
                      
      def initialize(model_name, model_hash, options = {})
        @singular_name = @model_name = model_name.singularize
				@plural_name = @singular_name.pluralize
        @model_hash = model_hash
				model_hash[:associations] ||= {}
				model_hash[:attributes] ||= {}
        
        @namespaces = options[:namespaces] || []
        @namespace_symbols = @namespaces.map {|x| ":#{x}"}
        @controller_class_nesting_depth = @namespaces.length
                
        #Inflect
        @class_name = model_name.classify
        @controller_file_name = @table_name = model_name.pluralize
        @class_path = []
        @controller_file_path = @namespaces
        @controller_class_path = @namespaces.join("/")
        @controller_class_name = ( (@namespaces.empty? ? "" : controller_class_path + "/" ) + table_name).camelize
				@templates = view_templates

        extract_attributes
        extract_associations
      end
    
      # TODO put all necessary attributes in the h so that it can be assigned in the templates.
      def to_h
        # unless @member_hash
          @member_hash = HashWithIndifferentAccess.new

          # First add all instance methods to the hash, this should be done first 
          # before values are overriden by their own references
	        my_methods.each do |method_name| 
						@member_hash[method_name] = send(method_name) 
					end
	
          # Attributes
          @member_hash[:attribute_names] = attributes.map(&:name)
          @member_hash[:boolean_attributes] = attributes.reject{|x| x.type != "boolean" }
          @member_hash[:boolean_attribute_names] = @member_hash[:boolean_attributes].map(&:name)
          @member_hash[:string_attributes] = attributes.reject{|x| not %w(string text).include? x.type }
          @member_hash[:string_attribute_names] = @member_hash[:string_attributes].map(&:name)

          # Associations
          supported_associations.each do |type|
            @member_hash["#{type}_associations"] = @associations[type]
            @member_hash["#{type}_associations_with_options"] = @associations[type].map{|x| association_with_options(x) }
            @member_hash["#{type}_association_names"] = @associations[type].map{|x| x[:name] }
          end

          # Add the names of parent associations
          @member_hash[:parent_names] = parent_associations.inject([]) { |names, type| @member_hash["#{type}_association_names"] }

					# Add special member 
					@attributes_for.each_pair {|template, attributes| @member_hash["attributes_for_#{template}"] = attributes }

          # All names should be available as symbols as well
          @member_hash.each_pair do |key, values|
            new_key = key.to_s.gsub("_names", "_symbols")
            unless new_key == key.to_s
              @member_hash[new_key] = values.map{|x| ":#{x}"}
            end
          end
        # end
        @member_hash

				# raise @member_hash.keys.to_yaml
      end
      
      # form_for should support namespaces and nested resources
  		def form_for_args
  			args = []
  			args += @namespace_symbols
  			args << "parent_object" unless @associations.empty? ## TODO only do this when make_resourceful or simular library that supports nesting is available
  			args << model_name

  			args.size == 1 ? args.first : "[#{args.join(", ")}]"
  		end

      private

        def my_methods
          self.class.public_instance_methods - (Object.instance_methods + %w(to_h model_hash path_for my_methods))
        end
        
        def association_with_options(association)
          assoc_string = ":" + association[:name]
          supported_association_options.each do |option|
            assoc_string += ", #{option} => :#{association[option]}" if association[option]
          end<commit_msg>added attribute_names_for*<commit_after>require 'yaml'

module DM
  class Reader 
    attr_accessor :models_hash,
                  :options,
									:yaml_file

    def initialize(yaml_file, options = {})
      @models_hash = HashWithIndifferentAccess.new(YAML::load_file(yaml_file)).symbolize_keys!
      @options = options.merge(:yaml_file => yaml_file)
    end

    def models
      Model.add_options(options)
			@models ||= load_models(models_hash)
    end


    # The nested Model class is responsible for extracting all information for each model
    class Model
	
			class << self
				attr_reader :supported_associations, 
										:parent_associations,
										:supported_association_options,
										:view_templates,
										:yaml_file
				
				def add_options(options = {})
	        @supported_associations = options[:supported_associations] || []
	        @parent_associations = options[:parent_associations] || []
	        @supported_association_options = options[:supported_association_options] || []
					@view_templates = options[:view_templates] || []
					@yaml_file = options[:yaml_file]
				end
			end
			
			# Delegate class 
			delegate	 	:parent_associations,
									:supported_associations, 
									:supported_association_options,
									:view_templates,
									:yaml_file,
							:to => :parent
			
			def parent
				self.class
			end 
		
      attr_reader :attributes,
									:class_name,
                  :class_path,
                  :controller_class_name,
                  :controller_class_path,
                  :controller_class_nesting_depth,
                  :controller_file_path,
                  :controller_file_name,
                  :habtm_associations,
                  :model_hash,
                  :model_name,
									:namespaces,
									:plural_name,
									:singular_name,
                  :table_name
                      
      def initialize(model_name, model_hash, options = {})
        @singular_name = @model_name = model_name.singularize
				@plural_name = @singular_name.pluralize
        @model_hash = model_hash
				model_hash[:associations] ||= {}
				model_hash[:attributes] ||= {}
        
        @namespaces = options[:namespaces] || []
        @namespace_symbols = @namespaces.map {|x| ":#{x}"}
        @controller_class_nesting_depth = @namespaces.length
                
        #Inflect
        @class_name = model_name.classify
        @controller_file_name = @table_name = model_name.pluralize
        @class_path = []
        @controller_file_path = @namespaces
        @controller_class_path = @namespaces.join("/")
        @controller_class_name = ( (@namespaces.empty? ? "" : controller_class_path + "/" ) + table_name).camelize
				@templates = view_templates

        extract_attributes
        extract_associations
      end
    
      # TODO put all necessary attributes in the h so that it can be assigned in the templates.
      def to_h
        # unless @member_hash
          @member_hash = HashWithIndifferentAccess.new

          # First add all instance methods to the hash, this should be done first 
          # before values are overriden by their own references
	        my_methods.each do |method_name| 
						@member_hash[method_name] = send(method_name) 
					end
	
          # Attributes
					@attributes_for.each_pair do |template, attributes| 
						@member_hash["attributes_for_#{template}"] = attributes
						@member_hash["attribute_names_for_#{template}"] = attributes.map(&:name)
					end
					
          @member_hash[:attribute_names] = attributes.map(&:name)
          @member_hash[:boolean_attributes] = attributes.reject{|x| x.type != "boolean" }
          @member_hash[:string_attributes] = attributes.reject{|x| not %w(string text).include? x.type }

					[:boolean_attributes, :string_attributes].each {|k| @member_hash["#{k.to_s[0..-2]}_names"] = @member_hash[:boolean_attributes].map(&:name) }

          # Associations
          supported_associations.each do |type|
            @member_hash["#{type}_associations"] = @associations[type]
            @member_hash["#{type}_associations_with_options"] = @associations[type].map{|x| association_with_options(x) }
            @member_hash["#{type}_association_names"] = @associations[type].map{|x| x[:name] }
          end

          # Add the names of parent associations
          @member_hash[:parent_names] = parent_associations.inject([]) { |names, type| @member_hash["#{type}_association_names"] }


          # All names should be available as symbols as well
          @member_hash.each_pair do |key, values|
            new_key = key.to_s.gsub("_names", "_symbols")
            unless new_key == key.to_s
              @member_hash[new_key] = values.map{|x| ":#{x}"}
            end
          end
        # end
        @member_hash
      end

      
      # form_for should support namespaces and nested resources
  		def form_for_args
  			args = []
  			args += @namespace_symbols
  			args << "parent_object" unless @associations.empty? ## TODO only do this when make_resourceful or simular library that supports nesting is available
  			args << model_name

  			args.size == 1 ? args.first : "[#{args.join(", ")}]"
  		end

      private

        def my_methods
          self.class.public_instance_methods - (Object.instance_methods + %w(to_h model_hash path_for my_methods))
        end
        
        def association_with_options(association)
          assoc_string = ":" + association[:name]
          supported_association_options.each do |option|
            assoc_string += ", #{option} => :#{association[option]}" if association[option]
          end
{'fraction_non_alphanumeric': 0.09964664310954063, 'fraction_numerical': 0.00035335689045936394, 'mean_word_length': 2.446270928462709, 'pattern_counts': {'":': 6, '<': 15, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '300114', 'n_tokens_mistral': 3685, 'n_tokens_neox': 3193, 'n_words': 642}