lazy_record 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Code Climate](https://codeclimate.com/github/msimonborg/lazy_record/badges/gpa.svg)](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.
|