nobrainer 0.14.0 → 0.15.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 43783bcf0d625af679de685ab771782ce9b141f3
4
- data.tar.gz: 4b5e4ff205f55adb754133b681b6e71c71772790
3
+ metadata.gz: e97dd4f563340a2c8551ffefb21f22fc628954b2
4
+ data.tar.gz: 1fca054e8f966be9e7518f8245c39987d40068c7
5
5
  SHA512:
6
- metadata.gz: 1c182d056390dd2c7b51bac68999d79c72cfaca49837239c4eead56ce8d0ff474630cc7b24e9fa12a4ff8d36641a5f6cc46fb7c588c45e975af42e8d4b5dbebc
7
- data.tar.gz: 5226adb01498de4e82f8b3a4729c818ed1a40dc07e3596061d64956407b9a62129108046e0625bbe60bcac1804f0b8111cab4ec3a736151b6cfdc3d5799f2d88
6
+ metadata.gz: 1cbfebfa6ac2922e733d157522eda4e6c9edf9de9e51601f6892ac2ac2814593ed20807c68441a2ff7391398cf37896eeb739eaf2cdafa0da8e9fe91bb02fce2
7
+ data.tar.gz: ace1719ae85c7593145e81818fb1b93f715ad65d4634130c664b0fdd134c637aba0395066163b9fd3aee91f7ec0b27a53338e857ec2c089a4b425e02f2eba00b
@@ -4,7 +4,8 @@ module NoBrainer::Config
4
4
  class << self
5
5
  mattr_accessor :rethinkdb_url, :logger, :warn_on_active_record,
6
6
  :auto_create_databases, :auto_create_tables,
7
- :max_reconnection_tries, :durability, :colorize_logger,
7
+ :max_reconnection_tries, :durability,
8
+ :user_timezone, :db_timezone, :colorize_logger,
8
9
  :distributed_lock_class
9
10
 
10
11
  def apply_defaults
@@ -15,6 +16,8 @@ module NoBrainer::Config
15
16
  self.auto_create_tables = true
16
17
  self.max_reconnection_tries = 10
17
18
  self.durability = default_durability
19
+ self.user_timezone = :local
20
+ self.db_timezone = :utc
18
21
  self.colorize_logger = true
19
22
  self.distributed_lock_class = nil
20
23
  end
@@ -27,6 +30,7 @@ module NoBrainer::Config
27
30
  def configure(&block)
28
31
  apply_defaults unless configured?
29
32
  block.call(self) if block
33
+ assert_valid_options!
30
34
  @configured = true
31
35
 
32
36
  NoBrainer.disconnect_if_url_changed
@@ -36,6 +40,18 @@ module NoBrainer::Config
36
40
  !!@configured
37
41
  end
38
42
 
43
+ def assert_valid_options!
44
+ assert_array_in :durability, [:hard, :soft]
45
+ assert_array_in :user_timezone, [:unchanged, :utc, :local]
46
+ assert_array_in :db_timezone, [:unchanged, :utc, :local]
47
+ end
48
+
49
+ def assert_array_in(name, values)
50
+ unless __send__(name).in?(values)
51
+ raise ArgumentError.new("Unknown configuration for #{name}: #{__send__(name)}. Valid values are: #{values.inspect}")
52
+ end
53
+ end
54
+
39
55
  def default_rethinkdb_url
40
56
  db = ENV['RETHINKDB_DB'] || ENV['RDB_DB']
41
57
  db ||= "#{Rails.application.class.parent_name.underscore}_#{Rails.env}" rescue nil
@@ -2,7 +2,7 @@ module NoBrainer::Criteria::Count
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  def count
5
- run(to_rql.count)
5
+ run(without_ordering.to_rql.count)
6
6
  end
7
7
 
8
8
  def empty?
@@ -17,6 +17,12 @@ module NoBrainer::Criteria::First
17
17
  last.tap { |doc| raise NoBrainer::Error::DocumentNotFound unless doc }
18
18
  end
19
19
 
