filemaker 0.0.8 → 0.0.9
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/.rubocop.yml +8 -1
- data/lib/filemaker/elasticsearch/filemaker_adapter.rb +28 -0
- data/lib/filemaker/errors.rb +1 -1
- data/lib/filemaker/metadata/field.rb +1 -1
- data/lib/filemaker/model/builder.rb +2 -1
- data/lib/filemaker/model/components.rb +1 -0
- data/lib/filemaker/model/field.rb +8 -1
- data/lib/filemaker/model/fields.rb +34 -6
- data/lib/filemaker/model/persistable.rb +16 -3
- data/lib/filemaker/model.rb +8 -0
- data/lib/filemaker/railtie.rb +1 -1
- data/lib/filemaker/version.rb +1 -1
- data/lib/filemaker.rb +12 -0
- data/lib/generators/filemaker/model/model_generator.rb +39 -0
- data/lib/generators/filemaker/model/templates/model.rb +12 -0
- data/spec/filemaker/layout_spec.rb +1 -1
- data/spec/filemaker/model/relations_spec.rb +1 -1
- data/spec/filemaker/model_spec.rb +15 -2
- data/spec/filemaker/server_spec.rb +10 -10
- data/spec/filemaker/store/database_store_spec.rb +1 -1
- data/spec/filemaker/store/layout_store_spec.rb +1 -1
- data/spec/filemaker/store/script_store_spec.rb +1 -1
- data/spec/support/models.rb +1 -1
- 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: 87dee5e465c260a70cc59492b12fb5a8a9f74dce
|
4
|
+
data.tar.gz: dec6305d44d0eac91f95ba7f5def8ddb8a179292
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 182382127660a2e3d081d4b12e80defbeca9db11042a29d4cb626f99ce8bebf016d3b89d16ec1392d4375035d77b5a2ca5450d2c623e6fb7bf3ab4f8b06a5cef
|
7
|
+
data.tar.gz: 3fbc5b636c7fda5f4d8f72b29305844d7777969adeea0b446cd72c6cbfcad98fb404b70e4029ebeb74a1fcd22f2bd1ae4be1a5cde69be9593f82b9a76bd3113e
|
data/.rubocop.yml
CHANGED
@@ -3,6 +3,7 @@ AllCops:
|
|
3
3
|
- .bundle/**
|
4
4
|
- filemaker.gemspec
|
5
5
|
- lib/filemaker/errors.rb
|
6
|
+
- lib/generators/filemaker/model/templates/model.rb
|
6
7
|
|
7
8
|
Documentation:
|
8
9
|
Enabled: false
|
@@ -14,4 +15,10 @@ MethodLength:
|
|
14
15
|
Enabled: false
|
15
16
|
|
16
17
|
LineLength:
|
17
|
-
Max: 80
|
18
|
+
Max: 80
|
19
|
+
|
20
|
+
SpecialGlobalVars:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
PredicateName:
|
24
|
+
Enabled: false
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Filemaker
|
2
|
+
module Elasticsearch
|
3
|
+
module FilemakerAdapter
|
4
|
+
module Records
|
5
|
+
def records
|
6
|
+
criteria = klass.in(klass.identity.name => ids)
|
7
|
+
|
8
|
+
criteria.instance_exec(response.response['hits']['hits']) do |hits|
|
9
|
+
define_singleton_method :to_a do
|
10
|
+
self.entries.sort_by do |e|
|
11
|
+
hits.index { |hit| hit['_id'].to_s == e.id.to_s }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
criteria
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Callbacks
|
21
|
+
# noop
|
22
|
+
end
|
23
|
+
|
24
|
+
module Importing
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/filemaker/errors.rb
CHANGED
@@ -49,7 +49,7 @@ module Filemaker
|
|
49
49
|
rescue
|
50
50
|
# We could be getting back these date:
|
51
51
|
# '17.12.95', '19/05/99', '27/11 /1981'
|
52
|
-
# '1959-07-03' will be
|
52
|
+
# '1959-07-03' will be beyond us, so consider returning exact value
|
53
53
|
value = value.gsub(/-|\./, '/')
|
54
54
|
split = value.split('/').map(&:strip)
|
55
55
|
split[2] = "19#{split[2]}" if split[2].size == 2
|
@@ -21,7 +21,8 @@ module Filemaker
|
|
21
21
|
field = klass.find_field_by_name(fm_field_name)
|
22
22
|
next unless field
|
23
23
|
|
24
|
-
|
24
|
+
# Because we are using ActiveModel::Dirty, so we hydrate directly.
|
25
|
+
object.attributes[field.name] = field.coerce(record[fm_field_name])
|
25
26
|
end
|
26
27
|
|
27
28
|
models << object
|
@@ -13,9 +13,13 @@ module Filemaker
|
|
13
13
|
@fm_name = (options.fetch(:fm_name) { name }).to_s.downcase
|
14
14
|
end
|
15
15
|
|
16
|
-
# From FileMaker to Ruby
|
16
|
+
# From FileMaker to Ruby.
|
17
|
+
#
|
18
|
+
# If the value is `==` (match empty) or `=*` (match record), then we will
|
19
|
+
# skip coercion.
|
17
20
|
def coerce(value)
|
18
21
|
return nil if value.nil?
|
22
|
+
return value if value == '==' || value == '=*'
|
19
23
|
|
20
24
|
if @type == String
|
21
25
|
value.to_s
|
@@ -32,6 +36,9 @@ module Filemaker
|
|
32
36
|
else
|
33
37
|
value
|
34
38
|
end
|
39
|
+
rescue
|
40
|
+
warn "Could not coerce #{name}: #{value}"
|
41
|
+
value
|
35
42
|
end
|
36
43
|
end
|
37
44
|
end
|
@@ -2,16 +2,29 @@ require 'filemaker/model/field'
|
|
2
2
|
|
3
3
|
module Filemaker
|
4
4
|
module Model
|
5
|
+
# `Fields` help to give `Model` their perceived schema. To find out your
|
6
|
+
# fields, use `Model.fm_fields` or use Rails generator like:
|
7
|
+
#
|
8
|
+
# rails generate filemaker:model filename database layout
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# class Model
|
12
|
+
# include Filemaker::Model
|
13
|
+
#
|
14
|
+
# string :id, identity: true
|
15
|
+
# string :title, fm_name: 'A_Title', default: 'Untitled'
|
16
|
+
# money :salary
|
17
|
+
# end
|
5
18
|
module Fields
|
6
19
|
extend ActiveSupport::Concern
|
7
20
|
|
8
21
|
TYPE_MAPPINGS = {
|
9
|
-
string:
|
10
|
-
date:
|
22
|
+
string: String,
|
23
|
+
date: Date,
|
11
24
|
datetime: DateTime,
|
12
|
-
money:
|
13
|
-
|
14
|
-
|
25
|
+
money: BigDecimal,
|
26
|
+
number: BigDecimal,
|
27
|
+
integer: Integer
|
15
28
|
}
|
16
29
|
|
17
30
|
included do
|
@@ -19,6 +32,8 @@ module Filemaker
|
|
19
32
|
self.fields = {}
|
20
33
|
end
|
21
34
|
|
35
|
+
# Apply default value when you instantiate a new model.
|
36
|
+
# @See Model.new
|
22
37
|
def apply_defaults
|
23
38
|
attribute_names.each do |name|
|
24
39
|
field = fields[name]
|
@@ -53,15 +68,27 @@ module Filemaker
|
|
53
68
|
end
|
54
69
|
|
55
70
|
def add_field(name, type, options)
|
71
|
+
name = name.to_s
|
56
72
|
fields[name] = Filemaker::Model::Field.new(name, type, options)
|
57
73
|
self.identity = fields[name] if options[:identity]
|
58
74
|
end
|
59
75
|
|
60
76
|
def create_accessors(name)
|
77
|
+
name = name.to_s # Normalize it so ActiveModel::Serialization can work
|
78
|
+
|
79
|
+
define_attribute_methods name
|
80
|
+
|
81
|
+
# Reader
|
61
82
|
define_method(name) { attributes[name] }
|
83
|
+
|
84
|
+
# Writer - We try to map to the correct type, if not we just return
|
85
|
+
# original.
|
62
86
|
define_method("#{name}=") do |value|
|
87
|
+
public_send("#{name}_will_change!") unless value == attributes[name]
|
63
88
|
attributes[name] = fields[name].coerce(value)
|
64
89
|
end
|
90
|
+
|
91
|
+
# Predicate
|
65
92
|
define_method("#{name}?") do
|
66
93
|
attributes[name] == true || attributes[name].present?
|
67
94
|
end
|
@@ -70,8 +97,9 @@ module Filemaker
|
|
70
97
|
# Find FileMaker's real name given either the attribute name or the real
|
71
98
|
# FileMaker name.
|
72
99
|
def find_field_by_name(name)
|
100
|
+
name = name.to_s
|
73
101
|
fields.values.find do |f|
|
74
|
-
f.name == name
|
102
|
+
f.name == name || f.fm_name == name
|
75
103
|
end
|
76
104
|
end
|
77
105
|
end
|
@@ -35,12 +35,14 @@ module Filemaker
|
|
35
35
|
|
36
36
|
def update
|
37
37
|
return false unless valid?
|
38
|
+
return true if dirty_attributes.empty?
|
38
39
|
|
39
40
|
run_callbacks :update do
|
40
41
|
# Will raise `RecordModificationIdMismatchError` if does not match
|
41
42
|
options = { modid: mod_id } # Always pass in?
|
42
43
|
yield options if block_given?
|
43
|
-
resultset = api.edit(record_id,
|
44
|
+
resultset = api.edit(record_id, dirty_attributes, options)
|
45
|
+
changes_applied
|
44
46
|
replace_new_data(resultset)
|
45
47
|
end
|
46
48
|
self
|
@@ -70,11 +72,21 @@ module Filemaker
|
|
70
72
|
# `fm_attributes`
|
71
73
|
def assign_attributes(new_attributes)
|
72
74
|
return if new_attributes.blank?
|
75
|
+
|
73
76
|
new_attributes.each_pair do |key, value|
|
74
|
-
|
77
|
+
next unless respond_to?("#{key}=")
|
78
|
+
|
79
|
+
public_send("#{key}=", (value || ''))
|
75
80
|
end
|
76
81
|
end
|
77
82
|
|
83
|
+
def reload!
|
84
|
+
reset_changes
|
85
|
+
resultset = api.find(record_id)
|
86
|
+
replace_new_data(resultset)
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
78
90
|
private
|
79
91
|
|
80
92
|
# If you have calculated field from FileMaker, it will be replaced.
|
@@ -90,7 +102,8 @@ module Filemaker
|
|
90
102
|
field = self.class.find_field_by_name(fm_field_name)
|
91
103
|
next unless field
|
92
104
|
|
93
|
-
|
105
|
+
# Because we are using ActiveModel::Dirty, so we hydrate directly.
|
106
|
+
attributes[field.name] = field.coerce(record[fm_field_name])
|
94
107
|
end
|
95
108
|
end
|
96
109
|
end
|
data/lib/filemaker/model.rb
CHANGED
@@ -49,6 +49,14 @@ module Filemaker
|
|
49
49
|
self.class.with_model_fields(attributes)
|
50
50
|
end
|
51
51
|
|
52
|
+
def dirty_attributes
|
53
|
+
dirty = {}
|
54
|
+
changed.each do |attr_name|
|
55
|
+
dirty[attr_name] = attributes[attr_name]
|
56
|
+
end
|
57
|
+
self.class.with_model_fields(dirty)
|
58
|
+
end
|
59
|
+
|
52
60
|
private
|
53
61
|
|
54
62
|
def process_attributes(attrs)
|
data/lib/filemaker/railtie.rb
CHANGED
data/lib/filemaker/version.rb
CHANGED
data/lib/filemaker.rb
CHANGED
@@ -58,3 +58,15 @@ module Filemaker
|
|
58
58
|
end
|
59
59
|
|
60
60
|
require 'filemaker/railtie' if defined?(Rails)
|
61
|
+
|
62
|
+
if defined?(Elasticsearch::Model)
|
63
|
+
require 'filemaker/elasticsearch/filemaker_adapter'
|
64
|
+
|
65
|
+
Elasticsearch::Model::Adapter.register(
|
66
|
+
::Filemaker::Elasticsearch::FilemakerAdapter,
|
67
|
+
lambda do |klass|
|
68
|
+
!!defined?(::Filemaker::Model) && \
|
69
|
+
klass.ancestors.include?(::Filemaker::Model)
|
70
|
+
end
|
71
|
+
)
|
72
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module Filemaker
|
4
|
+
module Generators
|
5
|
+
class ModelGenerator < ::Rails::Generators::NamedBase
|
6
|
+
desc 'Create FileMaker model.'
|
7
|
+
argument :db, type: :string, required: true
|
8
|
+
argument :lay, type: :string, required: true
|
9
|
+
argument :registry, type: :string, required: false
|
10
|
+
|
11
|
+
def self.source_root
|
12
|
+
@source_root ||= File.expand_path(
|
13
|
+
File.join(File.dirname(__FILE__), 'templates')
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_model_file
|
18
|
+
server = Filemaker.registry[registry || 'default']
|
19
|
+
api = server.db[db][lay]
|
20
|
+
@fields = api.view.fields.values.map do |field|
|
21
|
+
[field.name, field.data_type]
|
22
|
+
end
|
23
|
+
|
24
|
+
@type_mappings = {
|
25
|
+
'text' => 'string',
|
26
|
+
'number' => 'number',
|
27
|
+
'date' => 'date',
|
28
|
+
'time' => 'datetime',
|
29
|
+
'timestamp' => 'datetime'
|
30
|
+
}
|
31
|
+
|
32
|
+
template(
|
33
|
+
'model.rb',
|
34
|
+
File.join('app/models', class_path, "#{file_name}.rb")
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% module_namespacing do -%>
|
2
|
+
class <%= class_name %>
|
3
|
+
include Filemaker::Model
|
4
|
+
|
5
|
+
database '<%= db %>'
|
6
|
+
layout '<%= lay %>'
|
7
|
+
|
8
|
+
<% @fields.map do |name, type| -%>
|
9
|
+
<%= @type_mappings[type] %> :<%= name.parameterize.underscore %>, fm_name: '<%= name %>'
|
10
|
+
<% end -%>
|
11
|
+
end
|
12
|
+
<% end %>
|
@@ -53,7 +53,7 @@ describe Filemaker::Model::Relations do
|
|
53
53
|
|
54
54
|
context 'when using default reference_key' do
|
55
55
|
it 'will use owner identity name' do
|
56
|
-
expect(@model.posts.reference_key).to eq
|
56
|
+
expect(@model.posts.reference_key).to eq 'candidate_id'
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'target class should be Post' do
|
@@ -12,10 +12,10 @@ describe Filemaker::Model do
|
|
12
12
|
it 'sets up server and api' do
|
13
13
|
expect(MyModel.api.default_params).to eq \
|
14
14
|
({ '-db' => :candidates, '-lay' => :profile })
|
15
|
-
expect(MyModel.server.host).to eq '
|
15
|
+
expect(MyModel.server.host).to eq 'example'
|
16
16
|
expect(model.api.default_params).to eq \
|
17
17
|
({ '-db' => :candidates, '-lay' => :profile })
|
18
|
-
expect(model.server.host).to eq '
|
18
|
+
expect(model.server.host).to eq 'example'
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'is a new record' do
|
@@ -78,4 +78,17 @@ describe Filemaker::Model do
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
+
context 'dirty attributes' do
|
82
|
+
it 'does not track changes for new model' do
|
83
|
+
expect(model.changed?).to be false
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'tracks changes' do
|
87
|
+
model.name = 'Bob'
|
88
|
+
expect(model.changed?).to be true
|
89
|
+
expect(model.changed).to eq ['name']
|
90
|
+
expect(model.dirty_attributes).to eq({'name' => 'Bob'})
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
81
94
|
end
|
@@ -3,13 +3,13 @@ describe Filemaker::Server do
|
|
3
3
|
context 'initializing a server' do
|
4
4
|
it 'provides a host, account_name, and password' do
|
5
5
|
server = Filemaker::Server.new do |config|
|
6
|
-
config.host = '
|
6
|
+
config.host = 'example'
|
7
7
|
config.account_name = 'account_name'
|
8
8
|
config.password = 'password'
|
9
9
|
end
|
10
10
|
|
11
|
-
expect(server.host).to eq '
|
12
|
-
expect(server.url).to eq 'http://
|
11
|
+
expect(server.host).to eq 'example'
|
12
|
+
expect(server.url).to eq 'http://example'
|
13
13
|
expect(server.account_name).to eq 'account_name'
|
14
14
|
expect(server.password).to eq 'password'
|
15
15
|
expect(server.connection).to be_a Faraday::Connection
|
@@ -21,13 +21,13 @@ describe Filemaker::Server do
|
|
21
21
|
|
22
22
|
it 'specifically ask for no SSL' do
|
23
23
|
server = Filemaker::Server.new do |config|
|
24
|
-
config.host = '
|
24
|
+
config.host = 'example'
|
25
25
|
config.account_name = 'account_name'
|
26
26
|
config.password = 'password'
|
27
27
|
config.ssl = false
|
28
28
|
end
|
29
29
|
|
30
|
-
expect(server.url).to eq 'http://
|
30
|
+
expect(server.url).to eq 'http://example'
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'did not provide host, account_name, and password' do
|
@@ -36,7 +36,7 @@ describe Filemaker::Server do
|
|
36
36
|
end.to raise_error ArgumentError
|
37
37
|
|
38
38
|
expect do
|
39
|
-
Filemaker::Server.new { |config| config.host = '
|
39
|
+
Filemaker::Server.new { |config| config.host = 'example' }
|
40
40
|
end.to raise_error ArgumentError
|
41
41
|
end
|
42
42
|
end
|
@@ -44,13 +44,13 @@ describe Filemaker::Server do
|
|
44
44
|
context 'initializing a server with SSL' do
|
45
45
|
it 'indicates secured connection' do
|
46
46
|
server = Filemaker::Server.new do |config|
|
47
|
-
config.host = '
|
47
|
+
config.host = 'example'
|
48
48
|
config.account_name = 'account_name'
|
49
49
|
config.password = 'password'
|
50
50
|
config.ssl = { verify: false }
|
51
51
|
end
|
52
52
|
|
53
|
-
expect(server.url).to eq 'https://
|
53
|
+
expect(server.url).to eq 'https://example'
|
54
54
|
expect(server.connection.ssl[:verify]).to be false
|
55
55
|
end
|
56
56
|
end
|
@@ -58,7 +58,7 @@ describe Filemaker::Server do
|
|
58
58
|
describe 'databases is a store to track encountered -db' do
|
59
59
|
it 'stores database object and can be accessed with db and database' do
|
60
60
|
server = Filemaker::Server.new do |config|
|
61
|
-
config.host = '
|
61
|
+
config.host = 'example'
|
62
62
|
config.account_name = 'account_name'
|
63
63
|
config.password = 'password'
|
64
64
|
end
|
@@ -72,7 +72,7 @@ describe Filemaker::Server do
|
|
72
72
|
context 'HTTP errors' do
|
73
73
|
before do
|
74
74
|
@server = Filemaker::Server.new do |config|
|
75
|
-
config.host = '
|
75
|
+
config.host = 'example'
|
76
76
|
config.account_name = 'account_name'
|
77
77
|
config.password = 'password'
|
78
78
|
end
|
@@ -16,7 +16,7 @@ describe Filemaker::Store::DatabaseStore do
|
|
16
16
|
describe 'all' do
|
17
17
|
it 'returns all databases' do
|
18
18
|
server = Filemaker::Server.new do |config|
|
19
|
-
config.host = '
|
19
|
+
config.host = 'example'
|
20
20
|
config.account_name = 'account_name'
|
21
21
|
config.password = 'password'
|
22
22
|
end
|
@@ -16,7 +16,7 @@ describe Filemaker::Store::LayoutStore do
|
|
16
16
|
describe 'all' do
|
17
17
|
it 'returns all layouts for a database' do
|
18
18
|
server = Filemaker::Server.new do |config|
|
19
|
-
config.host = '
|
19
|
+
config.host = 'example'
|
20
20
|
config.account_name = 'account_name'
|
21
21
|
config.password = 'password'
|
22
22
|
end
|
@@ -16,7 +16,7 @@ describe Filemaker::Store::ScriptStore do
|
|
16
16
|
describe 'all' do
|
17
17
|
it 'returns all scripts for a database' do
|
18
18
|
server = Filemaker::Server.new do |config|
|
19
|
-
config.host = '
|
19
|
+
config.host = 'example'
|
20
20
|
config.account_name = 'account_name'
|
21
21
|
config.password = 'password'
|
22
22
|
end
|
data/spec/support/models.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: filemaker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mech
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -167,6 +167,7 @@ files:
|
|
167
167
|
- lib/filemaker/configuration.rb
|
168
168
|
- lib/filemaker/core_ext/hash.rb
|
169
169
|
- lib/filemaker/database.rb
|
170
|
+
- lib/filemaker/elasticsearch/filemaker_adapter.rb
|
170
171
|
- lib/filemaker/errors.rb
|
171
172
|
- lib/filemaker/layout.rb
|
172
173
|
- lib/filemaker/metadata/field.rb
|
@@ -195,6 +196,8 @@ files:
|
|
195
196
|
- lib/filemaker/store/layout_store.rb
|
196
197
|
- lib/filemaker/store/script_store.rb
|
197
198
|
- lib/filemaker/version.rb
|
199
|
+
- lib/generators/filemaker/model/model_generator.rb
|
200
|
+
- lib/generators/filemaker/model/templates/model.rb
|
198
201
|
- spec/filemaker/api/query_commands/compound_find_spec.rb
|
199
202
|
- spec/filemaker/configuration_spec.rb
|
200
203
|
- spec/filemaker/error_spec.rb
|