lazy_record 0.1.3 → 0.1.4
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/.ruby-version +1 -1
- data/README.md +15 -3
- data/Rakefile +4 -0
- data/bin/console +1 -2
- data/example/cat.rb +2 -0
- data/example/dog.rb +3 -1
- data/example/friend.rb +2 -0
- data/example/person.rb +12 -6
- data/lib/lazy_record.rb +2 -0
- data/lib/lazy_record/associations.rb +35 -25
- data/lib/lazy_record/attributes.rb +52 -33
- data/lib/lazy_record/base.rb +2 -52
- data/lib/lazy_record/base_module.rb +70 -0
- data/lib/lazy_record/callbacks.rb +18 -21
- data/lib/lazy_record/dynamic_modules.rb +3 -4
- data/lib/lazy_record/methods.rb +6 -15
- data/lib/lazy_record/relation.rb +25 -12
- data/lib/lazy_record/scopes.rb +2 -7
- data/lib/lazy_record/validations.rb +18 -17
- data/lib/lazy_record/version.rb +2 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f711b308e8306e2e5425614a25e6d8fe12377f38
|
4
|
+
data.tar.gz: 55ec6ec6d27afffae565d3a81723a514d07289cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a45dc9392a008a3e51425616b0742627f25f9a9d8980bd0bcc44f56da7a2181709b7bbfb302c2ce7f0c7702896aa50cc889f74e4b359c129e1586d5d8251b9f
|
7
|
+
data.tar.gz: 77945dd63bae3e6344fd66eb72552c12579a9aced18c75fbb3e5ea994c1b8356f48c3d7a77adf94f11c6d270d7aa49bd41355cc15806ee21ee0dae2bd0b55e66
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.4.
|
1
|
+
ruby-2.4.1
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# LazyRecord
|
2
|
+
[](https://codeclimate.com/github/msimonborg/lazy_record)
|
2
3
|
|
3
4
|
LazyRecord writes a bunch of boilerplate code for your POROs, similarly to what you'd expect ActiveRecord to do for your database-backed objects. This project is an attempt to understand and explore dynamic programming techniques in Ruby, and demystify some of the Rails magic. Maybe someone will find it useful.
|
4
5
|
|
@@ -26,9 +27,20 @@ All objects that inherit from `LazyRecord::Base` get block syntax added to their
|
|
26
27
|
class Thing < LazyRecord::Base
|
27
28
|
end
|
28
29
|
|
29
|
-
thing = Thing.new
|
30
|
-
|
30
|
+
thing = Thing.new { |t| puts t.class.superclass }
|
31
|
+
# LazyRecord::Base
|
32
|
+
# => #<Thing id: 1>
|
33
|
+
```
|
34
|
+
|
35
|
+
Alternatively, if you want to inherit from another class, you can mix in the `LazyRecord::BaseModule` and get all the same results.
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
class Thing
|
39
|
+
include LazyRecord::BaseModule
|
31
40
|
end
|
41
|
+
|
42
|
+
thing = Thing.new { |t| puts t.class.superclass }
|
43
|
+
# Object
|
32
44
|
# => #<Thing id: 1>
|
33
45
|
```
|
34
46
|
Every LazyRecord object is assigned an auto-incrementing ID after initialization. IDs reset when the program is terminated.
|
@@ -126,7 +138,7 @@ Whatever.where('id == 1')
|
|
126
138
|
# => #<WhateverRelation [#<Whatever id: 1, party_value: 12, sleepy_value: 12>
|
127
139
|
```
|
128
140
|
|
129
|
-
Use `lr_method` for an alternative API for defining short instance methods. Can use lambda syntax or string syntax.
|
141
|
+
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.
|
130
142
|
|
131
143
|
```ruby
|
132
144
|
class Whatever < LazyRecord::Base
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -4,12 +4,11 @@
|
|
4
4
|
require 'bundler/setup'
|
5
5
|
require_relative '../config/environment'
|
6
6
|
|
7
|
-
|
8
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
9
8
|
# with your gem easier. You can also use a different console, if you like.
|
10
9
|
|
11
10
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
12
|
-
require
|
11
|
+
require 'pry'
|
13
12
|
Pry.start
|
14
13
|
|
15
14
|
# require 'irb'
|
data/example/cat.rb
CHANGED
data/example/dog.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Example class
|
1
3
|
class Dog < LazyRecord::Base
|
2
4
|
lr_attr_accessor :name, :breed, :weight
|
3
5
|
lr_has_many :friends
|
4
6
|
|
5
7
|
def initialize(opts = {}, &block)
|
6
8
|
super
|
7
|
-
|
9
|
+
friends << Friend.new(opts) if opts[:friend] == true
|
8
10
|
self.name = name + 'y' if opts[:cute] == true
|
9
11
|
end
|
10
12
|
end
|
data/example/friend.rb
CHANGED
data/example/person.rb
CHANGED
@@ -1,23 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Example class
|
1
3
|
class Person < LazyRecord::Base
|
2
4
|
lr_attr_accessor :name, :age, :haircut
|
3
5
|
lr_has_many :dogs, :cats
|
4
6
|
lr_accepts_nested_attributes_for :dogs, :cats
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
lr_scope :new_with_dog, ->(opts = {}) {
|
8
|
+
lr_scope :new_with_dog, lambda { |opts = {}|
|
9
9
|
opts[:dog] = {} unless opts[:dog]
|
10
|
-
|
10
|
+
new(opts) { |p| p.adopt_a_dog(opts[:dog]) }
|
11
11
|
}
|
12
12
|
lr_scope :young, -> { where('age < 30') }
|
13
|
-
lr_scope :
|
13
|
+
lr_scope :old, -> { where('age > 30') }
|
14
|
+
lr_scope :short_hair, -> { where(haircut: 'short') }
|
14
15
|
|
15
|
-
lr_method :speak, ->
|
16
|
+
lr_method :speak, ->(string) { puts string }
|
16
17
|
lr_method :add_dog, :name, 'dogs << Dog.new(name: name)'
|
17
18
|
lr_method :introduce_yourself, 'puts "Hello, my name is #{name}"'
|
18
19
|
|
19
20
|
lr_validates :name, :age, presence: true
|
20
21
|
|
22
|
+
def self.new(opts = {}, &block)
|
23
|
+
puts 'hi'
|
24
|
+
super opts, &block
|
25
|
+
end
|
26
|
+
|
21
27
|
def self.make_people(*args, &block)
|
22
28
|
opts = args.extract_options!
|
23
29
|
|
data/lib/lazy_record.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'active_support'
|
3
4
|
require 'active_support/inflector'
|
4
5
|
require 'lazy_record/version'
|
@@ -10,6 +11,7 @@ require 'lazy_record/methods'
|
|
10
11
|
require 'lazy_record/scopes'
|
11
12
|
require 'lazy_record/validations'
|
12
13
|
require 'lazy_record/relation'
|
14
|
+
require 'lazy_record/base_module'
|
13
15
|
require 'lazy_record/base'
|
14
16
|
|
15
17
|
# Namespace
|
@@ -1,46 +1,56 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LazyRecord
|
3
4
|
# Set up in-memory associations between POROs.
|
4
5
|
module Associations
|
5
6
|
COLLECTION_MODULE_NAME = :Collections
|
6
7
|
NESTED_ATTRS_MODULE_NAME = :NestedAttributes
|
7
8
|
|
8
|
-
def
|
9
|
-
|
9
|
+
def define_collection_getter(collection, class_name)
|
10
|
+
define_method(collection) do
|
11
|
+
if instance_variable_get("@#{collection}").nil?
|
12
|
+
instance_variable_set("@#{collection}", Relation.new(model: class_name))
|
13
|
+
end
|
14
|
+
instance_variable_get("@#{collection}")
|
15
|
+
end
|
16
|
+
end
|
10
17
|
|
18
|
+
def define_collection_setter(collection, class_name)
|
19
|
+
define_method("#{collection}=") do |coll|
|
20
|
+
coll = Relation.new(model: class_name, array: coll) if coll.is_a?(Array)
|
21
|
+
return instance_variable_set("@#{collection}", coll) if coll.is_a? Relation
|
22
|
+
raise ArgumentError, "Argument must be a collection of #{collection}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def lr_has_many(*collections)
|
27
|
+
include mod = get_or_set_mod(COLLECTION_MODULE_NAME)
|
28
|
+
mod.extend(Associations)
|
11
29
|
mod.module_eval do
|
12
30
|
collections.each do |collection|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
31
|
+
class_name = collection.to_s.classify.constantize
|
32
|
+
define_collection_getter(collection, class_name)
|
33
|
+
define_collection_setter(collection, class_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
17
37
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if coll.is_a? Relation
|
23
|
-
instance_variable_set('@' + collection.to_s, coll)
|
24
|
-
else
|
25
|
-
raise ArgumentError, "Argument must be a collection of #{collection}"
|
26
|
-
end
|
27
|
-
end
|
38
|
+
def define_association_attributes_setter(collection, class_name)
|
39
|
+
define_method("#{collection}_attributes=") do |collection_attributes|
|
40
|
+
collection_attributes.values.each do |attributes|
|
41
|
+
send(collection) << class_name.new(attributes)
|
28
42
|
end
|
43
|
+
collection
|
29
44
|
end
|
30
45
|
end
|
31
46
|
|
32
47
|
def lr_accepts_nested_attributes_for(*collections)
|
33
|
-
mod =
|
34
|
-
|
48
|
+
include mod = get_or_set_mod(NESTED_ATTRS_MODULE_NAME)
|
49
|
+
mod.extend(Associations)
|
35
50
|
mod.module_eval do
|
36
51
|
collections.each do |collection|
|
37
|
-
|
38
|
-
|
39
|
-
collection_attributes.values.each do |attributes|
|
40
|
-
eval "@#{collection} << #{class_name}.new(attributes)"
|
41
|
-
end
|
42
|
-
collection
|
43
|
-
end
|
52
|
+
class_name = collection.to_s.classify.constantize
|
53
|
+
define_association_attributes_setter(collection, class_name)
|
44
54
|
end
|
45
55
|
end
|
46
56
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LazyRecord
|
3
4
|
# Add special attr_accessors that automatically add initialization options
|
4
5
|
# to your initialize method. Using lr_attr_accessor, you automatically get
|
@@ -8,48 +9,66 @@ module LazyRecord
|
|
8
9
|
module Attributes
|
9
10
|
ATTR_MODULE_NAME = :DynamicAttributes
|
10
11
|
|
11
|
-
def
|
12
|
-
|
12
|
+
def define_setters_and_getters(name)
|
13
|
+
define_method(name) do
|
14
|
+
instance_variable_get('@' + name.to_s)
|
15
|
+
end
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
define_method("#{name}=") do |val|
|
21
|
-
instance_variable_set('@' + name.to_s, val)
|
22
|
-
end
|
23
|
-
end
|
17
|
+
define_method("#{name}=") do |val|
|
18
|
+
instance_variable_set('@' + name.to_s, val)
|
19
|
+
end
|
20
|
+
end
|
24
21
|
|
25
|
-
|
26
|
-
|
22
|
+
def define_initialize
|
23
|
+
define_method(:initialize) do |opts = {}, &block|
|
24
|
+
instance_attr_accessors.each do |attr|
|
25
|
+
send("#{attr}=", opts[attr.to_sym])
|
27
26
|
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
block&.call self
|
29
|
+
self
|
30
|
+
end
|
31
|
+
end
|
33
32
|
|
34
|
-
|
35
|
-
|
33
|
+
def define_instance_attrs_to_s
|
34
|
+
define_method(:instance_attrs_to_s) do
|
35
|
+
instance_attr_accessors.map do |attr|
|
36
|
+
value = send(attr)
|
37
|
+
attr_to_s = stringify_value(value)
|
38
|
+
"#{attr.to_s.delete(':')}: #{attr_to_s}"
|
36
39
|
end
|
40
|
+
end
|
41
|
+
private :instance_attrs_to_s
|
42
|
+
end
|
37
43
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
value
|
47
|
-
end
|
48
|
-
"#{attr.to_s.delete(':')}: #{attr_to_s}"
|
49
|
-
end
|
44
|
+
def define_stringify_value
|
45
|
+
define_method(:stringify_value) do |value|
|
46
|
+
if value.is_a?(String)
|
47
|
+
"\"#{value}\""
|
48
|
+
elsif value.nil?
|
49
|
+
'nil'
|
50
|
+
else
|
51
|
+
value
|
50
52
|
end
|
53
|
+
end
|
54
|
+
end
|
51
55
|
|
52
|
-
|
56
|
+
def define_instance_attr_accessors(*names)
|
57
|
+
define_method(:instance_attr_accessors) do
|
58
|
+
names.map(&:to_sym)
|
59
|
+
end
|
60
|
+
private :instance_attr_accessors
|
61
|
+
end
|
62
|
+
|
63
|
+
def lr_attr_accessor(*names)
|
64
|
+
include mod = get_or_set_mod(ATTR_MODULE_NAME)
|
65
|
+
mod.extend(Attributes)
|
66
|
+
mod.module_eval do
|
67
|
+
names.each { |name| define_setters_and_getters(name) }
|
68
|
+
define_instance_attr_accessors(*names)
|
69
|
+
define_initialize
|
70
|
+
define_instance_attrs_to_s
|
71
|
+
define_stringify_value
|
53
72
|
end
|
54
73
|
end
|
55
74
|
end
|
data/lib/lazy_record/base.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LazyRecord
|
3
4
|
# Inherit from LazyRecord::Base to achieve lazier development.
|
4
5
|
#
|
@@ -7,57 +8,6 @@ module LazyRecord
|
|
7
8
|
# method generating macros, scope methods and scope chaining, associations
|
8
9
|
# with other objects, and validations. This is a WIP still in development.
|
9
10
|
class Base
|
10
|
-
|
11
|
-
extend Attributes
|
12
|
-
extend Associations
|
13
|
-
extend Callbacks
|
14
|
-
extend Validations
|
15
|
-
extend Methods
|
16
|
-
extend DynamicModules
|
17
|
-
|
18
|
-
class << self
|
19
|
-
attr_reader :all
|
20
|
-
end
|
21
|
-
|
22
|
-
attr_writer :id
|
23
|
-
|
24
|
-
def self.count
|
25
|
-
@all.count
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.first
|
29
|
-
@all.first
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.last
|
33
|
-
@all.last
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.where(condition)
|
37
|
-
@all.where(condition)
|
38
|
-
end
|
39
|
-
|
40
|
-
def initialize(_opts = {})
|
41
|
-
yield self if block_given?
|
42
|
-
end
|
43
|
-
|
44
|
-
def instance_attrs_to_s
|
45
|
-
[]
|
46
|
-
end
|
47
|
-
|
48
|
-
def instance_attr_accessors
|
49
|
-
[]
|
50
|
-
end
|
51
|
-
|
52
|
-
def id
|
53
|
-
@id.freeze
|
54
|
-
end
|
55
|
-
|
56
|
-
private :id=
|
57
|
-
|
58
|
-
def inspect
|
59
|
-
"#<#{self.class} id: #{id ? id : 'nil'}"\
|
60
|
-
"#{instance_attrs_to_s.unshift('').join(', ')}>"
|
61
|
-
end
|
11
|
+
include BaseModule
|
62
12
|
end
|
63
13
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LazyRecord
|
4
|
+
# This module gives the Base class its functionality, and can be included
|
5
|
+
# in any class as an alternative to inheriting from LazyRecord::Base
|
6
|
+
module BaseModule
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(
|
9
|
+
ClassMethods,
|
10
|
+
Scopes,
|
11
|
+
Attributes,
|
12
|
+
Associations,
|
13
|
+
Callbacks,
|
14
|
+
Validations,
|
15
|
+
Methods,
|
16
|
+
DynamicModules
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_writer :id
|
21
|
+
|
22
|
+
def initialize(_opts = {})
|
23
|
+
yield self if block_given?
|
24
|
+
end
|
25
|
+
|
26
|
+
def instance_attrs_to_s
|
27
|
+
[]
|
28
|
+
end
|
29
|
+
|
30
|
+
def instance_attr_accessors
|
31
|
+
[]
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspect
|
35
|
+
"#<#{self.class} id: #{id ? id : 'nil'}"\
|
36
|
+
"#{instance_attrs_to_s.unshift('').join(', ')}>"
|
37
|
+
end
|
38
|
+
|
39
|
+
def id
|
40
|
+
@id.freeze
|
41
|
+
end
|
42
|
+
|
43
|
+
private :id=
|
44
|
+
|
45
|
+
# Class methods provided to all LazyRecord classes
|
46
|
+
module ClassMethods
|
47
|
+
attr_reader :all
|
48
|
+
|
49
|
+
def count
|
50
|
+
@all.count
|
51
|
+
end
|
52
|
+
|
53
|
+
def first
|
54
|
+
@all.first
|
55
|
+
end
|
56
|
+
|
57
|
+
def last
|
58
|
+
@all.last
|
59
|
+
end
|
60
|
+
|
61
|
+
def where(condition)
|
62
|
+
@all.where(condition)
|
63
|
+
end
|
64
|
+
|
65
|
+
def destroy_all
|
66
|
+
@all.send(:clear)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -1,30 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'lazy_record/dynamic_modules'
|
4
|
+
|
2
5
|
module LazyRecord
|
3
6
|
# After #initialize callbacks for validations and setting object id.
|
4
7
|
module Callbacks
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
instance = instance.validation(*@validations)
|
14
|
-
end
|
15
|
-
add_id(instance)
|
16
|
-
end
|
17
|
-
|
18
|
-
def add_id(instance)
|
19
|
-
if instance
|
20
|
-
all << instance
|
21
|
-
instance.send(:id=, count)
|
22
|
-
end
|
23
|
-
instance
|
24
|
-
end
|
8
|
+
def new(opts = {}, &block)
|
9
|
+
@all ||= Relation.new(model: self)
|
10
|
+
instance = super(opts, &block)
|
11
|
+
if instance.respond_to?(:validation)
|
12
|
+
instance = instance.validation(*@validations)
|
13
|
+
end
|
14
|
+
add_id(instance)
|
15
|
+
end
|
25
16
|
|
26
|
-
|
17
|
+
def add_id(instance)
|
18
|
+
if instance
|
19
|
+
all << instance
|
20
|
+
instance.send(:id=, count)
|
27
21
|
end
|
22
|
+
instance
|
28
23
|
end
|
24
|
+
|
25
|
+
private :add_id
|
29
26
|
end
|
30
27
|
end
|
@@ -1,16 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LazyRecord
|
3
4
|
# Generate dynamic modules for dynamic methods created with #define_method,
|
4
5
|
# for insertion into inheritance chain. This allows you to make calls to
|
5
6
|
# super for these methods.
|
6
7
|
module DynamicModules
|
7
|
-
def
|
8
|
+
def get_or_set_mod(module_name)
|
8
9
|
if const_defined?(module_name, _search_ancestors = false)
|
9
10
|
const_get(module_name)
|
10
11
|
else
|
11
|
-
|
12
|
-
include mod
|
13
|
-
mod # return the Module for variable assignment.
|
12
|
+
const_set(module_name, Module.new)
|
14
13
|
end
|
15
14
|
end
|
16
15
|
end
|
data/lib/lazy_record/methods.rb
CHANGED
@@ -1,27 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LazyRecord
|
3
4
|
# Macro for dynamic instance method generation. Best to use for one-liners.
|
4
5
|
module Methods
|
5
6
|
METHODS_MODULE_NAME = :DynamicMethods
|
6
7
|
|
7
|
-
def can_multiply
|
8
|
-
mod = get_or_set_and_include_mod(METHODS_MODULE_NAME)
|
9
|
-
|
10
|
-
mod.module_eval do
|
11
|
-
define_method(:multiply) do |num1, num2|
|
12
|
-
num1 * num2
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
8
|
def lr_method(method_name, *method_args, method)
|
18
|
-
mod
|
19
|
-
|
20
|
-
|
9
|
+
include mod = get_or_set_mod(METHODS_MODULE_NAME)
|
10
|
+
|
21
11
|
if method.respond_to?(:call)
|
22
12
|
make_method_from_proc(mod, method_name, method)
|
23
13
|
else
|
24
|
-
make_method_from_string(mod, method_name, method_args, method)
|
14
|
+
make_method_from_string(mod, method_name, *method_args, method)
|
25
15
|
end
|
26
16
|
end
|
27
17
|
|
@@ -31,7 +21,8 @@ module LazyRecord
|
|
31
21
|
end
|
32
22
|
end
|
33
23
|
|
34
|
-
def make_method_from_string(mod, method_name, method_args, method)
|
24
|
+
def make_method_from_string(mod, method_name, *method_args, method)
|
25
|
+
method_args = method_args.map(&:to_s).join(', ')
|
35
26
|
mod.module_eval do
|
36
27
|
define_method(method_name) do |*params|
|
37
28
|
block = eval("lambda { |#{method_args}| #{method} }")
|
data/lib/lazy_record/relation.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LazyRecord
|
3
4
|
class Relation
|
4
5
|
include Enumerable
|
@@ -6,19 +7,21 @@ module LazyRecord
|
|
6
7
|
attr_reader :model, :all
|
7
8
|
|
8
9
|
def initialize(model:, array: nil)
|
9
|
-
raise ArgumentError,
|
10
|
+
raise ArgumentError, 'model must be a class' unless model.is_a?(Class)
|
10
11
|
@model = model
|
11
12
|
@all = []
|
12
13
|
self_extend_scopes_module
|
13
|
-
array
|
14
|
+
array&.each do |object|
|
15
|
+
@all << object && next if object.is_a?(model)
|
16
|
+
message = "Argument must be a collection of #{model.to_s.tableize}"
|
17
|
+
raise ArgumentError, message
|
18
|
+
end
|
14
19
|
end
|
15
20
|
|
16
21
|
def <<(other)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
all << other
|
21
|
-
end
|
22
|
+
message = "object must be of type #{model}"
|
23
|
+
raise ArgumentError, message unless other.is_a?(model)
|
24
|
+
all << other
|
22
25
|
end
|
23
26
|
|
24
27
|
def inspect
|
@@ -26,7 +29,13 @@ module LazyRecord
|
|
26
29
|
end
|
27
30
|
|
28
31
|
def where(condition)
|
29
|
-
result = all.select
|
32
|
+
result = all.select do |x|
|
33
|
+
if condition.is_a? Hash
|
34
|
+
condition.all? { |key, val| x.send(key) == val }
|
35
|
+
else
|
36
|
+
eval "x.#{condition}"
|
37
|
+
end
|
38
|
+
end
|
30
39
|
self.class.new(model: model, array: result)
|
31
40
|
end
|
32
41
|
|
@@ -42,11 +51,15 @@ module LazyRecord
|
|
42
51
|
self[-1]
|
43
52
|
end
|
44
53
|
|
54
|
+
def clear
|
55
|
+
all.clear
|
56
|
+
end
|
57
|
+
|
58
|
+
private :clear, :all
|
59
|
+
|
45
60
|
def self_extend_scopes_module
|
46
|
-
|
47
|
-
|
48
|
-
extend(mod)
|
49
|
-
end
|
61
|
+
return unless model.const_defined?(:ScopeMethods, _search_ancestors = false)
|
62
|
+
extend(model::ScopeMethods)
|
50
63
|
end
|
51
64
|
end
|
52
65
|
end
|
data/lib/lazy_record/scopes.rb
CHANGED
@@ -1,17 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LazyRecord
|
3
4
|
# Add ActiveRecord-style scope macros to your classes. Allows chaining.
|
4
5
|
module Scopes
|
5
6
|
SCOPE_MODULE_NAME = :ScopeMethods
|
6
7
|
|
7
8
|
def lr_scope(method_name, lambda)
|
8
|
-
|
9
|
-
mod = const_get(SCOPE_MODULE_NAME)
|
10
|
-
else
|
11
|
-
mod = const_set(SCOPE_MODULE_NAME, Module.new)
|
12
|
-
extend mod
|
13
|
-
end
|
14
|
-
|
9
|
+
extend mod = get_or_set_mod(SCOPE_MODULE_NAME)
|
15
10
|
mod.module_eval do
|
16
11
|
send(:define_method, method_name, &lambda)
|
17
12
|
end
|
@@ -1,30 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module LazyRecord
|
3
4
|
# Validations callbacks. If validations don't pass then initialization
|
4
5
|
# will return false.
|
5
6
|
module Validations
|
6
7
|
VALIDATIONS_MODULE_NAME = :ModelValidations
|
7
8
|
|
8
|
-
def
|
9
|
-
|
9
|
+
def define_validation
|
10
|
+
define_method(:validation) do |*params|
|
11
|
+
params.each do |param|
|
12
|
+
if send(param.to_sym).nil?
|
13
|
+
puts "#{param} must be given", inspect
|
14
|
+
return false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
self
|
18
|
+
end
|
19
|
+
end
|
10
20
|
|
21
|
+
def lr_validates(*args)
|
22
|
+
include mod = get_or_set_mod(VALIDATIONS_MODULE_NAME)
|
23
|
+
mod.extend(Validations)
|
11
24
|
opts = args.extract_options!
|
12
25
|
@validations = args
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
define_method(:validation) do |*params|
|
17
|
-
params.each do |param|
|
18
|
-
begin
|
19
|
-
raise ArgumentError if send(param.to_sym).nil?
|
20
|
-
rescue => e
|
21
|
-
puts e, "#{param} must be given", inspect
|
22
|
-
return false
|
23
|
-
end
|
24
|
-
end
|
25
|
-
self
|
26
|
-
end
|
27
|
-
end
|
26
|
+
return unless opts[:presence] == true
|
27
|
+
mod.module_eval do
|
28
|
+
define_validation
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
data/lib/lazy_record/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lazy_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- M. Simon Borg
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -112,6 +112,7 @@ files:
|
|
112
112
|
- lib/lazy_record/associations.rb
|
113
113
|
- lib/lazy_record/attributes.rb
|
114
114
|
- lib/lazy_record/base.rb
|
115
|
+
- lib/lazy_record/base_module.rb
|
115
116
|
- lib/lazy_record/callbacks.rb
|
116
117
|
- lib/lazy_record/dynamic_modules.rb
|
117
118
|
- lib/lazy_record/methods.rb
|
@@ -1466,7 +1467,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1466
1467
|
version: '0'
|
1467
1468
|
requirements: []
|
1468
1469
|
rubyforge_project:
|
1469
|
-
rubygems_version: 2.6.
|
1470
|
+
rubygems_version: 2.6.11
|
1470
1471
|
signing_key:
|
1471
1472
|
specification_version: 4
|
1472
1473
|
summary: Some ActiveRecord magic for your table-less POROs. WIP.
|