20
+ def sample(n=nil)
21
+ result = NoBrainer.run { self.without_ordering.to_rql.sample(n.nil? ? 1 : n) }
22
+ result = result.map(&method(:instantiate_doc))
23
+ n.nil? ? result.first : result
24
+ end
25
+
20
26
  private
21
27
 
22
28
  def get_one(criteria)
@@ -54,24 +54,26 @@ module NoBrainer::Criteria::Where
54
54
  end
55
55
  end
56
56
 
57
- class BinaryOperator < Struct.new(:key, :op, :value, :criteria)
57
+ class BinaryOperator < Struct.new(:key, :op, :value, :criteria, :casted_values)
58
58
  def simplify
59
59
  key = cast_key(self.key)
60
60
  case op
61
61
  when :in then
62
62
  case value
63
- when Range then BinaryOperator.new(key, :between, (cast_value(value.min)..cast_value(value.max)), criteria)
64
- when Array then BinaryOperator.new(key, :in, value.map(&method(:cast_value)).uniq, criteria)
63
+ when Range then BinaryOperator.new(key, :between, (cast_value(value.min)..cast_value(value.max)), criteria, true)
64
+ when Array then BinaryOperator.new(key, :in, value.map(&method(:cast_value)).uniq, criteria, true)
65
65
  else raise ArgumentError.new ":in takes an array/range, not #{value}"
66
66
  end
67
- else BinaryOperator.new(key, op, cast_value(value), criteria)
67
+ when :between then BinaryOperator.new(key, :between, (cast_value(value.min)..cast_value(value.max)), criteria, true)
68
+ else BinaryOperator.new(key, op, cast_value(value), criteria, true)
68
69
  end
69
70
  end
70
71
 
71
72
  def to_rql(doc)
72
73
  case op
74
+ when :defined then value ? doc.has_fields(key) : doc.has_fields(key).not
73
75
  when :between then (doc[key] >= value.min) & (doc[key] <= value.max)
74
- when :in then RethinkDB::RQL.new.expr(value).contains(doc[key])
76
+ when :in then RethinkDB::RQL.new.expr(value).contains(doc[key])
75
77
  else doc[key].__send__(op, value)
76
78
  end
77
79
  end
@@ -87,6 +89,8 @@ module NoBrainer::Criteria::Where
87
89
  end
88
90
 
89
91
  def cast_value(value)
92
+ return value if casted_values
93
+
90
94
  case association
91
95
  when NoBrainer::Document::Association::BelongsTo::Metadata
92
96
  target_klass = association.target_klass
@@ -99,6 +103,8 @@ module NoBrainer::Criteria::Where
99
103
  end
100
104
 
101
105
  def cast_key(key)
106
+ return key if casted_values
107
+
102
108
  case association
103
109
  when NoBrainer::Document::Association::BelongsTo::Metadata
104
110
  association.foreign_key
@@ -2,7 +2,8 @@ class NoBrainer::DecoratedSymbol < Struct.new(:symbol, :modifier, :args)
2
2
  MODIFIERS = { :in => :in, :nin => :nin,
3
3
  :eq => :eq, :ne => :ne, :not => :ne,
4
4
  :gt => :gt, :ge => :ge, :gte => :ge,
5
- :lt => :lt, :le => :le, :lte => :le}
5
+ :lt => :lt, :le => :le, :lte => :le,
6
+ :defined => :defined }
6
7
 
7
8
  def self.hook
8
9
  Symbol.class_eval do
@@ -1,7 +1,5 @@
1
1
  module NoBrainer::Document::Attributes
2
- VALID_FIELD_OPTIONS = [:index, :default, :type, :cast_user_to_db,
3
- :cast_db_to_user, :validates, :required, :unique,
4
- :readonly, :primary_key]
2
+ VALID_FIELD_OPTIONS = [:index, :default, :type, :validates, :required, :unique, :in, :readonly, :primary_key]
5
3
  RESERVED_FIELD_NAMES = [:index, :default, :and, :or, :selector, :associations, :pk_value] \
6
4
  + NoBrainer::DecoratedSymbol::MODIFIERS.keys
7
5
  extend ActiveSupport::Concern
