lazy_record 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e001b11d0607098306b11994a55436e0f1ee6a9
4
- data.tar.gz: a38d5dc0d58a33665aaea2b3bedd7c7b22018f8a
3
+ metadata.gz: e834e5aa45c25ab443c4d34a59898f94be6c242f
4
+ data.tar.gz: ee98fd7313a9a99a61a2f359242c38a4d8f6fd2a
5
5
  SHA512:
6
- metadata.gz: aeadbadcb0ffe05bd58a86996734aebfe9f9e0cccdc89e428874857e1d2b51e83c3e9de4813956e69ae8886ca9bdb95427b87f5a9a3683f8dde8366f43e8cf23
7
- data.tar.gz: 262e1db0468746deb5c76300f5297159cca1aeea6e98b54d0e6a680e155ef6a49b768835a770e71fe2296d1059c4c62909210fa086af59e21e4ddae299a92577
6
+ metadata.gz: cf4f07d687c4998664c1f2a31e74b5dca56bd9b489e60478fc01c14d8d8f956510e42c15eedc72f4e1f6837a97d55ca42d5bb54fa1621e7533e93e5b8fc60c42
7
+ data.tar.gz: eb64a330301f566edace26f5375af57ae1a2c9fdc509d772d55d6b7edb95fd613a9aaafb5d39e3f5f972be12c23b68c42127879dff0300bfb00b89496395e36d
data/.rubocop.yml CHANGED
@@ -3,3 +3,6 @@ Metrics/LineLength:
3
3
  Exclude:
4
4
  - 'lazy_record.gemspec'
5
5
  - 'spec/spec_helper.rb'
6
+
7
+ Lint/AmbiguousBlockAssociation:
8
+ Enabled: false
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  source 'https://rubygems.org'
3
4
 
4
5
  # Specify your gem's dependencies in lazy_record.gemspec
data/README.md CHANGED
@@ -123,13 +123,13 @@ thing.whatevers
123
123
  # => #<WhateverRelation [#<Whatever>]>
124
124
  ```
125
125
 
126
- Use `lr_scope` and `#where` to create class scope methods and query objects. Works just like ActiveRecord scopes, including scope chaining. Only since it is all Ruby and no SQL, use `==` as the comparison operator.
126
+ Use `lr_scope` and `#where` to create class scope methods and query objects.
127
127
 
128
128
  ```ruby
129
129
  class Whatever < LazyRecord::Base
130
130
  attr_accessor :party_value, :sleepy_value
131
- lr_scope :big_party, -> { where('party_value > 10') }
132
- lr_scope :low_sleepy, -> { where('sleepy_value < 10') }
131
+ lr_scope :big_party, -> { where { |w| w.party_value > 10 } }
132
+ lr_scope :low_sleepy, -> { where { |w| w.sleepy_value < 10 } }
133
133
  end
134
134
 
135
135
  class Thing < LazyRecord::Base
@@ -160,7 +160,7 @@ thing.whatevers.big_party.low_sleepy
160
160
  Whatever.low_sleepy
161
161
  # => #<WhateverRelation [#<Whatever party_value: 13, sleepy_value: 3>, #<Whatever id: 4, party_value: 3, sleepy_value: 5>]>
162
162
 
163
- Whatever.where('party_value == 12')
163
+ Whatever.where party_value: 12
164
164
  # => #<WhateverRelation [#<Whatever party_value: 12, sleepy_value: 12>
165
165
  ```
166
166
  You can also use hash syntax and block syntax with `.where`. Block syntax will yield each object in the collection to the block for evaluation.
@@ -180,33 +180,29 @@ num = 6
180
180
  Whatever.where party_value: -> { num * 2 }
181
181
  # => #<WhateverRelation [#<Whatever party_value: 12, sleepy_value: 12>]>
182
182
  ```
183
- Use `lr_method` for an alternative API for defining short instance methods. Can use lambda syntax or string syntax. Best for quick one-liners. If the method references `self` of the instance, either explicitly or implicitly, it needs to use the string syntax, since anything passed into the lambda will be evaluated in the context of the Class level scope.
183
+ Use `lr_method` for an alternative API for defining short instance methods using lambda syntax. The first argument passed to the block must be the receiver of the method, or `self` in the method scope.
184
184
 
185
185
  ```ruby
