activerecord-define_nils 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ Define Nils for ActiveRecord 3.x/4.x and Rails 3.x/4.x
2
+ =====
3
+
4
+ If working with a legacy database used by another application that uses a non-null value to mean null, you may need to translate certain values to nil to make them more normal to work with in Ruby/Rails and then save nil as a specific value.
5
+
6
+ For example, if nil is stored as 0 in `my_id`:
7
+
8
+ define_nils as: 0, for: :my_id
9
+
10
+ If nil is stored as 0 in `my_id` and `your_id`:
11
+
12
+ define_nils as: 0, for: [:my_id, :your_id]
13
+
14
+ If you want to accept 0 or '' as nil for `my_id` but save nil as 0:
15
+
16
+ define_nils as: [0, ''], for: :my_id, saving_as: 0
17
+
18
+ It will choose the only/first element in the as if you don't specify `saving_as`, so a less clear way to define that is:
19
+
20
+ define_nils as: [0, ''], for: :my_id
21
+
22
+ If you want to accept 0 or '' as nil for `my_id` and `your_id` but save nil as nil/null:
23
+
24
+ define_nils as: [0, ''], for: [:my_id, :your_id], saving_as: nil
25
+
26
+ It handles `read_attribute` calls, calls to the attribute name, and all `belongs_to` associations defined after the `define_nils` that use the specified attribute as a foreign_key. It also will show the value as nil in calls to inspect/returned values in rails console. So, for the most part it should look as if the value is nil within Ruby but on the database-side, nil is stored as whatever value you want to represent nil.
27
+
28
+ ### Setup
29
+
30
+ In your ActiveRecord/Rails 3.1+ project, add this to your Gemfile:
31
+
32
+ gem 'activerecord-define_nils'
33
+
34
+ For the development version:
35
+
36
+ gem 'activerecord-define_nils', :git => 'git://github.com/garysweaver/activerecord-define_nils.git'
37
+
38
+ Then run:
39
+
40
+ bundle install
41
+
42
+ ### Usage
43
+
44
+ If you are on Rails, the concern `ActiveRecordDefineNils::Model` is included automatically in `ActiveRecord::Base` via railtie.
45
+
46
+ Be sure to place `define_nils` above your `belongs_to` associations in the model class or those associations will query on unaltered foreign key values, which is probably not what you want.
47
+
48
+ ### License
49
+
50
+ Copyright (c) 2012 Gary S. Weaver, released under the [MIT license][lic].
51
+
52
+ [lic]: http://github.com/garysweaver/activerecord-define_nils/blob/master/LICENSE
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new(:test) do |t|
4
+ t.libs << 'test'
5
+ t.test_files = FileList['test/**/*_test.rb']
6
+ t.verbose = true
7
+ end
8
+
9
+ desc "Run tests"
10
+ task :default => :test
@@ -0,0 +1,76 @@
1
+ module ActiveRecordDefineNils
2
+ module Model
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :nil_definitions, instance_writer: false
7
+ class_attribute :nil_saved_as, instance_writer: false
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ def define_nils(options)
13
+ raise ArgumentError.new("define_nils takes a hash, but got #{options.inspect}") unless options.is_a?(Hash)
14
+ if options.has_key?(:as) && options.has_key?(:for)
15
+ self.nil_saved_as ||= {}
16
+ self.nil_definitions ||= {}
17
+ as_vals = Array.wrap(options[:as])
18
+ raise ArgumentError.new("define_nils must supply at least one value for :as, but got #{options.inspect}") if as_vals.size == 0
19
+ Array.wrap(options[:for]).each do |attr_name|
20
+ attr_sym = attr_name.to_sym
21
+ self.nil_saved_as[attr_sym] = options[:saving_as] || as_vals[0]
22
+ self.nil_definitions[attr_sym] = as_vals
23
+ class_eval "def #{attr_name}; value = super(); self.nil_definitions && self.nil_definitions[#{attr_sym.inspect}] && self.nil_definitions[#{attr_sym.inspect}].include?(value) ? nil : value; end"
24
+ end
25
+ else
26
+ raise ArgumentError.new("define_nils must at least supply :as and :for, but got #{options.inspect}")
27
+ end
28
+ end
29
+
30
+ def belongs_to(*args)
31
+ super(*args)
32
+ return unless self.nil_definitions
33
+ # after belongs_to is finished, we wrap it
34
+ self.nil_definitions.keys.each do |attr_sym|
35
+ self.reflections.collect {|association_name, reflection|
36
+ if reflection.macro == :belongs_to && reflection.foreign_key.to_sym == attr_sym
37
+ class_eval "def #{association_name}; return nil if send(#{attr_sym.inspect}).nil?; super(); end"
38
+ end
39
+ }
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ def read_attribute(attr_name)
46
+ value = super(attr_name)
47
+ self.nil_definitions && self.nil_definitions[attr_name.to_sym] && self.nil_definitions[attr_name.to_sym].include?(value) ? nil : value
48
+ end
49
+
50
+ private
51
+
52
+ def create
53
+ if self.nil_saved_as
54
+ self.nil_saved_as.each do |column, translated_nil|
55
+ if respond_to?(column) && respond_to?("#{column}=") && self.send(column).nil?
56
+ write_attribute(column.to_s, translated_nil)
57
+ end
58
+ end
59
+ end
60
+
61
+ super
62
+ end
63
+
64
+ def update(*args)
65
+ if self.nil_saved_as
66
+ self.nil_saved_as.each do |column, translated_nil|
67
+ if respond_to?(column) && respond_to?("#{column}=") && self.send(column).nil?
68
+ write_attribute(column.to_s, translated_nil)
69
+ end
70
+ end
71
+ end
72
+
73
+ super
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,11 @@
1
+ require 'activerecord-define_nils'
2
+
3
+ module ActiveRecordDefineNils
4
+ class Railtie < Rails::Railtie
5
+ initializer "define_nils.active_record" do
6
+ ActiveSupport.on_load(:active_record) do
7
+ include ActiveRecordDefineNils::Model
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveRecordDefineNils
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'activerecord-define_nils/version'
2
+ require 'activerecord-define_nils/model'
3
+ require 'activerecord-define_nils/railtie' if defined?(Rails)
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord-define_nils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gary S. Weaver
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Allows you to redefine what is translated to nil on read and what is
31
+ stored instead of nil for specified attributes.
32
+ email:
33
+ - garysweaver@gmail.com
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - lib/activerecord-define_nils/model.rb
39
+ - lib/activerecord-define_nils/railtie.rb
40
+ - lib/activerecord-define_nils/version.rb
41
+ - lib/activerecord-define_nils.rb
42
+ - Rakefile
43
+ - README.md
44
+ homepage: https://github.com/garysweaver/activerecord-define_nils
45
+ licenses:
46
+ - MIT
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.24
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Define nils for ActiveRecord 3.x/4.x.
69
+ test_files: []