@@ -64,6 +62,10 @@ module NoBrainer::Document::Attributes
64
62
  Hash[@_attributes.sort_by { |k,v| self.class.fields.keys.index(k.to_sym) || 2**10 }]
65
63
  end
66
64
 
65
+ def to_s
66
+ "#<#{self.class} #{self.class.pk_name}: #{self.pk_value.inspect}>"
67
+ end
68
+
67
69
  def inspect
68
70
  "#<#{self.class} #{inspectable_attributes.map { |k,v| "#{k}: #{v.inspect}" }.join(', ')}>"
69
71
  end
@@ -10,7 +10,7 @@ module NoBrainer::Document::Criteria
10
10
  module ClassMethods
11
11
  delegate :to_rql, # Core
12
12
  :limit, :offset, :skip, # Limit
13
- :order_by, :reverse_order, # OrderBy
13
+ :order_by, :reverse_order, :without_ordering, # OrderBy
14
14
  :scoped, :unscoped, # Scope
15
15
  :where, :with_index, :without_index, :used_index, :indexed?, # Where
16
16
  :with_cache, :without_cache, # Cache
@@ -18,7 +18,7 @@ module NoBrainer::Document::Criteria
18
18
  :delete_all, :destroy_all, # Delete
19
19
  :includes, :preload, # Preload
20
20
  :each, :to_a, # Enumerable
21
- :first, :last, :first!, :last!, # First
21
+ :first, :last, :first!, :last!, :sample, # First
22
22
  :update_all, :replace_all, # Update
23
23
  :to => :all
24
24
 
@@ -28,7 +28,7 @@ module NoBrainer::Document::Persistance
28
28
 
29
29
  def _create(options={})
30
30
  return false if options[:validate] && !valid?
31
- keys = self.class.insert_all(@_attributes)
31
+ keys = self.class.insert_all(self.class.persistable_attributes(@_attributes))
32
32
  self.pk_value ||= keys.first
33
33
  @new_record = false
34
34
  true
@@ -50,7 +50,7 @@ module NoBrainer::Document::Persistance
50
50
  attr = RethinkDB::RQL.new.literal(attr) if attr.is_a?(Hash)
51
51
  [k, attr]
52
52
  end]
53
- _update(attrs) if attrs.present?
53
+ _update(self.class.persistable_attributes(attrs)) if attrs.present?
54
54
  true
55
55
  end
56
56
 
@@ -1,102 +1,7 @@
1
1
  module NoBrainer::Document::Types
2
2
  extend ActiveSupport::Concern
3
3
 
4
- module CastUserToDB
5
- extend self
6
- InvalidType = NoBrainer::Error::InvalidType
7
-
8
- def String(value)
9
- case value
10
- when Symbol then value.to_s
11
- else raise InvalidType
12
- end
13
- end
14
-
15
- def Integer(value)
16
- case value
17
- when String
18
- value = value.strip.gsub(/^\+/, '')
19
- value.to_i.tap { |new_value| new_value.to_s == value or raise InvalidType }
20
- when Float
21
- value.to_i.tap { |new_value| new_value.to_f == value or raise InvalidType }
22
- else raise InvalidType
23
- end
24
- end
25
-
26
- def Float(value)
27
- case value
28
- when Integer then value.to_f
29
- when String
30
- value = value.strip.gsub(/^\+/, '')
31
- value = value.gsub(/0+$/, '') if value['.']
32
- value = value.gsub(/\.$/, '')
33
- value = "#{value}.0" unless value['.']
34
- value.to_f.tap { |new_value| new_value.to_s == value or raise InvalidType }
35
- else raise InvalidType
36
- end
37
- end
38
-
39
- def Boolean(value)
40
- case value
41
- when TrueClass then true
42
- when FalseClass then false
43
- when String, Integer
44
- value = value.to_s.strip.downcase
45
- return true if value.in? %w(true yes t 1)
46
- return false if value.in? %w(false no f 0)
47
- raise InvalidType
48
- else raise InvalidType
49
- end
50
- end
51
-
52
- def Symbol(value)
53
- case value
54
- when String
55
- value = value.strip
56
- raise InvalidType if value.empty?
57
- value.to_sym
58
- else raise InvalidType
59
- end
60
- end
61
-
62
- def lookup(type)
63
- public_method(type.to_s)
64
- rescue NameError
65
- proc { raise InvalidType }
66
- end
67
- end
68
-
69
- module CastDBToUser
70
- extend self
71
-
72
- def Symbol(value)
73
- value.to_sym rescue value
74
- end
75
-
76
- def lookup(type)
77
- public_method(type.to_s)
78
- rescue NameError
79
- nil
80
- end
81
- end
82
-
83
- included do
84
- # We namespace our fake Boolean class to avoid polluting the global namespace
85
- class_exec do
86
- class Boolean
87
- def initialize; raise; end
88
- def self.inspect; 'Boolean'; end
89
- def self.to_s; inspect; end
90
- def self.name; inspect; end
91
- end
92
- end
93
- before_validation :add_type_errors
94
-
95
- # Fast access for db->user cast methods for performance when reading from
96
- # the database.
97
- singleton_class.send(:attr_accessor, :cast_db_to_user_fields)
98
- self.cast_db_to_user_fields = Set.new
99
- end
4
+ included { before_validation :add_type_errors }
100
5
 