186
186
  class Whatever < LazyRecord::Base
187
187
  attr_accessor :party_value, :sleepy_value, :right
188
- lr_scope :big_party, -> { where('party_value > 10') }
189
- lr_scope :low_sleepy, -> { where('sleepy_value < 10') }
188
+ lr_scope :big_party, -> { where { |w| w.party_value > 10 } }
189
+ lr_scope :low_sleepy, -> { where { |w| w.sleepy_value < 10 } }
190
190
  end
191
191
 
192
192
  class Thing < LazyRecord::Base
193
193
  attr_accessor :stuff, :junk
194
194
  lr_validates :stuff, presence: true
195
195
  lr_has_many :whatevers
196
- lr_method :speak, -> (string) { puts string }
197
- lr_method :add_whatever, 'right', 'whatevers << Whatever.new(right: right)'
196
+ lr_method :speak, -> (_x, string) { puts string }
197
+ lr_method :what_am_i, ->(x) { "I'm a #{x.class}" }
198
198
  end
199
199
 
200
200
  thing = Thing.new stuff: 'stuff'
201
201
  thing.speak "I'm a thing"
202
202
  # I'm a thing
203
203
  # => nil
204
-
205
- thing.add_whatever(true)
206
- # => [#<Whatever party_value: nil, sleepy_value: nil, right: true>]
207
-
208
- thing.whatevers
209
- # => #<WhateverRelation [#<Whatever party_value: nil, sleepy_value: nil, right: true>]>
204
+ thing.what_am_i
205
+ # => "I'm a Thing"
210
206
  ```
211
207
 
212
208
  ## Development
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'bundler/gem_tasks'
3
4
  require 'rspec/core/rake_task'
4
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  example = File.expand_path('../../example', __FILE__)
2
4
  $LOAD_PATH.unshift(example) unless $LOAD_PATH.include?(example)
3
5
  lib = File.expand_path('../lib', __FILE__)
data/lazy_record.gemspec CHANGED
@@ -1,5 +1,6 @@
1
1
  # coding: utf-8
2
2
  # frozen_string_literal: true
3
+
3
4
  lib = File.expand_path('../lib', __FILE__)
4
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
6
  require 'lazy_record/version'
data/lib/lazy_record.rb CHANGED
@@ -1,5 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Copyright (c) 2017 M. Simon Borg
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
3
23
  require 'active_support'
4
24
  require 'active_support/inflector'
5
25
  require 'scoped_attr_accessor'
@@ -18,5 +38,19 @@ require 'lazy_record/relation'
18
38
  require 'lazy_record/base_module'
19
39
  require 'lazy_record/base'
20
40
 
21
- # Namespace
41
+ # A collection of convenience methods for adding enhanced constructors,
42
+ # attributes, one-to-many collections, one-to-one associations, scopes,
43
+ # methods, and basic validations. Get a lot done with a little code.
44
+ #
45
+ # Inherit from LazyRecord::Base or include LazyRecord::BaseModule to
46
+ # unlock the features. The primary use case in mind is a toolkit
47
+ # for designing response objects for web API wrappers. Two
48
+ # other gems in progress that are using LazyRecord for this purpose are
49
+ # <tt>pyr</tt>(https://www.github.com/msimonborg/pyr) (Ruby interface
50
+ # for Phone Your Rep, a civic tool), and
51
+ # <tt>lapi</tt>(https://www.github.com/msimonborg/lapi), an API wrapper
52
+ # building tool with the goal of easing the construction of simple
53
+ # Ruby API wrappers.
54
+ #
55
+ # This library's API draws heavy inspiration from ActiveRecord.
22
56
  module LazyRecord; end
@@ -27,6 +27,47 @@ module LazyRecord
27
27
  yield self if block_given?
28
28
  end
29
29
 
30
+ def inspect
31
+ format('#<%s%s>',
32
+ self.class,
33
+ displayable_attributes.join(', '))
34
+ end
35
+
36
+ def associations
37
+ []
38
+ end
39
+
40
+ def collections
41
+ []
42
+ end
43
+
44
+ def ==(other)
45
+ conditions = set_equality_conditions
46
+ return false if !other.is_a?(self.class) || conditions.empty?
47
+ conditions.all? { |attr| send(attr) == other.send(attr) }
48
+ end
49
+
50
+ def ===(other)
51
+ conditions = set_equality_conditions
52
+ return false if !other.is_a?(self.class) || conditions.empty?
53
+ # rubocop:disable Style/CaseEquality
54
+ conditions.all? { |attr| send(attr) === other.send(attr) }
55
+ # rubocop:enable Style/CaseEquality
56
+ end
57
+
58
+ def hash
59
+ conditions = set_equality_conditions
60
+ hash = {}
61
+ conditions.each { |attr| hash[attr] = send(attr) }
62
+ hash.hash
63
+ end
64
+
65
+ alias eql? ==
66
+
67
+ def set_equality_conditions
68
+ self.class.send(:attr_readers) + associations
69
+ end
70
+
30
71
  def collection_counts_to_s
31
72
  []
32
73
  end
@@ -43,12 +84,6 @@ module LazyRecord
43
84
  []
44
85
  end
45
86
 
46
- def inspect
47
- format('#<%s%s>',
48
- self.class,
49
- displayable_attributes.join(', '))
50
- end
51
-
52
87
  def displayable_attributes
53
88
  attributes = [
54
89
  public_attr_readers_to_s.dup,
@@ -69,9 +104,12 @@ module LazyRecord
69
104
  end
70
105
  end
71
106
 
72
- private :stringify_value,
107
+ private :displayable_attributes,
108
+ :stringify_value,
73
109
  :public_attr_readers_to_s,
74
- :collection_counts_to_s
110
+ :collection_counts_to_s,
111
+ :associations_to_s,
112
+ :set_equality_conditions
75
113
 
76
114
  # Class methods provided to all LazyRecord classes
77
115
  module ClassMethods
@@ -5,28 +5,12 @@ module LazyRecord
5
5
  module Methods
6
6
  METHODS_MODULE_NAME = :DynamicMethods
7
7
 
8
- def lr_method(method_name, *method_args, method)
8
+ def lr_method(method_name, method)
9
9
  include mod = get_or_set_mod(METHODS_MODULE_NAME)
10
10
 
11
- if method.respond_to?(:call)
12
- make_method_from_proc(mod, method_name, method)
13
- else
14
- make_method_from_string(mod, method_name, *method_args, method)
15
- end
16
- end
17
-
18
- def make_method_from_proc(mod, method_name, proc)
19
- mod.module_eval do
20
- send(:define_method, method_name, &proc)
21
- end
22
- end
23
-
24
- def make_method_from_string(mod, method_name, *method_args, method)
25
- method_args = method_args.map(&:to_s).join(', ')
26
11
  mod.module_eval do
27
- define_method(method_name) do |*params|
28
- block = eval("lambda { |#{method_args}| #{method} }")
29
- block.call(*params)
12
+ define_method(method_name) do |*args|
13
+ method.call(self, *args)
30
14
  end
31
15
  end
32
16
  end
@@ -37,8 +37,6 @@ module LazyRecord
37
37
  select_by_hash_condition(condition, instance)
38
38
  elsif block_given?
39
39
  yield instance
40
- elsif condition
41
- eval "instance.#{condition}"
42
40
  end
43
41
  end
44
42
  self.class.new(model: model, array: result)
@@ -71,7 +69,7 @@ module LazyRecord
71
69
  all.clear
72
70
  end
73
71
 
74
- private :clear, :all
72
+ private :clear, :all, :select_by_hash_condition
75
73
 
76
74
  def self_extend_scopes_module
77
75
  return unless model.const_defined?(Scopes::SCOPE_MODULE_NAME,
@@ -7,8 +7,9 @@ module LazyRecord
7
7
 
8
8
  def lr_scope(method_name, lambda)
9
9
  extend mod = get_or_set_mod(SCOPE_MODULE_NAME)
10
+
10
11
  mod.module_eval do
11
- send(:define_method, method_name, &lambda)
12
+ define_method(method_name, &lambda)
12
13
  end
13
14
  end
14
15
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LazyRecord
4
- VERSION = '0.5.0'
4
+ VERSION = '0.6.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lazy_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - M. Simon Borg