airctiverecord 0.2.0 → 0.2.1
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/examples/associations_example.rb +10 -10
- data/examples/basic_usage.rb +8 -8
- data/examples/boolean_fields.rb +3 -3
- data/examples/chainable_queries.rb +4 -4
- data/examples/field_mapping_example.rb +6 -6
- data/examples/readonly_fields.rb +9 -9
- data/examples/scope_isolation.rb +6 -6
- data/lib/airctiverecord/associations.rb +4 -4
- data/lib/airctiverecord/attribute_methods.rb +5 -7
- data/lib/airctiverecord/base.rb +14 -22
- data/lib/airctiverecord/relation.rb +3 -5
- data/lib/airctiverecord/scoping.rb +13 -35
- data/lib/airctiverecord/validations.rb +1 -0
- data/lib/airctiverecord/version.rb +1 -1
- metadata +15 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b646edd0e5f82349a4aeb249a12c8b56ee34b6fb1f090351341c1bb429a9edb
|
|
4
|
+
data.tar.gz: b5a8aaffeb5eb8fcc403f37dccb08f0fcbd4e51bc20c3e5a6ab63c170cf98b50
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 40749055a208071322ceaae739c4b93a2df42d1da1a19711fdc42db4dba1724fcb976b9ee876dcce8c4e2c4a72920187c7319e9c0aa6e04c54651767eef8293c
|
|
7
|
+
data.tar.gz: 41b2f812a0ba8b6a42e1c2b0bca4d8bc889d119668ef094348216e961c9bf67d8830a8bfffb620f69617e1eced2456af517005ea88908a1ad0eae4fe37ea8cf2
|
|
@@ -12,26 +12,26 @@ BASE_KEY = ENV.fetch("AIRTABLE_BASE_KEY")
|
|
|
12
12
|
class Team < AirctiveRecord::Base
|
|
13
13
|
self.base_key = BASE_KEY
|
|
14
14
|
self.table_name = "Teams"
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
attribute :name
|
|
17
17
|
attribute :description
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
has_many :users
|
|
20
20
|
has_one :leader, class_name: "User", foreign_key: "Leader"
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
validates :name, presence: true
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
class User < AirctiveRecord::Base
|
|
26
26
|
self.base_key = BASE_KEY
|
|
27
27
|
self.table_name = "Users"
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
attribute :name
|
|
30
30
|
attribute :email
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
belongs_to :team
|
|
33
33
|
has_many :tasks
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
validates :name, presence: true
|
|
36
36
|
validates :email, presence: true
|
|
37
37
|
end
|
|
@@ -39,17 +39,17 @@ end
|
|
|
39
39
|
class Task < AirctiveRecord::Base
|
|
40
40
|
self.base_key = BASE_KEY
|
|
41
41
|
self.table_name = "Tasks"
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
attribute :title
|
|
44
44
|
attribute :status
|
|
45
45
|
attribute :description
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
belongs_to :user
|
|
48
48
|
has_one :team, through: :user
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
validates :title, presence: true
|
|
51
51
|
validates :status, inclusion: { in: %w[pending in_progress completed] }
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
scope :pending, -> { where("{Status} = 'pending'") }
|
|
54
54
|
scope :completed, -> { where("{Status} = 'completed'") }
|
|
55
55
|
end
|
data/examples/basic_usage.rb
CHANGED
|
@@ -11,33 +11,33 @@ Norairrecord.api_key = ENV.fetch("AIRTABLE_API_KEY")
|
|
|
11
11
|
class User < AirctiveRecord::Base
|
|
12
12
|
self.base_key = ENV.fetch("AIRTABLE_BASE_KEY")
|
|
13
13
|
self.table_name = "Users"
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
# Define attributes
|
|
16
16
|
attribute :name
|
|
17
17
|
attribute :email
|
|
18
18
|
attribute :age
|
|
19
19
|
attribute :role
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
# Validations
|
|
22
22
|
validates :name, presence: true
|
|
23
23
|
validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
|
|
24
24
|
validates :age, numericality: { greater_than: 0, less_than: 150 }, allow_nil: true
|
|
25
25
|
validates :role, inclusion: { in: %w[admin user guest] }, allow_nil: true
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
# Callbacks
|
|
28
28
|
before_save :normalize_email
|
|
29
29
|
after_create :log_creation
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
# Scopes
|
|
32
32
|
scope :admins, -> { where("{Role} = 'admin'") }
|
|
33
33
|
scope :active, -> { where("{Active} = TRUE()") }
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
private
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
def normalize_email
|
|
38
38
|
self.email = email.downcase.strip if email.present?
|
|
39
39
|
end
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
def log_creation
|
|
42
42
|
puts "Created user: #{name} (#{email})"
|
|
43
43
|
end
|
|
@@ -86,6 +86,6 @@ puts "Name is now: #{user.name}"
|
|
|
86
86
|
puts "\nTrying to create invalid user..."
|
|
87
87
|
invalid_user = User.new(email: "not-an-email")
|
|
88
88
|
puts "Valid? #{invalid_user.valid?}"
|
|
89
|
-
puts "Errors: #{invalid_user.errors.full_messages.join(
|
|
89
|
+
puts "Errors: #{invalid_user.errors.full_messages.join(", ")}"
|
|
90
90
|
|
|
91
91
|
puts "\nDone!"
|
data/examples/boolean_fields.rb
CHANGED
|
@@ -7,17 +7,17 @@ require "airctiverecord"
|
|
|
7
7
|
class User < AirctiveRecord::Base
|
|
8
8
|
self.base_key = "appTest123"
|
|
9
9
|
self.table_name = "Users"
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
field :name, "Name"
|
|
12
12
|
field :email, "Email"
|
|
13
13
|
field :active, "Active", type: :boolean
|
|
14
14
|
field :verified, "Verified", type: :boolean
|
|
15
15
|
field :admin, "Admin", type: :boolean
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
scope :active, -> { where(active: true) }
|
|
18
18
|
scope :verified, -> { where(verified: true) }
|
|
19
19
|
scope :admins, -> { where(admin: true) }
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
def self.records(**params)
|
|
22
22
|
puts "records(#{params.inspect})"
|
|
23
23
|
[]
|
|
@@ -7,18 +7,18 @@ require "airctiverecord"
|
|
|
7
7
|
class User < AirctiveRecord::Base
|
|
8
8
|
self.base_key = "appTest123"
|
|
9
9
|
self.table_name = "Users"
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
field :first_name, "First Name"
|
|
12
12
|
field :email, "Email Address"
|
|
13
13
|
field :role, "Role"
|
|
14
14
|
field :active, "Active"
|
|
15
15
|
field :age, "Age"
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
scope :active, -> { where(active: true) }
|
|
18
18
|
scope :admins, -> { where(role: "admin") }
|
|
19
19
|
scope :adults, -> { where("AND({Age} >= 18, {Age} < 65)") }
|
|
20
20
|
scope :recent, -> { order(created_at: :desc).limit(10) }
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
def self.records(**params)
|
|
23
23
|
puts "Would call Airtable API with:"
|
|
24
24
|
puts params.inspect
|
|
@@ -44,7 +44,7 @@ User.where(age: 18..65).to_a
|
|
|
44
44
|
puts
|
|
45
45
|
|
|
46
46
|
puts "=== IN queries ==="
|
|
47
|
-
User.where(role: [
|
|
47
|
+
User.where(role: %w[admin moderator guest]).to_a
|
|
48
48
|
puts
|
|
49
49
|
|
|
50
50
|
puts "=== raw formulas still work ==="
|
|
@@ -11,7 +11,7 @@ Norairrecord.api_key = ENV.fetch("AIRTABLE_API_KEY", "test_key")
|
|
|
11
11
|
class Contact < AirctiveRecord::Base
|
|
12
12
|
self.base_key = ENV.fetch("AIRTABLE_BASE_KEY", "appTest123")
|
|
13
13
|
self.table_name = "Contacts"
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
# Map Ruby attribute names to Airtable field names with spaces
|
|
16
16
|
field :first_name, "First Name"
|
|
17
17
|
field :last_name, "Last Name"
|
|
@@ -22,21 +22,21 @@ class Contact < AirctiveRecord::Base
|
|
|
22
22
|
field :linkedin_url, "LinkedIn URL"
|
|
23
23
|
field :date_added, "Date Added"
|
|
24
24
|
field :is_vip, "VIP?"
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
# Validations using Ruby attribute names
|
|
27
27
|
validates :first_name, :last_name, presence: true
|
|
28
28
|
validates :email_address, format: { with: URI::MailTo::EMAIL_REGEXP }, allow_blank: true
|
|
29
29
|
validates :phone_number, length: { minimum: 10 }, allow_blank: true
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
# Callbacks
|
|
32
32
|
before_save :normalize_email
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
# Scopes
|
|
35
35
|
scope :vip, -> { where("{VIP?} = TRUE()") }
|
|
36
36
|
scope :with_email, -> { where("{Email Address} != ''") }
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
private
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
def normalize_email
|
|
41
41
|
self.email_address = email_address&.downcase&.strip
|
|
42
42
|
end
|
data/examples/readonly_fields.rb
CHANGED
|
@@ -10,15 +10,15 @@ end
|
|
|
10
10
|
|
|
11
11
|
class Contact < AirpplicationRecord
|
|
12
12
|
self.table_name = "Contacts"
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
field :name, "Name"
|
|
15
15
|
field :email, "Email"
|
|
16
16
|
field :company, "Company"
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
# lookup fields (pulled from linked Company record)
|
|
19
19
|
field :company_name, "Company Name (from Company)", readonly: true
|
|
20
20
|
field :company_address, "Company Address (from Company)", readonly: true
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
# formula fields (computed by airtable)
|
|
23
23
|
field :full_name, "Full Name (formula)", readonly: true
|
|
24
24
|
end
|
|
@@ -26,16 +26,16 @@ end
|
|
|
26
26
|
contact = Contact.new(
|
|
27
27
|
name: "Alice",
|
|
28
28
|
email: "alice@example.com",
|
|
29
|
-
company_name: "Acme Corp"
|
|
29
|
+
company_name: "Acme Corp" # readonly field - silently ignored
|
|
30
30
|
)
|
|
31
31
|
|
|
32
32
|
puts "=== readonly fields are readable ==="
|
|
33
33
|
contact.instance_variable_set(:@fields, {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
})
|
|
34
|
+
"Name" => "Alice",
|
|
35
|
+
"Email" => "alice@example.com",
|
|
36
|
+
"Company Name (from Company)" => "Acme Corp",
|
|
37
|
+
"Full Name (formula)" => "Alice Smith"
|
|
38
|
+
})
|
|
39
39
|
|
|
40
40
|
puts "company_name: #{contact.company_name}"
|
|
41
41
|
puts "full_name: #{contact.full_name}"
|
data/examples/scope_isolation.rb
CHANGED
|
@@ -7,13 +7,13 @@ require "airctiverecord"
|
|
|
7
7
|
class User < AirctiveRecord::Base
|
|
8
8
|
self.base_key = "appTest123"
|
|
9
9
|
self.table_name = "Users"
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
field :role, "Role"
|
|
12
12
|
field :active, "Active"
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
scope :active, -> { where(active: true) }
|
|
15
15
|
scope :admins, -> { where(role: "admin") }
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
def self.records(**params)
|
|
18
18
|
puts "User.records called with: #{params.inspect}"
|
|
19
19
|
[]
|
|
@@ -23,13 +23,13 @@ end
|
|
|
23
23
|
class Post < AirctiveRecord::Base
|
|
24
24
|
self.base_key = "appTest123"
|
|
25
25
|
self.table_name = "Posts"
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
field :status, "Status"
|
|
28
28
|
field :featured, "Featured"
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
scope :published, -> { where(status: "published") }
|
|
31
31
|
scope :featured, -> { where(featured: true) }
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
def self.records(**params)
|
|
34
34
|
puts "Post.records called with: #{params.inspect}"
|
|
35
35
|
[]
|
|
@@ -8,13 +8,13 @@ module AirctiveRecord
|
|
|
8
8
|
# just add activerecord-style defaults, norairrecord does the heavy lifting
|
|
9
9
|
def has_many(name, options_arg = nil, **options_kwargs)
|
|
10
10
|
options = options_arg || options_kwargs
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
if options[:through]
|
|
13
13
|
define_has_many_through(name, options)
|
|
14
14
|
else
|
|
15
15
|
column = options[:column] || options[:foreign_key] || "#{name.to_s.singularize}_ids"
|
|
16
16
|
klass = options[:class_name] || name.to_s.classify
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
super(name, { column: column, class: klass }.merge(options))
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -22,14 +22,14 @@ module AirctiveRecord
|
|
|
22
22
|
def belongs_to(name, **options)
|
|
23
23
|
column = options[:column] || options[:foreign_key] || "#{name}_id"
|
|
24
24
|
klass = options[:class_name] || name.to_s.classify
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
super(name, { column: column, class: klass }.merge(options))
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def has_one(name, **options)
|
|
30
30
|
column = options[:column] || options[:foreign_key] || "#{name}_id"
|
|
31
31
|
klass = options[:class_name] || name.to_s.classify
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
super(name, { column: column, class: klass }.merge(options))
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -22,10 +22,10 @@ module AirctiveRecord
|
|
|
22
22
|
airtable_field_name ||= attr_name
|
|
23
23
|
readonly = options[:readonly] || options[:read_only]
|
|
24
24
|
field_type = options[:type]
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
field_mappings[attr_name] = airtable_field_name
|
|
27
27
|
readonly_fields << airtable_field_name if readonly
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
define_attribute_methods attr_name
|
|
30
30
|
|
|
31
31
|
define_method(attr_name) do
|
|
@@ -35,14 +35,14 @@ module AirctiveRecord
|
|
|
35
35
|
|
|
36
36
|
if readonly
|
|
37
37
|
# readonly fields silently ignore sets (airtable rejects them anyway)
|
|
38
|
-
define_method("#{attr_name}=") do |
|
|
38
|
+
define_method("#{attr_name}=") do |_value|
|
|
39
39
|
nil
|
|
40
40
|
end
|
|
41
41
|
else
|
|
42
42
|
define_method("#{attr_name}=") do |value|
|
|
43
43
|
field_name = self.class.field_mappings[attr_name]
|
|
44
44
|
return if self[field_name] == value
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
send("#{attr_name}_will_change!") unless self[field_name] == value
|
|
47
47
|
self[field_name] = value
|
|
48
48
|
end
|
|
@@ -66,9 +66,7 @@ module AirctiveRecord
|
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
def attributes
|
|
70
|
-
fields
|
|
71
|
-
end
|
|
69
|
+
def attributes = fields
|
|
72
70
|
|
|
73
71
|
def attributes=(attrs)
|
|
74
72
|
attrs.each do |key, value|
|
data/lib/airctiverecord/base.rb
CHANGED
|
@@ -27,19 +27,17 @@ module AirctiveRecord
|
|
|
27
27
|
@relation_class ||= Class.new(AirctiveRecord::Relation)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
def relation_class_name
|
|
31
|
-
"#{name}::Relation"
|
|
32
|
-
end
|
|
30
|
+
def relation_class_name = "#{name}::Relation"
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
def initialize(attributes = {}, **kwargs)
|
|
36
34
|
# Extract id and created_at if present
|
|
37
35
|
id = kwargs.delete(:id)
|
|
38
36
|
created_at = kwargs.delete(:created_at)
|
|
39
|
-
|
|
37
|
+
|
|
40
38
|
# Merge positional hash and kwargs to handle both styles
|
|
41
39
|
all_attrs = attributes.is_a?(Hash) ? attributes.merge(kwargs) : kwargs
|
|
42
|
-
|
|
40
|
+
|
|
43
41
|
# Norairrecord::Table expects field names as STRING keys
|
|
44
42
|
# We need to convert Ruby attribute names to Airtable field names
|
|
45
43
|
mapped_attrs = {}
|
|
@@ -47,7 +45,7 @@ module AirctiveRecord
|
|
|
47
45
|
field_name = self.class.field_mappings[key.to_s] || key.to_s
|
|
48
46
|
mapped_attrs[field_name.to_s] = value # Ensure string keys
|
|
49
47
|
end
|
|
50
|
-
|
|
48
|
+
|
|
51
49
|
# Call norairrecord's initialize properly
|
|
52
50
|
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0.0")
|
|
53
51
|
if mapped_attrs.empty?
|
|
@@ -58,7 +56,7 @@ module AirctiveRecord
|
|
|
58
56
|
else
|
|
59
57
|
super(mapped_attrs, id: id, created_at: created_at)
|
|
60
58
|
end
|
|
61
|
-
|
|
59
|
+
|
|
62
60
|
clear_changes_information
|
|
63
61
|
end
|
|
64
62
|
|
|
@@ -68,12 +66,12 @@ module AirctiveRecord
|
|
|
68
66
|
|
|
69
67
|
def serializable_fields
|
|
70
68
|
# exclude readonly fields from serialization
|
|
71
|
-
fields.reject { |k,
|
|
69
|
+
fields.reject { |k, _v| self.class.readonly_fields.include?(k) }
|
|
72
70
|
end
|
|
73
71
|
|
|
74
72
|
def save(**options)
|
|
75
73
|
return false unless valid?
|
|
76
|
-
|
|
74
|
+
|
|
77
75
|
begin
|
|
78
76
|
run_callbacks :save do
|
|
79
77
|
if new_record?
|
|
@@ -88,13 +86,14 @@ module AirctiveRecord
|
|
|
88
86
|
end
|
|
89
87
|
changes_applied
|
|
90
88
|
true
|
|
91
|
-
rescue
|
|
89
|
+
rescue StandardError
|
|
92
90
|
false
|
|
93
91
|
end
|
|
94
92
|
end
|
|
95
93
|
|
|
96
94
|
def save!(**options)
|
|
97
95
|
raise RecordInvalid, errors.full_messages.join(", ") unless valid?
|
|
96
|
+
|
|
98
97
|
save(**options) || raise(RecordNotSaved, "Failed to save record")
|
|
99
98
|
end
|
|
100
99
|
|
|
@@ -110,6 +109,7 @@ module AirctiveRecord
|
|
|
110
109
|
|
|
111
110
|
def reload
|
|
112
111
|
return self if new_record?
|
|
112
|
+
|
|
113
113
|
reloaded = self.class.find(id)
|
|
114
114
|
@fields = reloaded.fields
|
|
115
115
|
@created_at = reloaded.created_at
|
|
@@ -117,20 +117,12 @@ module AirctiveRecord
|
|
|
117
117
|
self
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
-
def persisted?
|
|
121
|
-
!new_record?
|
|
122
|
-
end
|
|
120
|
+
def persisted? = !new_record?
|
|
123
121
|
|
|
124
|
-
def to_param
|
|
125
|
-
id
|
|
126
|
-
end
|
|
122
|
+
def to_param = id
|
|
127
123
|
|
|
128
|
-
def to_key
|
|
129
|
-
persisted? ? [id] : nil
|
|
130
|
-
end
|
|
124
|
+
def to_key = persisted? ? [id] : nil
|
|
131
125
|
|
|
132
|
-
def to_model
|
|
133
|
-
self
|
|
134
|
-
end
|
|
126
|
+
def to_model = self
|
|
135
127
|
end
|
|
136
128
|
end
|
|
@@ -18,11 +18,9 @@ module AirctiveRecord
|
|
|
18
18
|
# override to use field mappings when building airtable params
|
|
19
19
|
def to_airtable_params
|
|
20
20
|
params = {}
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
# filter
|
|
23
|
-
if @where_clause.any?
|
|
24
|
-
params[:filter] = @where_clause.to_airtable_formula
|
|
25
|
-
end
|
|
23
|
+
params[:filter] = @where_clause.to_airtable_formula if @where_clause.any?
|
|
26
24
|
|
|
27
25
|
# sort - use field mappings
|
|
28
26
|
if @order_values.any?
|
|
@@ -34,7 +32,7 @@ module AirctiveRecord
|
|
|
34
32
|
|
|
35
33
|
# limit
|
|
36
34
|
params[:max_records] = @limit_value if @limit_value
|
|
37
|
-
|
|
35
|
+
|
|
38
36
|
# offset
|
|
39
37
|
params[:offset] = @offset_value if @offset_value
|
|
40
38
|
|
|
@@ -5,22 +5,18 @@ module AirctiveRecord
|
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
6
|
|
|
7
7
|
class_methods do
|
|
8
|
-
# returns a chainable Relation object
|
|
9
|
-
def all
|
|
10
|
-
relation_class.new(self)
|
|
11
|
-
end
|
|
8
|
+
# returns a chainable Relation object
|
|
9
|
+
def all = relation_class.new(self)
|
|
12
10
|
|
|
13
11
|
# scopes are defined on the model's specific Relation class
|
|
14
12
|
def scope(name, body)
|
|
15
|
-
unless body.respond_to?(:call)
|
|
16
|
-
raise ArgumentError, "The scope body needs to be callable."
|
|
17
|
-
end
|
|
13
|
+
raise ArgumentError, "The scope body needs to be callable." unless body.respond_to?(:call)
|
|
18
14
|
|
|
19
15
|
# define on the class
|
|
20
16
|
singleton_class.send(:define_method, name) do |*args|
|
|
21
17
|
all.public_send(name, *args)
|
|
22
18
|
end
|
|
23
|
-
|
|
19
|
+
|
|
24
20
|
# define on this model's Relation class
|
|
25
21
|
relation_class.send(:define_method, name) do |*args|
|
|
26
22
|
instance_exec(*args, &body)
|
|
@@ -28,41 +24,23 @@ module AirctiveRecord
|
|
|
28
24
|
end
|
|
29
25
|
|
|
30
26
|
# delegate finder methods to all
|
|
31
|
-
def where(conditions)
|
|
32
|
-
all.where(conditions)
|
|
33
|
-
end
|
|
27
|
+
def where(conditions) = all.where(conditions)
|
|
34
28
|
|
|
35
|
-
def order(*args)
|
|
36
|
-
all.order(*args)
|
|
37
|
-
end
|
|
29
|
+
def order(*args) = all.order(*args)
|
|
38
30
|
|
|
39
|
-
def limit(value)
|
|
40
|
-
all.limit(value)
|
|
41
|
-
end
|
|
31
|
+
def limit(value) = all.limit(value)
|
|
42
32
|
|
|
43
|
-
def offset(value)
|
|
44
|
-
all.offset(value)
|
|
45
|
-
end
|
|
33
|
+
def offset(value) = all.offset(value)
|
|
46
34
|
|
|
47
|
-
def find_by(conditions)
|
|
48
|
-
all.find_by(conditions)
|
|
49
|
-
end
|
|
35
|
+
def find_by(conditions) = all.find_by(conditions)
|
|
50
36
|
|
|
51
|
-
def find_by!(conditions)
|
|
52
|
-
all.find_by!(conditions)
|
|
53
|
-
end
|
|
37
|
+
def find_by!(conditions) = all.find_by!(conditions)
|
|
54
38
|
|
|
55
|
-
def first(limit = nil)
|
|
56
|
-
all.first(limit)
|
|
57
|
-
end
|
|
39
|
+
def first(limit = nil) = all.first(limit)
|
|
58
40
|
|
|
59
|
-
def last(limit = nil)
|
|
60
|
-
all.last(limit)
|
|
61
|
-
end
|
|
41
|
+
def last(limit = nil) = all.last(limit)
|
|
62
42
|
|
|
63
|
-
def count
|
|
64
|
-
all.count
|
|
65
|
-
end
|
|
43
|
+
def count = all.count
|
|
66
44
|
end
|
|
67
45
|
end
|
|
68
46
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: airctiverecord
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- 24c02
|
|
@@ -9,20 +9,6 @@ bindir: exe
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
-
- !ruby/object:Gem::Dependency
|
|
13
|
-
name: norairrecord
|
|
14
|
-
requirement: !ruby/object:Gem::Requirement
|
|
15
|
-
requirements:
|
|
16
|
-
- - "~>"
|
|
17
|
-
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0.5'
|
|
19
|
-
type: :runtime
|
|
20
|
-
prerelease: false
|
|
21
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
-
requirements:
|
|
23
|
-
- - "~>"
|
|
24
|
-
- !ruby/object:Gem::Version
|
|
25
|
-
version: '0.5'
|
|
26
12
|
- !ruby/object:Gem::Dependency
|
|
27
13
|
name: activemodel
|
|
28
14
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -65,6 +51,20 @@ dependencies:
|
|
|
65
51
|
- - ">="
|
|
66
52
|
- !ruby/object:Gem::Version
|
|
67
53
|
version: 0.2.0
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: norairrecord
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.5'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.5'
|
|
68
68
|
description: Provides a familiar ActiveRecord-like interface for Airtable, built on
|
|
69
69
|
top of norairrecord with validations, callbacks, and associations.
|
|
70
70
|
email:
|