101
6
  def add_type_errors
102
7
  return unless @pending_type_errors
@@ -108,49 +13,59 @@ module NoBrainer::Document::Types
108
13
  def assign_attributes(attrs, options={})
109
14
  super
110
15
  if options[:from_db]
111
- self.class.cast_db_to_user_fields.each do |attr|
112
- field_def = self.class.fields[attr]
113
- type = field_def[:type]
114
- value = @_attributes[attr.to_s]
115
- unless value.nil? || value.is_a?(type)
116
- @_attributes[attr.to_s] = field_def[:cast_db_to_user].call(value)
117
- end
118
- end
16
+ @_attributes = Hash[@_attributes.map do |k,v|
17
+ [k, self.class.cast_db_to_model_for(k, v)]
18
+ end].with_indifferent_access
119
19
  end
120
20
  end
121
21
 
122
22
  module ClassMethods
123
- def cast_user_to_db_for(attr, value)
124
- field_def = fields[attr.to_sym]
125
- return value if !field_def
126
- type = field_def[:type]
127
- return value if value.nil? || type.nil? || value.is_a?(type)
128
- field_def[:cast_user_to_db].call(value)
23
+ def cast_user_to_model_for(attr, value)
24
+ type = fields[attr.to_sym].try(:[], :type)
25
+ return value if type.nil? || value.nil?
26
+ if type.respond_to?(:nobrainer_cast_user_to_model)
27
+ type.nobrainer_cast_user_to_model(value)
28
+ else
29
+ raise NoBrainer::Error::InvalidType unless value.is_a?(type)
30
+ value
31
+ end
129
32
  rescue NoBrainer::Error::InvalidType => error
130
- error.type = field_def[:type]
33
+ error.type = type
131
34
  error.value = value
132
35
  error.attr_name = attr
133
36
  raise error
134
37
  end
135
38
 
136
- def inherited(subclass)
137
- super
138
- subclass.cast_db_to_user_fields = self.cast_db_to_user_fields.dup
39
+ def cast_model_to_db_for(attr, value)
40
+ type = fields[attr.to_sym].try(:[], :type)
41
+ return value if type.nil? || value.nil? || !type.respond_to?(:nobrainer_cast_model_to_db)
42
+ type.nobrainer_cast_model_to_db(value)
43
+ end
44
+
45
+ def cast_db_to_model_for(attr, value)
46
+ type = fields[attr.to_sym].try(:[], :type)
47
+ return value if type.nil? || value.nil? || !type.respond_to?(:nobrainer_cast_db_to_model)
48
+ type.nobrainer_cast_db_to_model(value)
49
+ end
50
+
51
+ def cast_user_to_db_for(attr, value)
52
+ value = cast_user_to_model_for(attr, value)
53
+ cast_model_to_db_for(attr, value)
54
+ end
55
+
56
+ def persistable_attributes(attrs)
57
+ Hash[attrs.map { |k,v| [k, cast_model_to_db_for(k, v)] }]
139
58
  end
