<commit_before>module Roar
  module Representer
    module Feature
      # Define hypermedia links in your representations.
      #
      # Example:
      #
      #   class Order
      #     include Roar::Representer::JSON
      #
      #     property :id
      #
      #     link :self do
      #       "http://orders/#{id}"
      #     end
      #
      # If you want more attributes, just pass a hash to #link.
      #
      #     link :rel => :next, :title => "Next, please!" do
      #       "http://orders/#{id}"
      #     end
      #
      # If you need dynamic attributes, the block can return a hash.
      #
      #     link :preview do
      #       {:href => image.url, :title => image.name}
      #     end
      #
      # Sometimes you need values from outside when the representation links are rendered. Just pass them
      # to the render method, they will be available as block parameters.
      #
      #   link :self do |opts|
      #     "http://orders/#{opts[:id]}"
      #   end
      #
      #   model.to_json(:id => 1)
      module Hypermedia
        def self.included(base)
          base.extend ClassMethods
        end

        def before_serialize(options={})
          prepare_links!(options) unless options[:links] == false  # DISCUSS: doesn't work when links are already setup (e.g. from #deserialize).
          super # Representer::Base
        end

        attr_writer :links

        def links
          @links ||= LinkCollection.new
        end

        def links_array
          links.values  # FIXME: move to LinkCollection#to_a.
        end

        def links_array=(ary)
          # FIXME: move to LinkCollection
          self.links= LinkCollection.new
          ary.each do |lnk|
            self.links[lnk.rel.to_s] = lnk
          end
        end

      private
        def links_definition
          representable_attrs.find { |d| d.is_a?(LinksDefinition) } or [] # FIXME: this is a bug as soon as #links_definition is used somewhere else beside #prepare_links.
        end

        # Setup hypermedia links by invoking their blocks. Usually called by #serialize.
        def prepare_links!(*args)
          links_definition.each do |config|  # config is [{..}, block]
            options, block  = config.first, config.last
            href            = run_link_block(block, *args) or next

            links.add(prepare_link_for(href, options))
          end
        end

        def prepare_link_for(href, options)
          options.merge! href.is_a?(Hash) ? href : {:href => href}
          Hyperlink.new(options)
        end

        def run_link_block(block, *args)
          instance_exec(*args, &block)
        end
<commit_msg>use LinkCollection API wherever possible.<commit_after>module Roar
  module Representer
    module Feature
      # Define hypermedia links in your representations.
      #
      # Example:
      #
      #   class Order
      #     include Roar::Representer::JSON
      #
      #     property :id
      #
      #     link :self do
      #       "http://orders/#{id}"
      #     end
      #
      # If you want more attributes, just pass a hash to #link.
      #
      #     link :rel => :next, :title => "Next, please!" do
      #       "http://orders/#{id}"
      #     end
      #
      # If you need dynamic attributes, the block can return a hash.
      #
      #     link :preview do
      #       {:href => image.url, :title => image.name}
      #     end
      #
      # Sometimes you need values from outside when the representation links are rendered. Just pass them
      # to the render method, they will be available as block parameters.
      #
      #   link :self do |opts|
      #     "http://orders/#{opts[:id]}"
      #   end
      #
      #   model.to_json(:id => 1)
      module Hypermedia
        def self.included(base)
          base.extend ClassMethods
        end

        def before_serialize(options={})
          prepare_links!(options) unless options[:links] == false  # DISCUSS: doesn't work when links are already setup (e.g. from #deserialize).
          super # Representer::Base
        end

        attr_writer :links

        def links
          @links ||= LinkCollection.new
        end

        def links_array
          links.values  # FIXME: move to LinkCollection#to_a.
        end

        def links_array=(ary)
          # FIXME: move to LinkCollection
          self.links= LinkCollection.new
          ary.each { |lnk| links.add(lnk) }
        end

      private
        def links_definition
          representable_attrs.find { |d| d.is_a?(LinksDefinition) } or [] # FIXME: this is a bug as soon as #links_definition is used somewhere else beside #prepare_links.
        end

        # Setup hypermedia links by invoking their blocks. Usually called by #serialize.
        def prepare_links!(*args)
          links_definition.each do |config|  # config is [{..}, block]
            options, block  = config.first, config.last
            href            = run_link_block(block, *args) or next

            links.add(prepare_link_for(href, options))
          end
        end

        def prepare_link_for(href, options)
          options.merge! href.is_a?(Hash) ? href : {:href => href}
          Hyperlink.new(options)
        end

        def run_link_block(block, *args)
          instance_exec(*args, &block)
        end

{'fraction_non_alphanumeric': 0.09374416433239963, 'fraction_numerical': 0.00037348272642390287, 'mean_word_length': 1.738241308793456, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, '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': '3736801', 'n_tokens_mistral': 1502, 'n_tokens_neox': 1472, 'n_words': 451}