rails_view_adapters 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +181 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.md +27 -0
- data/README.md +88 -0
- data/Rakefile +6 -0
- data/lib/rails_view_adapters/adapter.rb +34 -0
- data/lib/rails_view_adapters/adapter_base.rb +101 -0
- data/lib/rails_view_adapters/definition_proxy.rb +155 -0
- data/lib/rails_view_adapters/map.rb +46 -0
- data/lib/rails_view_adapters/version.rb +4 -0
- data/lib/rails_view_adapters.rb +13 -0
- data/rails_view_adapters.gemspec +35 -0
- data/spec/active_record_helper.rb +16 -0
- data/spec/active_record_support/db/migrate/20161031222934_create_users.rb +14 -0
- data/spec/active_record_support/db/migrate/20161031223219_create_posts.rb +11 -0
- data/spec/active_record_support/db/migrate/20161031223253_create_teams.rb +10 -0
- data/spec/active_record_support/fabricators/post_fabricator.rb +7 -0
- data/spec/active_record_support/fabricators/team_fabricator.rb +6 -0
- data/spec/active_record_support/fabricators/user_fabricator.rb +10 -0
- data/spec/active_record_support/models/post.rb +4 -0
- data/spec/active_record_support/models/team.rb +4 -0
- data/spec/active_record_support/models/user.rb +5 -0
- data/spec/integration/an_adapter_spec.rb +58 -0
- data/spec/lib/adapter_base_spec.rb +133 -0
- data/spec/lib/adapter_spec.rb +45 -0
- data/spec/lib/definition_proxy_spec.rb +242 -0
- data/spec/lib/map_spec.rb +99 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/support/an_adapter.rb +72 -0
- data/spec/support/fuzzy_nested_match.rb +96 -0
- metadata +206 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "active_support/core_ext/time"
|
3
|
+
Time.zone = "UTC"
|
4
|
+
|
5
|
+
require "rails_view_adapters/version"
|
6
|
+
require "rails_view_adapters/adapter_base"
|
7
|
+
require "rails_view_adapters/map"
|
8
|
+
require "rails_view_adapters/definition_proxy"
|
9
|
+
require "rails_view_adapters/adapter"
|
10
|
+
|
11
|
+
# Namespace for rails_view_adapters
|
12
|
+
module RailsViewAdapters
|
13
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rails_view_adapters/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rails_view_adapters"
|
8
|
+
spec.version = RailsViewAdapters::VERSION
|
9
|
+
spec.authors = ["Bryan Hockey"]
|
10
|
+
spec.email = ["bhock@umich.edu"]
|
11
|
+
|
12
|
+
spec.summary = "Bidirectional mappings between models and external views for Rails."
|
13
|
+
spec.description = spec.summary
|
14
|
+
spec.homepage = "https://github.com/mlibrary/rails_view_adapters"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
spec.test_files = Dir["spec/**/*"]
|
23
|
+
|
24
|
+
spec.required_ruby_version = ">= 2.2.2"
|
25
|
+
|
26
|
+
spec.add_dependency "activerecord", "~>4.2.7.1"
|
27
|
+
spec.add_dependency "activesupport", "~>4.2.7.1"
|
28
|
+
|
29
|
+
spec.add_development_dependency "sqlite3"
|
30
|
+
spec.add_development_dependency "rspec-rails"
|
31
|
+
spec.add_development_dependency "faker"
|
32
|
+
spec.add_development_dependency "fabrication"
|
33
|
+
spec.add_development_dependency "pry"
|
34
|
+
spec.add_development_dependency "rubocop"
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "active_record"
|
3
|
+
require "fabrication"
|
4
|
+
|
5
|
+
require "active_record_support/models/user"
|
6
|
+
require "active_record_support/models/post"
|
7
|
+
require "active_record_support/models/team"
|
8
|
+
|
9
|
+
require "active_record_support/fabricators/user_fabricator"
|
10
|
+
require "active_record_support/fabricators/post_fabricator"
|
11
|
+
require "active_record_support/fabricators/team_fabricator"
|
12
|
+
|
13
|
+
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
14
|
+
ActiveSupport::Deprecation.silenced = true
|
15
|
+
ActiveRecord::Migration.verbose = false
|
16
|
+
ActiveRecord::Migrator.migrate File.join(File.dirname(__FILE__), "active_record_support/db/migrate")
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class CreateUsers < ActiveRecord::Migration
|
3
|
+
def change
|
4
|
+
create_table :users do |t|
|
5
|
+
t.string :name
|
6
|
+
t.time :join_date
|
7
|
+
t.string :secret
|
8
|
+
t.boolean :admin
|
9
|
+
t.references :team, foreign_key: true
|
10
|
+
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "active_record_helper"
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
module RailsViewAdapters
|
6
|
+
|
7
|
+
describe "an adapter", integration: true do
|
8
|
+
date_format = "%Y-%m-%dT%H:%M:%S%z"
|
9
|
+
secret_token = Faker::Internet.password
|
10
|
+
Adapter.define(:user_integration_test_adapter) do
|
11
|
+
map_simple :name, :author
|
12
|
+
map_date :join_date, :member_since, date_format
|
13
|
+
map_date :created_at, :created_at, date_format
|
14
|
+
map_date :updated_at, :updated_at, date_format
|
15
|
+
map_bool :admin, :super_user
|
16
|
+
hidden_field :secret
|
17
|
+
map_from_public :secret do |token|
|
18
|
+
{ secret: token }
|
19
|
+
end
|
20
|
+
map_belongs_to :team, :favorite_team, model_class: Team
|
21
|
+
map_has_many :posts, :all_posts, sub_method: :body
|
22
|
+
end
|
23
|
+
|
24
|
+
before(:each) do
|
25
|
+
@model = Fabricate(:user, secret: secret_token)
|
26
|
+
Fabricate.times(3, :post, user: @model)
|
27
|
+
|
28
|
+
@public_hash = {
|
29
|
+
author: @model.name,
|
30
|
+
member_since: @model.join_date.in_time_zone.strftime(date_format),
|
31
|
+
super_user: @model.admin,
|
32
|
+
favorite_team: @model.team.id,
|
33
|
+
all_posts: @model.posts.pluck(:body),
|
34
|
+
created_at: @model.created_at.in_time_zone.strftime(date_format),
|
35
|
+
updated_at: @model.updated_at.in_time_zone.strftime(date_format)
|
36
|
+
}
|
37
|
+
|
38
|
+
@model_hash = {
|
39
|
+
name: @model.name,
|
40
|
+
join_date: @model.join_date,
|
41
|
+
admin: @model.admin,
|
42
|
+
secret: @model.secret,
|
43
|
+
team_id: @model.team_id,
|
44
|
+
posts: @model.posts,
|
45
|
+
created_at: @model.created_at,
|
46
|
+
updated_at: @model.updated_at
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
it_behaves_like "an adapter", secret: secret_token do
|
51
|
+
let(:adapter_class) { UserIntegrationTestAdapter }
|
52
|
+
let(:model) { @model }
|
53
|
+
let(:public_hash) { @public_hash }
|
54
|
+
let(:model_hash) { @model_hash }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
require "active_record_helper"
|
4
|
+
|
5
|
+
module RailsViewAdapters
|
6
|
+
describe AdapterBase do
|
7
|
+
class TestAdapter < AdapterBase
|
8
|
+
def self.simple_maps
|
9
|
+
[[:body, :post_text]]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.to_maps
|
13
|
+
[[:user_id, proc {|v| { user_name: v + 10 } }]]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.from_maps
|
17
|
+
[[:user_name, proc {|v| { user_id: v + 100 } }]]
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.model_fields
|
21
|
+
[:body, :user_id]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.public_fields
|
25
|
+
[:post_text, :user_name]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class ARTestAdapter < TestAdapter
|
30
|
+
def self.to_maps
|
31
|
+
[[:user_id, proc {|v| { user_name: User.find(v).name } }]]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.from_maps
|
35
|
+
[[:user_name, proc {|v| { user_id: User.find_by_name(v).id } }]]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#to_model_hash" do
|
40
|
+
let(:internals) { { a: 1, b: 2 } }
|
41
|
+
it "returns the internals" do
|
42
|
+
expect(described_class.new(internals, {}).to_model_hash).to eql(internals)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#to_params_hash" do
|
47
|
+
let(:internals) { { a: 1, b: 2 } }
|
48
|
+
let(:disjoint_extras) { { c: 3 } }
|
49
|
+
let(:overlapping_extras) { { b: 27, c: 3 } }
|
50
|
+
it "merges internals and extras" do
|
51
|
+
expect(described_class.new(internals, disjoint_extras).to_params_hash)
|
52
|
+
.to eql(a: 1, b: 2, c: 3)
|
53
|
+
end
|
54
|
+
it "prefers internals over extras" do
|
55
|
+
expect(described_class.new(internals, overlapping_extras).to_params_hash)
|
56
|
+
.to eql(a: 1, b: 2, c: 3)
|
57
|
+
end
|
58
|
+
it "symbolizes keys" do
|
59
|
+
expect(described_class.new(internals, "c" => 3).to_params_hash)
|
60
|
+
.to eql(a: 1, b: 2, c: 3)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#to_public_hash" do
|
65
|
+
let(:internals) { { body: 2, user_id: 4 } }
|
66
|
+
let(:extras) { { extra_field: "asdf" } }
|
67
|
+
let(:adapter) { TestAdapter.new(internals, extras) }
|
68
|
+
it "returns the public hash w/o extras" do
|
69
|
+
expect(adapter.to_public_hash).to eql(
|
70
|
+
post_text: 2,
|
71
|
+
user_name: 14
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#to_json" do
|
77
|
+
let(:adapter) { described_class.new({}, {}) }
|
78
|
+
let(:public_hash) { double(:public_hash) }
|
79
|
+
let(:options) { { a: 11_313, b: 1231 } }
|
80
|
+
it "delegates to #to_json on the public hash" do
|
81
|
+
allow(adapter).to receive(:to_public_hash).and_return(public_hash)
|
82
|
+
expect(public_hash).to receive(:to_json).with(options)
|
83
|
+
adapter.to_json(options)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "::from_model" do
|
88
|
+
let(:model) { Fabricate(:post) }
|
89
|
+
it "instantiates the adapter" do
|
90
|
+
expect(TestAdapter.from_model(model)).to be_an_instance_of(TestAdapter)
|
91
|
+
end
|
92
|
+
it "loads the model as its internals" do
|
93
|
+
expect(TestAdapter.from_model(model).to_model_hash).to eql(
|
94
|
+
body: model.body,
|
95
|
+
user_id: model.user_id
|
96
|
+
)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "::from_public" do
|
101
|
+
let(:user) { Fabricate(:user) }
|
102
|
+
let(:input_hash) do
|
103
|
+
{
|
104
|
+
post_text: Faker::Lorem.paragraph,
|
105
|
+
user_name: user.name,
|
106
|
+
extra_field: 12_345
|
107
|
+
}
|
108
|
+
end
|
109
|
+
it "instantiates the adapter" do
|
110
|
+
expect(ARTestAdapter.from_public(input_hash)).to be_an_instance_of(ARTestAdapter)
|
111
|
+
end
|
112
|
+
it "loads the internals" do
|
113
|
+
expect(ARTestAdapter.from_public(input_hash).to_model_hash).to eql(
|
114
|
+
body: input_hash[:post_text],
|
115
|
+
user_id: user.id
|
116
|
+
)
|
117
|
+
end
|
118
|
+
it "loads the extras" do
|
119
|
+
expect(ARTestAdapter.from_public(input_hash).to_params_hash).to eql(
|
120
|
+
body: input_hash[:post_text],
|
121
|
+
user_id: user.id,
|
122
|
+
extra_field: 12_345
|
123
|
+
)
|
124
|
+
end
|
125
|
+
it "doesn't mutate the public representation" do
|
126
|
+
expect(ARTestAdapter.from_public(input_hash).to_public_hash).to eql(
|
127
|
+
post_text: input_hash[:post_text],
|
128
|
+
user_name: input_hash[:user_name]
|
129
|
+
)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
module RailsViewAdapters
|
5
|
+
describe Adapter do
|
6
|
+
describe "::define" do
|
7
|
+
it "defines a new class" do
|
8
|
+
Adapter.define(:new_test_adapter) {}
|
9
|
+
expect do
|
10
|
+
Object.const_get("NewTestAdapter")
|
11
|
+
end.to_not raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
it "sets the constant equal to the created adapter" do
|
15
|
+
spy = double(:spy)
|
16
|
+
allow(Adapter).to receive(:adapter_from_map).and_return(spy)
|
17
|
+
Adapter.define(:even_newer) {}
|
18
|
+
expect(EvenNewer).to eql(spy)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "::adapter_from_map" do
|
23
|
+
let(:map) do
|
24
|
+
double(:map,
|
25
|
+
model_fields: [:m1, :m2],
|
26
|
+
public_fields: [:p1, :p2],
|
27
|
+
simple_maps: [[:m1, :p1]],
|
28
|
+
to_maps: [[:m2, double(:proc1)]],
|
29
|
+
from_maps: [[:p2, double(:proc2)]])
|
30
|
+
end
|
31
|
+
let(:adapter) { Adapter.adapter_from_map(map) }
|
32
|
+
it "returns a new class" do
|
33
|
+
expect(adapter).to be_a(Class)
|
34
|
+
end
|
35
|
+
it "inherits from AdapterBase" do
|
36
|
+
expect(adapter).to be <= AdapterBase
|
37
|
+
end
|
38
|
+
[:model_fields, :public_fields, :simple_maps, :to_maps, :from_maps].each do |field|
|
39
|
+
it "adds the ::#{field} method" do
|
40
|
+
expect(adapter.public_send(field)).to eql(map.public_send(field))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
require "active_record_helper"
|
4
|
+
|
5
|
+
module RailsViewAdapters
|
6
|
+
|
7
|
+
class TestMap < Map
|
8
|
+
def to_hash
|
9
|
+
{
|
10
|
+
model_fields: model_fields,
|
11
|
+
public_fields: public_fields,
|
12
|
+
simple_maps: simple_maps,
|
13
|
+
to_maps: to_maps,
|
14
|
+
from_maps: from_maps
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe DefinitionProxy do
|
20
|
+
let(:proxy) { described_class.new(TestMap.new) }
|
21
|
+
let(:bare_hash) do
|
22
|
+
{
|
23
|
+
model_fields: [],
|
24
|
+
public_fields: [],
|
25
|
+
simple_maps: [],
|
26
|
+
to_maps: [],
|
27
|
+
from_maps: []
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#map_simple" do
|
32
|
+
let(:model_field) { :mod }
|
33
|
+
let(:public_field) { :pub }
|
34
|
+
it "creates the correct mapping" do
|
35
|
+
proxy.map_simple(model_field, public_field)
|
36
|
+
expect(proxy.map.to_hash).to eql(bare_hash.merge(
|
37
|
+
public_fields: [public_field],
|
38
|
+
model_fields: [model_field],
|
39
|
+
simple_maps: [[model_field, public_field]]
|
40
|
+
))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#map_to_public" do
|
45
|
+
let(:model_field) { :mod }
|
46
|
+
let(:extra_fields) { [:one, :two] }
|
47
|
+
let(:process) { proc {|v| { one: v + 1, two: v + 2 } } }
|
48
|
+
it "creates the correct mapping" do
|
49
|
+
proxy.map_to_public(model_field, extra_fields, &process)
|
50
|
+
expect(proxy.map.to_hash).to eql(bare_hash.merge(
|
51
|
+
to_maps: [[model_field, process]],
|
52
|
+
public_fields: extra_fields,
|
53
|
+
model_fields: [model_field]
|
54
|
+
))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#map_from_public" do
|
59
|
+
let(:public_field) { :pub }
|
60
|
+
let(:process) { proc {|v| { one: v + 1, two: v + 2 } } }
|
61
|
+
it "creates the correct mapping" do
|
62
|
+
proxy.map_from_public(public_field, &process)
|
63
|
+
expect(proxy.map.to_hash).to eql(bare_hash.merge(
|
64
|
+
from_maps: [[public_field, process]],
|
65
|
+
public_fields: [public_field]
|
66
|
+
))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#hidden_field" do
|
71
|
+
let(:hidden_field) { :hidden }
|
72
|
+
it "adds a model_field" do
|
73
|
+
proxy.hidden_field(hidden_field)
|
74
|
+
expect(proxy.map.to_hash).to eql(bare_hash.merge(
|
75
|
+
model_fields: [hidden_field]
|
76
|
+
))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#map_date" do
|
81
|
+
let(:model_field) { :mod }
|
82
|
+
let(:public_field) { :pub }
|
83
|
+
let(:date_format) { "%Y-%m-%dT%H:%M:%SZ" }
|
84
|
+
let(:time) { Time.new(2016, 10, 31, 12, 25, 33).utc }
|
85
|
+
let(:time_string) { time.strftime(date_format) }
|
86
|
+
it "creates the correct model_fields" do
|
87
|
+
proxy.map_date(model_field, public_field, date_format)
|
88
|
+
expect(proxy.map.model_fields).to eql([model_field])
|
89
|
+
end
|
90
|
+
it "creates the correct public_fields" do
|
91
|
+
proxy.map_date(model_field, public_field, date_format)
|
92
|
+
expect(proxy.map.public_fields).to eql([public_field])
|
93
|
+
end
|
94
|
+
it "creates no simple_maps" do
|
95
|
+
proxy.map_date(model_field, public_field, date_format)
|
96
|
+
expect(proxy.map.simple_maps).to eql([])
|
97
|
+
end
|
98
|
+
it "creates the correct to_maps" do
|
99
|
+
proxy.map_date(model_field, public_field, date_format)
|
100
|
+
expect(proxy.map.to_maps[0]).to contain_exactly(model_field, an_instance_of(Proc))
|
101
|
+
end
|
102
|
+
it "creates the correct from_maps" do
|
103
|
+
proxy.map_date(model_field, public_field, date_format)
|
104
|
+
expect(proxy.map.from_maps[0]).to contain_exactly(public_field, an_instance_of(Proc))
|
105
|
+
end
|
106
|
+
it "defines a to_map that converts the model's date to the public's string" do
|
107
|
+
proxy.map_date(model_field, public_field, date_format)
|
108
|
+
expect(proxy.map.to_maps[0][1].call(time)).to eql(public_field => time_string)
|
109
|
+
end
|
110
|
+
it "defines a from_map that converts the public's string to the model's Time" do
|
111
|
+
proxy.map_date(model_field, public_field, date_format)
|
112
|
+
expect(proxy.map.from_maps[0][1].call(time_string)).to eql(model_field => time)
|
113
|
+
end
|
114
|
+
it "raises ArgumentError if date_format is nil" do
|
115
|
+
expect do
|
116
|
+
proxy.map_date(model_field, public_field, nil)
|
117
|
+
end.to raise_error ArgumentError
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "#map_bool" do
|
122
|
+
let(:model_field) { :mod }
|
123
|
+
let(:public_field) { :pub }
|
124
|
+
it "creates the correct model_fields" do
|
125
|
+
proxy.map_bool(model_field, public_field)
|
126
|
+
expect(proxy.map.model_fields).to eql([model_field])
|
127
|
+
end
|
128
|
+
it "creates the correct public_fields" do
|
129
|
+
proxy.map_bool(model_field, public_field)
|
130
|
+
expect(proxy.map.public_fields).to eql([public_field])
|
131
|
+
end
|
132
|
+
it "creates the correct to_maps" do
|
133
|
+
proxy.map_bool(model_field, public_field)
|
134
|
+
expect(proxy.map.to_maps[0]).to contain_exactly(model_field, an_instance_of(Proc))
|
135
|
+
end
|
136
|
+
it "creates the correct from_maps" do
|
137
|
+
proxy.map_bool(model_field, public_field)
|
138
|
+
expect(proxy.map.from_maps[0]).to contain_exactly(public_field, an_instance_of(Proc))
|
139
|
+
end
|
140
|
+
[true, false, nil].each do |bool|
|
141
|
+
it "defines a to_map that converts models' #{bool} to public's #{bool}" do
|
142
|
+
proxy.map_bool(model_field, public_field)
|
143
|
+
expect(proxy.map.to_maps[0][1].call(bool)).to eql(public_field => bool)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
["true", "True", "t", "T", "yes", "Yes", "Y", "y", "1"].each do |truthy_string|
|
147
|
+
it "defines a from_map that converts public #{truthy_string} to model true" do
|
148
|
+
proxy.map_bool(model_field, public_field)
|
149
|
+
expect(proxy.map.from_maps[0][1].call(truthy_string)).to eql(model_field => true)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
["false", "False", "f", "F", "no", "No", "N", "n", "0"].each do |falsey_string|
|
153
|
+
it "defines a from_map that converts public #{falsey_string} to model false" do
|
154
|
+
proxy.map_bool(model_field, public_field)
|
155
|
+
expect(proxy.map.from_maps[0][1].call(falsey_string)).to eql(model_field => false)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
[nil, "nil", "null"].each do |null|
|
159
|
+
it "defines a from_map that converts public #{null} to model nil" do
|
160
|
+
proxy.map_bool(model_field, public_field)
|
161
|
+
expect(proxy.map.from_maps[0][1].call(null)).to eql(model_field => nil)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "#map_belongs_to" do
|
167
|
+
let(:model_field) { :user_id }
|
168
|
+
let(:public_field) { :user_name }
|
169
|
+
let(:options) { { model_class: User, sub_method: :name } }
|
170
|
+
let(:post) { Fabricate(:post, user: Fabricate(:user)) }
|
171
|
+
it "creates the correct model_fields" do
|
172
|
+
proxy.map_belongs_to(model_field, public_field, options)
|
173
|
+
expect(proxy.map.model_fields).to contain_exactly(model_field)
|
174
|
+
end
|
175
|
+
it "creates the correct public_fields" do
|
176
|
+
proxy.map_belongs_to(model_field, public_field, options)
|
177
|
+
expect(proxy.map.public_fields).to contain_exactly(public_field)
|
178
|
+
end
|
179
|
+
it "creates no simple_maps" do
|
180
|
+
proxy.map_belongs_to(model_field, public_field, options)
|
181
|
+
expect(proxy.map.simple_maps).to eql([])
|
182
|
+
end
|
183
|
+
it "creates the correct to_maps" do
|
184
|
+
proxy.map_belongs_to(model_field, public_field, options)
|
185
|
+
expect(proxy.map.to_maps[0]).to contain_exactly(model_field, an_instance_of(Proc))
|
186
|
+
end
|
187
|
+
it "creates the correct from_maps" do
|
188
|
+
proxy.map_belongs_to(model_field, public_field, options)
|
189
|
+
expect(proxy.map.from_maps[0]).to contain_exactly(public_field, an_instance_of(Proc))
|
190
|
+
end
|
191
|
+
it "defines a to_map that converts the model's parent to the public's field:value string" do
|
192
|
+
proxy.map_belongs_to(model_field, public_field, options)
|
193
|
+
expect(proxy.map.to_maps[0][1].call(post.user.id))
|
194
|
+
.to eql(public_field => post.user.name)
|
195
|
+
end
|
196
|
+
it "defines a from_map that converts the public's string to the model's owning model id" do
|
197
|
+
proxy.map_belongs_to(model_field, public_field, options)
|
198
|
+
expect(proxy.map.from_maps[0][1].call(post.user.name))
|
199
|
+
.to eql(model_field => post.user.id)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "#map_has_many" do
|
204
|
+
let(:model_field) { :posts }
|
205
|
+
let(:public_field) { :post_dates }
|
206
|
+
let(:options) { { model_class: Post, sub_method: :created_at } }
|
207
|
+
let(:user) { Fabricate(:user) }
|
208
|
+
before(:each) { Fabricate.times(2, :post, user: user) }
|
209
|
+
it "creates the correct model_fields" do
|
210
|
+
proxy.map_has_many(model_field, public_field, options)
|
211
|
+
expect(proxy.map.model_fields).to contain_exactly(model_field)
|
212
|
+
end
|
213
|
+
it "creates the correct public_fields" do
|
214
|
+
proxy.map_has_many(model_field, public_field, options)
|
215
|
+
expect(proxy.map.public_fields).to contain_exactly(public_field)
|
216
|
+
end
|
217
|
+
it "creates no simple_maps" do
|
218
|
+
proxy.map_has_many(model_field, public_field, options)
|
219
|
+
expect(proxy.map.simple_maps).to eql([])
|
220
|
+
end
|
221
|
+
it "creates the correct to_maps" do
|
222
|
+
proxy.map_has_many(model_field, public_field, options)
|
223
|
+
expect(proxy.map.to_maps[0]).to contain_exactly(model_field, an_instance_of(Proc))
|
224
|
+
end
|
225
|
+
it "creates the correct from_maps" do
|
226
|
+
proxy.map_has_many(model_field, public_field, options)
|
227
|
+
expect(proxy.map.from_maps[0]).to contain_exactly(public_field, an_instance_of(Proc))
|
228
|
+
end
|
229
|
+
it "defines a to_map that converts the model's children to the public's Array<String>" do
|
230
|
+
proxy.map_has_many(model_field, public_field, options)
|
231
|
+
expect(proxy.map.to_maps[0][1].call(user.posts))
|
232
|
+
.to eql(public_field => user.posts.pluck(:created_at))
|
233
|
+
end
|
234
|
+
it "defines a from_map that converts the public's string to the model's owning models" do
|
235
|
+
proxy.map_has_many(model_field, public_field, options)
|
236
|
+
expect(proxy.map.from_maps[0][1].call(user.posts.pluck(:created_at).to_a))
|
237
|
+
.to eql(model_field => user.posts.to_a)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|