140
59
 
141
60
  def _field(attr, options={})
142
61
  super
143
62
 
144
- if options[:cast_db_to_user]
145
- ([self] + descendants).each do |klass|
146
- klass.cast_db_to_user_fields << attr
147
- end
148
- end
63
+ NoBrainer::Document::Types.load_type_extensions(options[:type]) if options[:type]
149
64
 
150
65
  inject_in_layer :types do
151
66
  define_method("#{attr}=") do |value|
152
67
  begin
153
- value = self.class.cast_user_to_db_for(attr, value)
68
+ value = self.class.cast_user_to_model_for(attr, value)
154
69
  @pending_type_errors.try(:delete, attr)
155
70
  rescue NoBrainer::Error::InvalidType => error
156
71
  @pending_type_errors ||= {}
@@ -163,21 +78,38 @@ module NoBrainer::Document::Types
163
78
  end
164
79
  end
165
80
 
166
- def field(attr, options={})
167
- if options[:type]
168
- options = options.merge(
169
- :cast_user_to_db => NoBrainer::Document::Types::CastUserToDB.lookup(options[:type]),
170
- :cast_db_to_user => NoBrainer::Document::Types::CastDBToUser.lookup(options[:type]))
171
- end
172
- super
173
- end
174
-
175
81
  def _remove_field(attr, options={})
176
82
  super
83
+
177
84
  inject_in_layer :types do
178
85
  remove_method("#{attr}=")
179
86
  remove_method("#{attr}?") if method_defined?("#{attr}?")
180
87
  end
181
88
  end
89
+
90
+ def field(attr, options={})
91
+ if options[:type] == Array || options[:type] == Hash
92
+ # XXX For the moment, NoBrainer does not support these complex types
93
+ options.delete(:type)
94
+ end
95
+ super
96
+ end
97
+ end
98
+
99
+ require File.join(File.dirname(__FILE__), 'types', 'boolean')
100
+ Boolean = NoBrainer::Boolean
101
+
102
+ class << self
103
+ mattr_accessor :loaded_extensions
104
+ self.loaded_extensions = Set.new
105
+ def load_type_extensions(klass)
106
+ unless loaded_extensions.include?(klass)
107
+ begin
108
+ require File.join(File.dirname(__FILE__), 'types', klass.name.underscore)
109
+ rescue LoadError
110
+ end
111
+ loaded_extensions << klass
112
+ end
113
+ end
182
114
  end
183
115
  end
