passive_record 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.md +1 -2
 - data/lib/passive_record/class_methods.rb +98 -0
 - data/lib/passive_record/instance_methods.rb +70 -0
 - data/lib/passive_record/pretty_printing.rb +33 -0
 - data/lib/passive_record/version.rb +1 -1
 - data/lib/passive_record.rb +5 -161
 - data/spec/passive_record_spec.rb +30 -0
 - metadata +5 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: bd4210b6d42edbbc3b345887b2a15918d452fdd2
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: c5c73ddb836c84ceaaf9290e829f7b7d31ae6e20
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: c56f0f03af33458ed3a8d0e0d8b8d4795187df9197a71c95625a688f47636b1898c4ce03450142bc4baaedf615c70b34ca075e018e038cdb2731a05e94254f07
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 18e488e25f0ad1a0ca791920160bd0fc7f4c3fb49987f1801fa5f1485aa93dd8463ca5cf8be723ae966a5b43544c69c15aa7ea640335aba4342f4dc6780c1f07
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -7,7 +7,7 @@ 
     | 
|
| 
       7 
7 
     | 
    
         
             
            [](https://codeclimate.com/github/deepcerulean/passive_record)
         
     | 
| 
       8 
8 
     | 
    
         
             
            [](https://codeship.com/projects/128700)
         
     | 
| 
       9 
9 
     | 
    
         
             
            [](https://codeclimate.com/github/deepcerulean/passive_record/coverage)
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
      
 10 
     | 
    
         
            +
            [](https://badge.fury.io/rb/passive_record)
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
            ## Description
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
         @@ -27,7 +27,6 @@ PassiveRecord may be right for you! 
     | 
|
| 
       27 
27 
     | 
    
         | 
| 
       28 
28 
     | 
    
         
             
            ## Features
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
              - New objects are tracked and assigned IDs
         
     | 
| 
       31 
30 
     | 
    
         
             
              - Build relationships with belongs_to, has_one and has_many
         
     | 
| 
       32 
31 
     | 
    
         
             
              - Query on attributes and associations
         
     | 
| 
       33 
32 
     | 
    
         
             
              - Supports many-to-many and self-referential relationships
         
     | 
| 
         @@ -0,0 +1,98 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module PassiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module ClassMethods
         
     | 
| 
      
 3 
     | 
    
         
            +
                include PassiveRecord::Core
         
     | 
| 
      
 4 
     | 
    
         
            +
                include PassiveRecord::Associations
         
     | 
| 
      
 5 
     | 
    
         
            +
                include PassiveRecord::Hooks
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                include Enumerable
         
     | 
| 
      
 8 
     | 
    
         
            +
                extend Forwardable
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                # from http://stackoverflow.com/a/2393750/90042
         
     | 
| 
      
 11 
     | 
    
         
            +
                def descendants
         
     | 
| 
      
 12 
     | 
    
         
            +
                  ObjectSpace.each_object(Class).select { |klass| klass < self }
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def all
         
     | 
| 
      
 16 
     | 
    
         
            +
                  instances_by_id.values
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
                def_delegators :all, :each
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def last
         
     | 
| 
      
 21 
     | 
    
         
            +
                  all.last
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def find(id_or_ids)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  if id_or_ids.is_a?(Array)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    find_by_ids(id_or_ids)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  else
         
     | 
| 
      
 28 
     | 
    
         
            +
                    find_by_id(id_or_ids)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def find_by(conditions)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  if conditions.is_a?(Identifier)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    find_by_id(conditions)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  elsif conditions.is_a?(Array) && conditions.all? { |c| c.is_a?(Identifier) }
         
     | 
| 
      
 36 
     | 
    
         
            +
                    find_by_ids(conditions)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  else
         
     | 
| 
      
 38 
     | 
    
         
            +
                    where(conditions).first
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def find_all_by(conditions)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  if conditions.is_a?(Array) && conditions.all? { |c| c.is_a?(Identifier) }
         
     | 
| 
      
 44 
     | 
    
         
            +
                    find_by_ids(conditions)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  else
         
     | 
| 
      
 46 
     | 
    
         
            +
                    where(conditions).all
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def where(conditions)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  Query.new(self, conditions)
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def create(attrs={})
         
     | 
| 
      
 55 
     | 
    
         
            +
                  instance = new
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  instance.singleton_class.class_eval { attr_accessor :id }
         
     | 
| 
      
 58 
     | 
    
         
            +
                  instance.send(:"id=", Identifier.generate(self))
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  register(instance)
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  attrs.each do |(k,v)|
         
     | 
| 
      
 63 
     | 
    
         
            +
                    instance.send("#{k}=", v)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  after_create_hooks.each do |hook|
         
     | 
| 
      
 67 
     | 
    
         
            +
                    hook.run(instance)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  instance
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def destroy_all
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @instances = {}
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                protected
         
     | 
| 
      
 78 
     | 
    
         
            +
                def find_by_id(_id)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  key = instances_by_id.keys.detect { |id,_| id == _id }
         
     | 
| 
      
 80 
     | 
    
         
            +
                  instances_by_id[key] if key
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                def find_by_ids(ids)
         
     | 
| 
      
 84 
     | 
    
         
            +
                  instances_by_id.select { |id,_| ids.include?(id) }.values
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                private
         
     | 
| 
      
 88 
     | 
    
         
            +
                def instances_by_id
         
     | 
| 
      
 89 
     | 
    
         
            +
                  @instances ||= {}
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                def register(model)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  instances_by_id[model.id] = model
         
     | 
| 
      
 94 
     | 
    
         
            +
                  self
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
              end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,70 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module PassiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module InstanceMethods
         
     | 
| 
      
 3 
     | 
    
         
            +
                include PrettyPrinting
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def respond_to?(meth,*args,&blk)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  if find_relation_by_target_name_symbol(meth)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    true
         
     | 
| 
      
 8 
     | 
    
         
            +
                  else
         
     | 
| 
      
 9 
     | 
    
         
            +
                    super(meth,*args,&blk)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def method_missing(meth, *args, &blk)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  if (matching_relation = find_relation_by_target_name_symbol(meth))
         
     | 
| 
      
 15 
     | 
    
         
            +
                    send_relation(matching_relation, meth, *args, &blk)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  else
         
     | 
| 
      
 17 
     | 
    
         
            +
                    super(meth,*args,&blk)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                protected
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def send_relation(matching_relation, meth, *args, &blk)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  target_name = matching_relation.association.target_name_symbol.to_s
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  case meth.to_s
         
     | 
| 
      
 27 
     | 
    
         
            +
                  when target_name
         
     | 
| 
      
 28 
     | 
    
         
            +
                    matching_relation.lookup
         
     | 
| 
      
 29 
     | 
    
         
            +
                  when "#{target_name}="
         
     | 
| 
      
 30 
     | 
    
         
            +
                    matching_relation.parent_model_id = args.first.id
         
     | 
| 
      
 31 
     | 
    
         
            +
                  when "create_#{target_name}", "create_#{target_name.singularize}"
         
     | 
| 
      
 32 
     | 
    
         
            +
                    matching_relation.create(*args)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  when "#{target_name}_id"
         
     | 
| 
      
 34 
     | 
    
         
            +
                    matching_relation.parent_model_id
         
     | 
| 
      
 35 
     | 
    
         
            +
                  when "#{target_name}_id="
         
     | 
| 
      
 36 
     | 
    
         
            +
                    matching_relation.parent_model_id = args.first
         
     | 
| 
      
 37 
     | 
    
         
            +
                  when "#{target_name}_ids", "#{target_name.singularize}_ids"
         
     | 
| 
      
 38 
     | 
    
         
            +
                    matching_relation.parent_model.send(target_name).map(&:id)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def relata
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @_relata ||= self.class.associations.map do |assn|
         
     | 
| 
      
 44 
     | 
    
         
            +
                    assn.to_relation(self)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                private
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def find_relation_by_target_name_symbol(meth)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  relata.detect do |relation|  # matching relation...
         
     | 
| 
      
 52 
     | 
    
         
            +
                    possible_target_names(relation).include?(meth.to_s)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def possible_target_names(relation)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  target_name = relation.association.target_name_symbol.to_s
         
     | 
| 
      
 58 
     | 
    
         
            +
                  [
         
     | 
| 
      
 59 
     | 
    
         
            +
                    target_name,
         
     | 
| 
      
 60 
     | 
    
         
            +
                    "#{target_name}=",
         
     | 
| 
      
 61 
     | 
    
         
            +
                    "#{target_name}_id",
         
     | 
| 
      
 62 
     | 
    
         
            +
                    "#{target_name}_ids",
         
     | 
| 
      
 63 
     | 
    
         
            +
                    "#{target_name.singularize}_ids",
         
     | 
| 
      
 64 
     | 
    
         
            +
                    "#{target_name}_id=",
         
     | 
| 
      
 65 
     | 
    
         
            +
                    "create_#{target_name}",
         
     | 
| 
      
 66 
     | 
    
         
            +
                    "create_#{target_name.singularize}"
         
     | 
| 
      
 67 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module PassiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module PrettyPrinting
         
     | 
| 
      
 3 
     | 
    
         
            +
                def inspect
         
     | 
| 
      
 4 
     | 
    
         
            +
                  pretty_vars = instance_variables_hash.map do |k,v|
         
     | 
| 
      
 5 
     | 
    
         
            +
                    "#{k.to_s.gsub(/^\@/,'')}: #{v.inspect}"
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end.join(', ')
         
     | 
| 
      
 7 
     | 
    
         
            +
                  "#{self.class.name} (#{pretty_vars})"
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                protected
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def uninspectable_instance_variables
         
     | 
| 
      
 13 
     | 
    
         
            +
                  []
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                private
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def inspectable_instance_variables
         
     | 
| 
      
 19 
     | 
    
         
            +
                  vars = instance_variables
         
     | 
| 
      
 20 
     | 
    
         
            +
                  vars += members rescue []
         
     | 
| 
      
 21 
     | 
    
         
            +
                  vars - uninspectable_instance_variables
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                # from http://stackoverflow.com/a/8417341/90042
         
     | 
| 
      
 25 
     | 
    
         
            +
                def instance_variables_hash
         
     | 
| 
      
 26 
     | 
    
         
            +
                  Hash[
         
     | 
| 
      
 27 
     | 
    
         
            +
                    inspectable_instance_variables.
         
     | 
| 
      
 28 
     | 
    
         
            +
                    reject { |sym| sym.to_s.start_with?("@_") }.
         
     | 
| 
      
 29 
     | 
    
         
            +
                    map { |name| [name, (instance_variable_get(name) rescue send(name))] }
         
     | 
| 
      
 30 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/passive_record.rb
    CHANGED
    
    | 
         @@ -10,6 +10,11 @@ require 'passive_record/class_inheritable_attrs' 
     | 
|
| 
       10 
10 
     | 
    
         
             
            require 'passive_record/associations'
         
     | 
| 
       11 
11 
     | 
    
         
             
            require 'passive_record/hooks'
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
      
 13 
     | 
    
         
            +
            require 'passive_record/pretty_printing'
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            require 'passive_record/instance_methods'
         
     | 
| 
      
 16 
     | 
    
         
            +
            require 'passive_record/class_methods'
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
       13 
18 
     | 
    
         
             
            module PassiveRecord
         
     | 
| 
       14 
19 
     | 
    
         
             
              def self.included(base)
         
     | 
| 
       15 
20 
     | 
    
         
             
                base.send :include, InstanceMethods
         
     | 
| 
         @@ -31,165 +36,4 @@ module PassiveRecord 
     | 
|
| 
       31 
36 
     | 
    
         
             
              def self.drop_all
         
     | 
| 
       32 
37 
     | 
    
         
             
                (model_classes + model_classes.flat_map(&:descendants)).each(&:destroy_all)
         
     | 
| 
       33 
38 
     | 
    
         
             
              end
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
              module InstanceMethods
         
     | 
| 
       36 
     | 
    
         
            -
                def inspect
         
     | 
| 
       37 
     | 
    
         
            -
                  pretty_vars = instance_variables_hash.map do |k,v|
         
     | 
| 
       38 
     | 
    
         
            -
                    "#{k.to_s.gsub(/^\@/,'')}: #{v.inspect}"
         
     | 
| 
       39 
     | 
    
         
            -
                  end.join(', ')
         
     | 
| 
       40 
     | 
    
         
            -
                  "#{self.class.name} (#{pretty_vars})"
         
     | 
| 
       41 
     | 
    
         
            -
                end
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                # from http://stackoverflow.com/a/8417341/90042
         
     | 
| 
       44 
     | 
    
         
            -
                def instance_variables_hash
         
     | 
| 
       45 
     | 
    
         
            -
                  Hash[
         
     | 
| 
       46 
     | 
    
         
            -
                    instance_variables.
         
     | 
| 
       47 
     | 
    
         
            -
                      reject { |sym| sym.to_s.start_with?("@_") }.
         
     | 
| 
       48 
     | 
    
         
            -
                      map { |name| [name, instance_variable_get(name)] }
         
     | 
| 
       49 
     | 
    
         
            -
                  ]
         
     | 
| 
       50 
     | 
    
         
            -
                end
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                def relata
         
     | 
| 
       53 
     | 
    
         
            -
                  @_relata ||= self.class.associations.map do |assn|
         
     | 
| 
       54 
     | 
    
         
            -
                    assn.to_relation(self)
         
     | 
| 
       55 
     | 
    
         
            -
                  end
         
     | 
| 
       56 
     | 
    
         
            -
                end
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                def find_relation_by_target_name_symbol(meth)
         
     | 
| 
       60 
     | 
    
         
            -
                  relata.detect do |relation|  # matching relation...
         
     | 
| 
       61 
     | 
    
         
            -
                    meth == relation.association.target_name_symbol ||
         
     | 
| 
       62 
     | 
    
         
            -
                      meth.to_s == relation.association.target_name_symbol.to_s + "=" ||
         
     | 
| 
       63 
     | 
    
         
            -
                      meth.to_s == relation.association.target_name_symbol.to_s + "_id" ||
         
     | 
| 
       64 
     | 
    
         
            -
                      meth.to_s == relation.association.target_name_symbol.to_s + "_id=" ||
         
     | 
| 
       65 
     | 
    
         
            -
                      meth.to_s == "create_" + relation.association.target_name_symbol.to_s ||
         
     | 
| 
       66 
     | 
    
         
            -
                      meth.to_s == "create_" + (relation.association.target_name_symbol.to_s).singularize
         
     | 
| 
       67 
     | 
    
         
            -
                  end
         
     | 
| 
       68 
     | 
    
         
            -
                end
         
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
                def respond_to?(meth,*args,&blk)
         
     | 
| 
       71 
     | 
    
         
            -
                  if find_relation_by_target_name_symbol(meth)
         
     | 
| 
       72 
     | 
    
         
            -
                    true
         
     | 
| 
       73 
     | 
    
         
            -
                  else
         
     | 
| 
       74 
     | 
    
         
            -
                    super(meth,*args,&blk)
         
     | 
| 
       75 
     | 
    
         
            -
                  end
         
     | 
| 
       76 
     | 
    
         
            -
                end
         
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
                def method_missing(meth, *args, &blk)
         
     | 
| 
       79 
     | 
    
         
            -
                  matching_relation = find_relation_by_target_name_symbol(meth)
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
                  if matching_relation
         
     | 
| 
       82 
     | 
    
         
            -
                    if meth.to_s == matching_relation.association.target_name_symbol.to_s + "_id"
         
     | 
| 
       83 
     | 
    
         
            -
                      matching_relation.parent_model_id
         
     | 
| 
       84 
     | 
    
         
            -
                    elsif meth.to_s.end_with?("_id=")
         
     | 
| 
       85 
     | 
    
         
            -
                      matching_relation.parent_model_id = args.first
         
     | 
| 
       86 
     | 
    
         
            -
                    elsif meth.to_s.end_with?("=")
         
     | 
| 
       87 
     | 
    
         
            -
                      matching_relation.parent_model_id = args.first.id
         
     | 
| 
       88 
     | 
    
         
            -
                    elsif meth.to_s.start_with?("create_")
         
     | 
| 
       89 
     | 
    
         
            -
                      matching_relation.create(*args)
         
     | 
| 
       90 
     | 
    
         
            -
                    else
         
     | 
| 
       91 
     | 
    
         
            -
                      # lookup the matching associated entities
         
     | 
| 
       92 
     | 
    
         
            -
                      matching_relation.lookup
         
     | 
| 
       93 
     | 
    
         
            -
                    end
         
     | 
| 
       94 
     | 
    
         
            -
                  else
         
     | 
| 
       95 
     | 
    
         
            -
                    super(meth,*args,&blk)
         
     | 
| 
       96 
     | 
    
         
            -
                  end
         
     | 
| 
       97 
     | 
    
         
            -
                end
         
     | 
| 
       98 
     | 
    
         
            -
              end
         
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
              module ClassMethods
         
     | 
| 
       101 
     | 
    
         
            -
                include PassiveRecord::Core
         
     | 
| 
       102 
     | 
    
         
            -
                include PassiveRecord::Associations
         
     | 
| 
       103 
     | 
    
         
            -
                include PassiveRecord::Hooks
         
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
                include Enumerable
         
     | 
| 
       106 
     | 
    
         
            -
                extend Forwardable
         
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
                # from http://stackoverflow.com/a/2393750/90042
         
     | 
| 
       109 
     | 
    
         
            -
                def descendants
         
     | 
| 
       110 
     | 
    
         
            -
                  ObjectSpace.each_object(Class).select { |klass| klass < self }
         
     | 
| 
       111 
     | 
    
         
            -
                end
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
                def all
         
     | 
| 
       114 
     | 
    
         
            -
                  instances_by_id.values
         
     | 
| 
       115 
     | 
    
         
            -
                end
         
     | 
| 
       116 
     | 
    
         
            -
                def_delegators :all, :each
         
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
                def last
         
     | 
| 
       119 
     | 
    
         
            -
                  all.last
         
     | 
| 
       120 
     | 
    
         
            -
                end
         
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
                def find(id_or_ids)
         
     | 
| 
       123 
     | 
    
         
            -
                  if id_or_ids.is_a?(Array)
         
     | 
| 
       124 
     | 
    
         
            -
                    find_by_ids(id_or_ids)
         
     | 
| 
       125 
     | 
    
         
            -
                  else
         
     | 
| 
       126 
     | 
    
         
            -
                    find_by_id(id_or_ids)
         
     | 
| 
       127 
     | 
    
         
            -
                  end
         
     | 
| 
       128 
     | 
    
         
            -
                end
         
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
                def find_by(conditions)
         
     | 
| 
       131 
     | 
    
         
            -
                  if conditions.is_a?(Identifier)
         
     | 
| 
       132 
     | 
    
         
            -
                    find_by_id(conditions)
         
     | 
| 
       133 
     | 
    
         
            -
                  elsif conditions.is_a?(Array) && conditions.all? { |c| c.is_a?(Identifier) }
         
     | 
| 
       134 
     | 
    
         
            -
                    find_by_ids(conditions)
         
     | 
| 
       135 
     | 
    
         
            -
                  else
         
     | 
| 
       136 
     | 
    
         
            -
                    where(conditions).first
         
     | 
| 
       137 
     | 
    
         
            -
                  end
         
     | 
| 
       138 
     | 
    
         
            -
                end
         
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
                def find_all_by(conditions)
         
     | 
| 
       141 
     | 
    
         
            -
                  if conditions.is_a?(Array) && conditions.all? { |c| c.is_a?(Identifier) }
         
     | 
| 
       142 
     | 
    
         
            -
                    find_by_ids(conditions)
         
     | 
| 
       143 
     | 
    
         
            -
                  else
         
     | 
| 
       144 
     | 
    
         
            -
                    where(conditions).all
         
     | 
| 
       145 
     | 
    
         
            -
                  end
         
     | 
| 
       146 
     | 
    
         
            -
                end
         
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
                def where(conditions)
         
     | 
| 
       149 
     | 
    
         
            -
                  Query.new(self, conditions)
         
     | 
| 
       150 
     | 
    
         
            -
                end
         
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
                def create(attrs={})
         
     | 
| 
       153 
     | 
    
         
            -
                  instance = new
         
     | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
       155 
     | 
    
         
            -
                  instance.singleton_class.class_eval { attr_accessor :id }
         
     | 
| 
       156 
     | 
    
         
            -
                  instance.send(:"id=", Identifier.generate(self))
         
     | 
| 
       157 
     | 
    
         
            -
             
     | 
| 
       158 
     | 
    
         
            -
                  register(instance)
         
     | 
| 
       159 
     | 
    
         
            -
             
     | 
| 
       160 
     | 
    
         
            -
                  attrs.each do |(k,v)|
         
     | 
| 
       161 
     | 
    
         
            -
                    instance.send("#{k}=", v)
         
     | 
| 
       162 
     | 
    
         
            -
                  end
         
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
                  after_create_hooks.each do |hook|
         
     | 
| 
       165 
     | 
    
         
            -
                    hook.run(instance)
         
     | 
| 
       166 
     | 
    
         
            -
                  end
         
     | 
| 
       167 
     | 
    
         
            -
             
     | 
| 
       168 
     | 
    
         
            -
                  instance
         
     | 
| 
       169 
     | 
    
         
            -
                end
         
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
     | 
    
         
            -
                def destroy_all
         
     | 
| 
       172 
     | 
    
         
            -
                  @instances = {}
         
     | 
| 
       173 
     | 
    
         
            -
                end
         
     | 
| 
       174 
     | 
    
         
            -
             
     | 
| 
       175 
     | 
    
         
            -
                protected
         
     | 
| 
       176 
     | 
    
         
            -
                def find_by_id(_id)
         
     | 
| 
       177 
     | 
    
         
            -
                  key = instances_by_id.keys.detect { |id,_| id == _id }
         
     | 
| 
       178 
     | 
    
         
            -
                  instances_by_id[key] if key
         
     | 
| 
       179 
     | 
    
         
            -
                end
         
     | 
| 
       180 
     | 
    
         
            -
             
     | 
| 
       181 
     | 
    
         
            -
                def find_by_ids(ids)
         
     | 
| 
       182 
     | 
    
         
            -
                  instances_by_id.select { |id,_| ids.include?(id) }.values
         
     | 
| 
       183 
     | 
    
         
            -
                end
         
     | 
| 
       184 
     | 
    
         
            -
             
     | 
| 
       185 
     | 
    
         
            -
                private
         
     | 
| 
       186 
     | 
    
         
            -
                def instances_by_id
         
     | 
| 
       187 
     | 
    
         
            -
                  @instances ||= {}
         
     | 
| 
       188 
     | 
    
         
            -
                end
         
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
                def register(model)
         
     | 
| 
       191 
     | 
    
         
            -
                  instances_by_id[model.id] = model
         
     | 
| 
       192 
     | 
    
         
            -
                  self
         
     | 
| 
       193 
     | 
    
         
            -
                end
         
     | 
| 
       194 
     | 
    
         
            -
              end
         
     | 
| 
       195 
39 
     | 
    
         
             
            end
         
     | 
    
        data/spec/passive_record_spec.rb
    CHANGED
    
    | 
         @@ -21,6 +21,12 @@ describe Model do 
     | 
|
| 
       21 
21 
     | 
    
         
             
                let!(:model) { SimpleModel.create(foo: value) }
         
     | 
| 
       22 
22 
     | 
    
         
             
                let(:value) { 'foo_value' }
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
      
 24 
     | 
    
         
            +
                describe "#inspect" do
         
     | 
| 
      
 25 
     | 
    
         
            +
                  it 'should report attribute details' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                    expect(model.inspect).to eq("SimpleModel (id: 1, foo: \"foo_value\")")
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
       24 
30 
     | 
    
         
             
                describe "#id" do
         
     | 
| 
       25 
31 
     | 
    
         
             
                  it 'should be retrievable by id' do
         
     | 
| 
       26 
32 
     | 
    
         
             
                    expect(SimpleModel.find_by(model.id)).to eq(model)
         
     | 
| 
         @@ -69,6 +75,27 @@ describe Model do 
     | 
|
| 
       69 
75 
     | 
    
         
             
                      expect(SimpleModel.find([model.id, model_b.id])).to eq([model, model_b])
         
     | 
| 
       70 
76 
     | 
    
         
             
                    end
         
     | 
| 
       71 
77 
     | 
    
         
             
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  describe "#where" do
         
     | 
| 
      
 80 
     | 
    
         
            +
                    it 'should return a query obj' do
         
     | 
| 
      
 81 
     | 
    
         
            +
                      expect(SimpleModel.where(id: 'fake_id')).to be_a(PassiveRecord::Core::Query)
         
     | 
| 
      
 82 
     | 
    
         
            +
                    end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                    context "queries" do
         
     | 
| 
      
 85 
     | 
    
         
            +
                      describe "#create" do
         
     | 
| 
      
 86 
     | 
    
         
            +
                      it 'should create objects' do
         
     | 
| 
      
 87 
     | 
    
         
            +
                        expect{SimpleModel.where(id: 'new_id').create }.to change{SimpleModel.count}.by(1)
         
     | 
| 
      
 88 
     | 
    
         
            +
                      end
         
     | 
| 
      
 89 
     | 
    
         
            +
                      end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                      describe "#first_or_create" do
         
     | 
| 
      
 92 
     | 
    
         
            +
                        it 'should create the object or return matching' do
         
     | 
| 
      
 93 
     | 
    
         
            +
                          expect{SimpleModel.where(id: 'another_id').first_or_create }.to change{SimpleModel.count}.by(1)
         
     | 
| 
      
 94 
     | 
    
         
            +
                          expect{SimpleModel.where(id: 'another_id').first_or_create }.not_to change{SimpleModel.count}
         
     | 
| 
      
 95 
     | 
    
         
            +
                        end
         
     | 
| 
      
 96 
     | 
    
         
            +
                      end
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
       72 
99 
     | 
    
         
             
                end
         
     | 
| 
       73 
100 
     | 
    
         | 
| 
       74 
101 
     | 
    
         
             
                context 'querying by attributes' do
         
     | 
| 
         @@ -157,6 +184,7 @@ describe Model do 
     | 
|
| 
       157 
184 
     | 
    
         | 
| 
       158 
185 
     | 
    
         
             
                    expect(child.id).not_to eq(another_child.id)
         
     | 
| 
       159 
186 
     | 
    
         
             
                    expect(parent.children).to eq([child, another_child])
         
     | 
| 
      
 187 
     | 
    
         
            +
                    expect(parent.children_ids).to eq([child.id, another_child.id])
         
     | 
| 
       160 
188 
     | 
    
         
             
                  end
         
     | 
| 
       161 
189 
     | 
    
         
             
                end
         
     | 
| 
       162 
190 
     | 
    
         | 
| 
         @@ -169,6 +197,7 @@ describe Model do 
     | 
|
| 
       169 
197 
     | 
    
         
             
                    expect(parent.dogs).to all(be_a(Dog))
         
     | 
| 
       170 
198 
     | 
    
         
             
                    expect(parent.dogs.count).to eq(1)
         
     | 
| 
       171 
199 
     | 
    
         
             
                    expect(parent.dogs.first).to eq(child.dogs.first)
         
     | 
| 
      
 200 
     | 
    
         
            +
                    expect(parent.dog_ids).to eq([child.dogs.first.id])
         
     | 
| 
       172 
201 
     | 
    
         
             
                  end
         
     | 
| 
       173 
202 
     | 
    
         | 
| 
       174 
203 
     | 
    
         
             
                  it 'should do the nested query example from the readme' do
         
     | 
| 
         @@ -228,4 +257,5 @@ describe Model do 
     | 
|
| 
       228 
257 
     | 
    
         
             
                  end
         
     | 
| 
       229 
258 
     | 
    
         
             
                end
         
     | 
| 
       230 
259 
     | 
    
         
             
              end
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
       231 
261 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: passive_record
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.7
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Joseph Weissman
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2016-02- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2016-02-22 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: bundler
         
     | 
| 
         @@ -140,9 +140,12 @@ files: 
     | 
|
| 
       140 
140 
     | 
    
         
             
            - lib/passive_record/associations/has_many_through.rb
         
     | 
| 
       141 
141 
     | 
    
         
             
            - lib/passive_record/associations/has_one.rb
         
     | 
| 
       142 
142 
     | 
    
         
             
            - lib/passive_record/class_inheritable_attrs.rb
         
     | 
| 
      
 143 
     | 
    
         
            +
            - lib/passive_record/class_methods.rb
         
     | 
| 
       143 
144 
     | 
    
         
             
            - lib/passive_record/core/identifier.rb
         
     | 
| 
       144 
145 
     | 
    
         
             
            - lib/passive_record/core/query.rb
         
     | 
| 
       145 
146 
     | 
    
         
             
            - lib/passive_record/hooks.rb
         
     | 
| 
      
 147 
     | 
    
         
            +
            - lib/passive_record/instance_methods.rb
         
     | 
| 
      
 148 
     | 
    
         
            +
            - lib/passive_record/pretty_printing.rb
         
     | 
| 
       146 
149 
     | 
    
         
             
            - lib/passive_record/version.rb
         
     | 
| 
       147 
150 
     | 
    
         
             
            - passive_record.gemspec
         
     | 
| 
       148 
151 
     | 
    
         
             
            - spec/passive_record_spec.rb
         
     |