lookup_by 0.1.0
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.
- data/.gitignore +11 -0
- data/.rvmrc +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +16 -0
- data/MIT-LICENSE +20 -0
- data/README.md +230 -0
- data/Rakefile +14 -0
- data/TODO.md +16 -0
- data/lib/lookup_by/association.rb +89 -0
- data/lib/lookup_by/cache.rb +145 -0
- data/lib/lookup_by/caching/lru.rb +57 -0
- data/lib/lookup_by/caching/safe_lru.rb +30 -0
- data/lib/lookup_by/cucumber.rb +7 -0
- data/lib/lookup_by/hooks/cucumber.rb +9 -0
- data/lib/lookup_by/hooks/formtastic.rb +27 -0
- data/lib/lookup_by/hooks/simple_form.rb +27 -0
- data/lib/lookup_by/lookup.rb +113 -0
- data/lib/lookup_by/railtie.rb +20 -0
- data/lib/lookup_by/version.rb +3 -0
- data/lib/lookup_by.rb +27 -0
- data/lookup_by.gemspec +23 -0
- data/spec/association_spec.rb +102 -0
- data/spec/caching/lru_spec.rb +72 -0
- data/spec/dummy/.rspec +1 -0
- data/spec/dummy/Rakefile +14 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/account.rb +5 -0
- data/spec/dummy/app/models/address.rb +6 -0
- data/spec/dummy/app/models/city.rb +5 -0
- data/spec/dummy/app/models/email_address.rb +5 -0
- data/spec/dummy/app/models/ip_address.rb +5 -0
- data/spec/dummy/app/models/postal_code.rb +5 -0
- data/spec/dummy/app/models/state.rb +5 -0
- data/spec/dummy/app/models/status.rb +9 -0
- data/spec/dummy/app/models/street.rb +5 -0
- data/spec/dummy/config/application.rb +20 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +52 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +15 -0
- data/spec/dummy/config/environments/test.rb +16 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20121019040009_create_tables.rb +23 -0
- data/spec/dummy/db/schema.rb +71 -0
- data/spec/dummy/lib/missing.rb +3 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/lookup_by_spec.rb +100 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/support/shared_examples_for_a_lookup.rb +163 -0
- metadata +140 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
require "active_support/concern"
|
2
|
+
|
3
|
+
module LookupBy
|
4
|
+
module Hooks
|
5
|
+
module SimpleForm
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
alias_method_chain :input, :lookup
|
10
|
+
end
|
11
|
+
|
12
|
+
def input_with_lookup(method, options = {}, &block)
|
13
|
+
klass = object.class
|
14
|
+
|
15
|
+
if klass.respond_to?(:lookups) && klass.lookups.include?(method.to_sym)
|
16
|
+
target = method.to_s.classify.constantize
|
17
|
+
|
18
|
+
options[:collection] ||= target.pluck(target.lookup.field) if target.lookup.cache_all?
|
19
|
+
end
|
20
|
+
|
21
|
+
input_without_lookup(method, options, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
::SimpleForm::FormBuilder.send :include, LookupBy::Hooks::SimpleForm
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module LookupBy
|
2
|
+
module Lookup
|
3
|
+
module MacroMethods
|
4
|
+
def is_a_lookup?
|
5
|
+
is_a? LookupBy::Lookup::ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
def lookup_by(field, options = {})
|
9
|
+
options.symbolize_keys!
|
10
|
+
options.assert_valid_keys :order, :cache, :normalize, :find, :find_or_create, :raise
|
11
|
+
|
12
|
+
raise "#{self} already uses lookup_by" if is_a? LookupBy::Lookup::ClassMethods
|
13
|
+
raise "#{self} responds_to :[], needed for lookup_by" if respond_to? :[]
|
14
|
+
raise "#{self} responds_to :lookup, needed for lookup_by" if respond_to? :lookup
|
15
|
+
|
16
|
+
extend ClassMethods
|
17
|
+
|
18
|
+
class_eval do
|
19
|
+
include InstanceMethods
|
20
|
+
|
21
|
+
class << self; attr_reader :lookup; end
|
22
|
+
|
23
|
+
# validates field, presence: true, uniqueness: true
|
24
|
+
|
25
|
+
unless field == :name || column_names.include?("name")
|
26
|
+
alias_attribute :name, field
|
27
|
+
|
28
|
+
attr_accessible :name if respond_to?(:accessible_attributes) && accessible_attributes.include?(field)
|
29
|
+
end
|
30
|
+
|
31
|
+
@lookup = Cache.new(self, options.merge(field: field))
|
32
|
+
@lookup.reload
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
def all
|
39
|
+
return super if @lookup.read_through?
|
40
|
+
|
41
|
+
@lookup.cache.values
|
42
|
+
end
|
43
|
+
|
44
|
+
def count(column_name = nil, options = {})
|
45
|
+
return super if @lookup.read_through?
|
46
|
+
return super if column_name
|
47
|
+
|
48
|
+
@lookup.cache.size
|
49
|
+
end
|
50
|
+
|
51
|
+
def pluck(column_name)
|
52
|
+
return super if @lookup.read_through?
|
53
|
+
|
54
|
+
@lookup.cache.values.map { |o| o.send(column_name) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def [](arg)
|
58
|
+
case arg
|
59
|
+
when nil, "" then nil
|
60
|
+
when String then @lookup.fetch(arg)
|
61
|
+
when Symbol then @lookup.fetch(arg.to_s)
|
62
|
+
when Fixnum then @lookup.fetch(arg)
|
63
|
+
when self then arg
|
64
|
+
else raise TypeError, "#{name}[arg]: arg must be a String, Symbol, Fixnum, nil, or #{name}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module InstanceMethods
|
70
|
+
def ===(arg)
|
71
|
+
case arg
|
72
|
+
when Symbol, String, Fixnum, nil
|
73
|
+
return self == self.class[arg]
|
74
|
+
when Array
|
75
|
+
return !!arg.detect { |i| self === i }
|
76
|
+
end
|
77
|
+
|
78
|
+
super
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
module SchemaMethods
|
83
|
+
def create_lookup_table(table_name, options = {})
|
84
|
+
lookup_column = options[:lookup_column] || table_name.to_s.singularize
|
85
|
+
primary_key = options[:primary_key] || table_name.to_s.singularize + "_id"
|
86
|
+
|
87
|
+
create_table table_name, primary_key: primary_key do |t|
|
88
|
+
t.text lookup_column, null: false
|
89
|
+
|
90
|
+
yield t if block_given?
|
91
|
+
end
|
92
|
+
|
93
|
+
add_index table_name, lookup_column, unique: true
|
94
|
+
end
|
95
|
+
|
96
|
+
def create_lookup_tables(*table_names)
|
97
|
+
table_names.each do |table_name|
|
98
|
+
create_lookup_table table_name
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
module CommandRecorderMethods
|
104
|
+
def create_lookup_table(*args)
|
105
|
+
record(:create_lookup_table, args)
|
106
|
+
end
|
107
|
+
|
108
|
+
def invert_create_lookup_table(args)
|
109
|
+
[:drop_table, [args.first]]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "active_record/railtie"
|
2
|
+
|
3
|
+
module LookupBy
|
4
|
+
class Railtie < ::Rails::Railtie
|
5
|
+
initializer "lookup_by" do
|
6
|
+
ActiveSupport.on_load :active_record do
|
7
|
+
extend Lookup::MacroMethods
|
8
|
+
extend Association::MacroMethods
|
9
|
+
|
10
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
|
11
|
+
include Lookup::SchemaMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
ActiveRecord::Migration::CommandRecorder.class_eval do
|
15
|
+
include Lookup::CommandRecorderMethods
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/lookup_by.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "lookup_by/version"
|
2
|
+
require "lookup_by/railtie" if defined? Rails
|
3
|
+
|
4
|
+
module LookupBy
|
5
|
+
class Error < StandardError; end
|
6
|
+
|
7
|
+
autoload :Association, "lookup_by/association"
|
8
|
+
autoload :Cache, "lookup_by/cache"
|
9
|
+
autoload :Lookup, "lookup_by/lookup"
|
10
|
+
|
11
|
+
module Caching
|
12
|
+
autoload :LRU, "lookup_by/caching/lru"
|
13
|
+
autoload :SafeLRU, "lookup_by/caching/safe_lru"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
begin
|
18
|
+
require "simple_form"
|
19
|
+
require "lookup_by/hooks/simple_form"
|
20
|
+
rescue LoadError
|
21
|
+
end
|
22
|
+
|
23
|
+
begin
|
24
|
+
require "formtastic"
|
25
|
+
require "lookup_by/hooks/formtastic"
|
26
|
+
rescue LoadError
|
27
|
+
end
|
data/lookup_by.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
require "lookup_by/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "lookup_by"
|
8
|
+
gem.version = LookupBy::VERSION
|
9
|
+
|
10
|
+
gem.summary = %q(A thread-safe lookup table cache for ActiveRecord)
|
11
|
+
gem.description = %q(Use database lookup tables in AR models.)
|
12
|
+
|
13
|
+
gem.authors = ["Erik Peterson"]
|
14
|
+
gem.email = ["erik@enova.com"]
|
15
|
+
|
16
|
+
gem.homepage = "http://www.github.com/companygardener/lookup_by"
|
17
|
+
|
18
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
19
|
+
gem.files = `git ls-files`.split("\n")
|
20
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
|
22
|
+
gem.add_dependency "rails", ">= 3.0.0"
|
23
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "lookup_by"
|
3
|
+
require "pry"
|
4
|
+
|
5
|
+
describe ::ActiveRecord::Base do
|
6
|
+
describe "macro methods" do
|
7
|
+
subject { described_class }
|
8
|
+
|
9
|
+
it { should respond_to :lookup_for }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".lookup_for" do
|
13
|
+
subject { Address }
|
14
|
+
|
15
|
+
it "doesn't clobber methods" do
|
16
|
+
class << subject
|
17
|
+
public :define_method, :remove_method
|
18
|
+
end
|
19
|
+
|
20
|
+
[:foo, :foo=, :raw_foo, :foo_before_type_cast].each do |method|
|
21
|
+
subject.define_method(method) { }
|
22
|
+
|
23
|
+
expect { subject.lookup_for :foo }.to raise_error LookupBy::Error, /already exists/
|
24
|
+
|
25
|
+
subject.remove_method(method)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "requires a foreign key" do
|
30
|
+
expect { subject.lookup_for :missing }.to raise_error LookupBy::Error, /foreign key/
|
31
|
+
end
|
32
|
+
|
33
|
+
it "rejects unsaved lookup values" do
|
34
|
+
expect { subject.new.city = City.new(name: "Toronto") }.to raise_error ArgumentError, /must be saved/
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe LookupBy::Association do
|
40
|
+
before do
|
41
|
+
City.create(name: "New York")
|
42
|
+
end
|
43
|
+
|
44
|
+
after do
|
45
|
+
City.delete_all
|
46
|
+
end
|
47
|
+
|
48
|
+
subject { Address.new }
|
49
|
+
|
50
|
+
context "Address.lookup_for :city, strict: false" do
|
51
|
+
it_behaves_like "a lookup for", :city
|
52
|
+
|
53
|
+
it "accepts Fixnums" do
|
54
|
+
subject.city = City.where(city: "New York").first.id
|
55
|
+
subject.city.should eq "New York"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "rejects symbols" do
|
59
|
+
expect { subject.city = :'New York' }.to raise_error ArgumentError
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns strings" do
|
63
|
+
subject.city = "New York"
|
64
|
+
subject.city.should eq "New York"
|
65
|
+
end
|
66
|
+
|
67
|
+
it "allows missing values" do
|
68
|
+
subject.city = "Chicago"
|
69
|
+
subject.city.should be_nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "Address.lookup_for :state, symbolize: true" do
|
74
|
+
it_behaves_like "a lookup for", :state
|
75
|
+
|
76
|
+
it "allows symbols" do
|
77
|
+
subject.state = :AL
|
78
|
+
subject.state.should eq :AL
|
79
|
+
end
|
80
|
+
|
81
|
+
it "returns symbols" do
|
82
|
+
subject.state = "AL"
|
83
|
+
subject.state.should eq :AL
|
84
|
+
end
|
85
|
+
|
86
|
+
it "rejects missing values" do
|
87
|
+
expect { subject.state = "FOO" }.to raise_error LookupBy::Error, /not in the .* lookup cache/
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "Address.lookup_for :street" do
|
92
|
+
it "accepts write-through values" do
|
93
|
+
expect { subject.street = "Dearborn Street" }.to change(Street, :count)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "Missing.lookup_for :city" do
|
98
|
+
it "does not raise foreign key error when table hasn't been created" do
|
99
|
+
expect { require "missing"; }.to_not raise_error
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "lookup_by/caching/lru"
|
3
|
+
|
4
|
+
include LookupBy::Caching
|
5
|
+
|
6
|
+
module LookupBy::Caching
|
7
|
+
describe LRU do
|
8
|
+
before(:each) do
|
9
|
+
@cache = LRU.new(2)
|
10
|
+
|
11
|
+
@cache[1] = "one"
|
12
|
+
@cache[2] = "two"
|
13
|
+
end
|
14
|
+
|
15
|
+
subject { @cache }
|
16
|
+
|
17
|
+
it "stores entries" do
|
18
|
+
@cache[1].should eq "one"
|
19
|
+
@cache[2].should eq "two"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "drops oldest" do
|
23
|
+
@cache[3] = "three"
|
24
|
+
|
25
|
+
@cache[1].should be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it "keeps gets" do
|
29
|
+
@cache[1]
|
30
|
+
@cache[3] = "three"
|
31
|
+
|
32
|
+
@cache[1].should eq "one"
|
33
|
+
@cache[2].should be_nil
|
34
|
+
@cache[3].should eq "three"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "keeps sets" do
|
38
|
+
@cache[1] = "one"
|
39
|
+
@cache[3] = "three"
|
40
|
+
|
41
|
+
@cache[1].should eq "one"
|
42
|
+
@cache[2].should be_nil
|
43
|
+
@cache[3].should eq "three"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "#clear" do
|
47
|
+
cache = LRU.new(2)
|
48
|
+
|
49
|
+
cache[1] = "one"
|
50
|
+
cache.size.should eq 1
|
51
|
+
cache.clear
|
52
|
+
cache.size.should eq 0
|
53
|
+
end
|
54
|
+
|
55
|
+
specify "#merge" do
|
56
|
+
@cache.merge(1 => "change", 3 => "three").should
|
57
|
+
eq(1 => "change", 2 => "two", 3 => "three")
|
58
|
+
end
|
59
|
+
|
60
|
+
specify "#merge!" do
|
61
|
+
cache = LRU.new(3)
|
62
|
+
|
63
|
+
cache[1] = "one"
|
64
|
+
cache[2] = "two"
|
65
|
+
|
66
|
+
cache.merge!(1 => "change", 3 => "three")
|
67
|
+
cache.should eq(1 => "change", 2 => "two", 3 => "three")
|
68
|
+
end
|
69
|
+
|
70
|
+
its(:to_h) { should eq(1 => "one", 2 => "two") }
|
71
|
+
end
|
72
|
+
end
|
data/spec/dummy/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/dummy/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
3
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
4
|
+
|
5
|
+
require File.expand_path('../config/application', __FILE__)
|
6
|
+
|
7
|
+
Dummy::Application.load_tasks
|
8
|
+
|
9
|
+
require "rspec/core/rake_task"
|
10
|
+
RSpec::Core::RakeTask.new(:spec) do |config|
|
11
|
+
config.pattern = FileList["../**/*_spec.rb"]
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default => :spec
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.expand_path('../boot', __FILE__)
|
2
|
+
|
3
|
+
require "active_record/railtie"
|
4
|
+
|
5
|
+
Bundler.require
|
6
|
+
require "lookup_by"
|
7
|
+
|
8
|
+
module Dummy
|
9
|
+
class Application < Rails::Application
|
10
|
+
# Configure the default encoding used in templates for Ruby 1.9.
|
11
|
+
config.encoding = "utf-8"
|
12
|
+
|
13
|
+
# Enforce whitelist mode for mass assignment.
|
14
|
+
# This will create an empty whitelist of attributes available for mass-assignment for all models
|
15
|
+
# in your app. As such, your models will need to explicitly whitelist or blacklist accessible
|
16
|
+
# parameters by using an attr_accessible or attr_protected declaration.
|
17
|
+
config.active_record.whitelist_attributes = true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# PostgreSQL. Versions 8.2 and up are supported.
|
2
|
+
#
|
3
|
+
# Install the pg driver:
|
4
|
+
# gem install pg
|
5
|
+
# On Mac OS X with macports:
|
6
|
+
# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
|
7
|
+
# On Windows:
|
8
|
+
# gem install pg
|
9
|
+
# Choose the win32 build.
|
10
|
+
# Install PostgreSQL and put its /bin directory on your path.
|
11
|
+
#
|
12
|
+
# Configure Using Gemfile
|
13
|
+
# gem 'pg'
|
14
|
+
#
|
15
|
+
development:
|
16
|
+
adapter: postgresql
|
17
|
+
encoding: unicode
|
18
|
+
database: lookup_by_development
|
19
|
+
pool: 5
|
20
|
+
username: dummy
|
21
|
+
password:
|
22
|
+
|
23
|
+
# Connect on a TCP socket. Omitted by default since the client uses a
|
24
|
+
# domain socket that doesn't need configuration. Windows does not have
|
25
|
+
# domain sockets, so uncomment these lines.
|
26
|
+
#host: localhost
|
27
|
+
#port: 5432
|
28
|
+
|
29
|
+
# Schema search path. The server defaults to $user,public
|
30
|
+
#schema_search_path: myapp,sharedapp,public
|
31
|
+
|
32
|
+
# Minimum log levels, in increasing order:
|
33
|
+
# debug5, debug4, debug3, debug2, debug1,
|
34
|
+
# log, notice, warning, error, fatal, and panic
|
35
|
+
# The server defaults to notice.
|
36
|
+
#min_messages: warning
|
37
|
+
|
38
|
+
# Warning: The database defined as "test" will be erased and
|
39
|
+
# re-generated from your development database when you run "rake".
|
40
|
+
# Do not set this db to the same as development or production.
|
41
|
+
test:
|
42
|
+
adapter: postgresql
|
43
|
+
database: lookup_by_test
|
44
|
+
username: postgres
|
45
|
+
|
46
|
+
production:
|
47
|
+
adapter: postgresql
|
48
|
+
encoding: unicode
|
49
|
+
database: dummy_production
|
50
|
+
pool: 5
|
51
|
+
username: dummy
|
52
|
+
password:
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Dummy::Application.configure do
|
2
|
+
# In the development environment your application's code is reloaded on
|
3
|
+
# every request. This slows down response time but is perfect for development
|
4
|
+
# since you don't have to restart the web server when you make code changes.
|
5
|
+
config.cache_classes = false
|
6
|
+
|
7
|
+
# Log error messages when you accidentally call methods on nil.
|
8
|
+
config.whiny_nils = true
|
9
|
+
|
10
|
+
# Print deprecation notices to the Rails logger
|
11
|
+
config.active_support.deprecation = :log
|
12
|
+
|
13
|
+
# Raise exception on mass assignment protection for Active Record models
|
14
|
+
config.active_record.mass_assignment_sanitizer = :strict
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Dummy::Application.configure do
|
2
|
+
# The test environment is used exclusively to run your application's
|
3
|
+
# test suite. You never need to work with it otherwise. Remember that
|
4
|
+
# your test database is "scratch space" for the test suite and is wiped
|
5
|
+
# and recreated between test runs. Don't rely on the data there!
|
6
|
+
config.cache_classes = true
|
7
|
+
|
8
|
+
# Log error messages when you accidentally call methods on nil
|
9
|
+
config.whiny_nils = true
|
10
|
+
|
11
|
+
# Raise exception on mass assignment protection for Active Record models
|
12
|
+
config.active_record.mass_assignment_sanitizer = :strict
|
13
|
+
|
14
|
+
# Print deprecation notices to the stderr
|
15
|
+
config.active_support.deprecation = :stderr
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class CreateTables < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
create_lookup_tables :cities, :states, :postal_codes, :streets
|
4
|
+
|
5
|
+
create_lookup_table :ip_addresses
|
6
|
+
create_lookup_table :email_addresses
|
7
|
+
|
8
|
+
create_lookup_table :accounts
|
9
|
+
create_lookup_table :statuses
|
10
|
+
|
11
|
+
create_table :addresses, primary_key: "address_id" do |t|
|
12
|
+
t.belongs_to :city
|
13
|
+
t.belongs_to :state
|
14
|
+
t.belongs_to :postal_code
|
15
|
+
t.belongs_to :street
|
16
|
+
end
|
17
|
+
|
18
|
+
State.create(name: "AL")
|
19
|
+
end
|
20
|
+
|
21
|
+
def down
|
22
|
+
end
|
23
|
+
end
|