@@ -0,0 +1,26 @@
1
+ # We namespace our fake Boolean class to avoid polluting the global namespace
2
+ class NoBrainer::Boolean
3
+ def initialize; raise; end
4
+ def self.inspect; 'Boolean'; end
5
+ def self.to_s; inspect; end
6
+ def self.name; inspect; end
7
+
8
+ module NoBrainerExtentions
9
+ InvalidType = NoBrainer::Error::InvalidType
10
+
11
+ def nobrainer_cast_user_to_model(value)
12
+ case value
13
+ when TrueClass then true
14
+ when FalseClass then false
15
+ when String, Integer
16
+ value = value.to_s.strip.downcase
17
+ return true if value.in? %w(true yes t 1)
18
+ return false if value.in? %w(false no f 0)
19
+ raise InvalidType
20
+ else raise InvalidType
21
+ end
22
+ end
23
+ end
24
+ extend NoBrainerExtentions
25
+ end
26
+
@@ -0,0 +1,26 @@
1
+ class Date
2
+ module NoBrainerExtentions
3
+ InvalidType = NoBrainer::Error::InvalidType
4
+
5
+ def nobrainer_cast_user_to_model(value)
6
+ case value
7
+ when Date then value
8
+ when String
9
+ value = value.strip
10
+ date = Date.parse(value) rescue (raise InvalidType)
11
+ raise InvalidType unless date.iso8601 == value
12
+ date
13
+ else raise InvalidType
14
+ end
15
+ end
16
+
17
+ def nobrainer_cast_db_to_model(value)
18
+ value.is_a?(Time) ? value.to_date : value
19
+ end
20
+
21
+ def nobrainer_cast_model_to_db(value)
22
+ value.is_a?(Date) ? Time.utc(value.year, value.month, value.day) : value
23
+ end
24
+ end
25
+ extend NoBrainerExtentions
26
+ end
@@ -0,0 +1,20 @@
1
+ class Float
2
+ module NoBrainerExtentions
3
+ InvalidType = NoBrainer::Error::InvalidType
4
+
5
+ def nobrainer_cast_user_to_model(value)
6
+ case value
7
+ when Float then value
8
+ when Integer then value.to_f
9
+ when String
10
+ value = value.strip.gsub(/^\+/, '')
11
+ value = value.gsub(/0+$/, '') if value['.']
12
+ value = value.gsub(/\.$/, '')
13
+ value = "#{value}.0" unless value['.']
14
+ value.to_f.tap { |new_value| new_value.to_s == value or raise InvalidType }
15
+ else raise InvalidType
16
+ end
17
+ end
18
+ end
19
+ extend NoBrainerExtentions
20
+ end
@@ -0,0 +1,18 @@
1
+ class Integer
2
+ module NoBrainerExtentions
3
+ InvalidType = NoBrainer::Error::InvalidType
4
+
5
+ def nobrainer_cast_user_to_model(value)
6
+ case value
7
+ when Integer then value
8
+ when String
9
+ value = value.strip.gsub(/^\+/, '')
10
+ value.to_i.tap { |new_value| new_value.to_s == value or raise InvalidType }
11
+ when Float
12
+ value.to_i.tap { |new_value| new_value.to_f == value or raise InvalidType }
13
+ else raise InvalidType
14
+ end
15
+ end
16
+ end
17
+ extend NoBrainerExtentions
18
+ end
@@ -0,0 +1,14 @@
1
+ class String
2
+ module NoBrainerExtentions
3
+ InvalidType = NoBrainer::Error::InvalidType
4
+
5
+ def nobrainer_cast_user_to_model(value)
6
+ case value
7
+ when String then value
8
+ when Symbol then value.to_s
9
+ else raise InvalidType
10
+ end
11
+ end
12
+ end
13
+ extend NoBrainerExtentions
14
+ end
@@ -0,0 +1,21 @@
1
+ class Symbol
2
+ module NoBrainerExtentions
3
+ InvalidType = NoBrainer::Error::InvalidType
4
+
5
+ def nobrainer_cast_user_to_model(value)
6
+ case value
7
+ when Symbol then value
8
+ when String
9
+ value = value.strip
10
+ raise InvalidType if value.empty?
11
+ value.to_sym
12
+ else raise InvalidType
13
+ end
14
+ end
15
+
16
+ def nobrainer_cast_db_to_model(value)
17
+ value.to_sym rescue (value.to_s.to_sym rescue value)
18
+ end
19
+ end
20
+ extend NoBrainerExtentions
21
+ end
@@ -0,0 +1,41 @@
1
+ require 'time'
2
+
3
+ class Time
4
+ module NoBrainerExtentions
5
+ InvalidType = NoBrainer::Error::InvalidType
6
+
7
+ def nobrainer_cast_user_to_model(value)
8
+ case value
9
+ when Time then time = value
10
+ when String
11
+ value = value.strip.sub(/Z$/, '+00:00')
12
+ # Using DateTime to preserve the timezone offset
13
+ dt = DateTime.parse(value) rescue (raise InvalidType)
14
+ time = Time.new(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.zone)
15
+ raise InvalidType unless time.iso8601 == value
16
+ else raise InvalidType
17
+ end
18
+
19
+ nobrainer_timezoned(NoBrainer::Config.user_timezone, time)
20
+ end
21
+
22
+ def nobrainer_cast_db_to_model(value)
23
+ return value unless value.is_a?(Time)
24
+ nobrainer_timezoned(NoBrainer::Config.user_timezone, value)
25
+ end
26
+
27
+ def nobrainer_cast_model_to_db(value)
28
+ return value unless value.is_a?(Time)
29
+ nobrainer_timezoned(NoBrainer::Config.db_timezone, value)
30
+ end
31
+
32
+ def nobrainer_timezoned(tz, value)
33
+ case tz
34
+ when :local then value.getlocal
35
+ when :utc then value.getutc
36
+ when :unchanged then value
37
+ end
38
+ end
39
+ end
40
+ extend NoBrainerExtentions
41
+ end
@@ -18,6 +18,7 @@ module NoBrainer::Document::Validation
18
18
  super
19
19
  validates(attr, { :presence => options[:required] }) if options.has_key?(:required)
20
20
  validates(attr, { :uniqueness => options[:unique] }) if options.has_key?(:unique)
21
+ validates(attr, { :inclusion => {:in => options[:in]} }) if options.has_key?(:in)
21
22
  validates(attr, options[:validates]) if options[:validates]
22
23
  end
23
24
  end
@@ -33,7 +33,7 @@ module NoBrainer::Error
33
33
  end
34
34
 
35
35
  def message
36
- "#{attr_name} should be used with a #{human_type_name}. Got `#{value}`"
36
+ "#{attr_name} should be used with a #{human_type_name}. Got `#{value}` (#{value.class})"
37
37
  end
38
38
  end
39
39
  end
data/lib/nobrainer.rb CHANGED
@@ -45,6 +45,10 @@ module NoBrainer
45
45
  def jruby?
46
46
  RUBY_PLATFORM == 'java'
47
47
  end
48
+
49
+ def user_caller
50
+ caller.reject { |s| s =~ /\/no_brainer\// }.first
51
+ end
48
52
  end
49
53
 
50
54
  DecoratedSymbol.hook
@@ -2,7 +2,8 @@ require "rails/generators/nobrainer"
2
2
 
3
3
  module NoBrainer::Generators
4
4
  class ModelGenerator < Base
5
- argument :attributes, :type => :array, default: [], banner: "field ... field"
5
+ argument(:attributes, :type => :array, default: [],
6
+ banner: "field[:type][:index] ... field[:type][:index]")
6
7
 
7
8
  check_class_collision
8
9
 
@@ -2,12 +2,17 @@
2
2
  class <%= class_name %><%= " < #{options[:parent].classify}" if options[:parent] %>
3
3
  <% unless options[:parent] -%>
4
4
  include NoBrainer::Document
5
+ include NoBrainer::Document::Timestamps
6
+
5
7
  <% end -%>
6
8
  <% attributes.reject(&:reference?).each do |attribute| -%>
7
- field :<%= attribute.name %>
9
+ field :<%= attribute.name -%>
10
+ <%= puts attribute; ", :type => #{attribute.type.to_s.classify}" if attribute.type != :object -%>
11
+ <%= ", :index => true" if attribute.has_index? %>
8
12
  <% end -%>
9
13
  <% attributes.select(&:reference?).each do |attribute| -%>
10
- belongs_to :<%= attribute.name %>
14
+ belongs_to :<%= attribute.name -%>
15
+ <%= ", :index => true" if attribute.has_index? %>
11
16
  <% end -%>
12
17
  end
13
18
  <% end -%>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nobrainer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicolas Viennot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-17 00:00:00.000000000 Z
11
+ date: 2014-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rethinkdb
@@ -119,6 +119,13 @@ files:
119
119
  - lib/no_brainer/document/store_in.rb
120
120
  - lib/no_brainer/document/timestamps.rb
121
121
  - lib/no_brainer/document/types.rb
122
+ - lib/no_brainer/document/types/boolean.rb
123
+ - lib/no_brainer/document/types/date.rb
124
+ - lib/no_brainer/document/types/float.rb
125
+ - lib/no_brainer/document/types/integer.rb
126
+ - lib/no_brainer/document/types/string.rb
127
+ - lib/no_brainer/document/types/symbol.rb
128
+ - lib/no_brainer/document/types/time.rb
122
129
  - lib/no_brainer/document/uniqueness.rb
123
130
  - lib/no_brainer/document/validation.rb
124
131
  - lib/no_brainer/error.rb