datastax_rails 2.0.12 → 2.0.15
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/Rakefile +5 -5
- data/lib/blankslate.rb +8 -11
- data/lib/cql-rb_extensions.rb +5 -3
- data/lib/datastax_rails/associations/association.rb +93 -101
- data/lib/datastax_rails/associations/association_scope.rb +7 -7
- data/lib/datastax_rails/associations/belongs_to_association.rb +46 -48
- data/lib/datastax_rails/associations/builder/association.rb +32 -31
- data/lib/datastax_rails/associations/builder/belongs_to.rb +19 -20
- data/lib/datastax_rails/associations/builder/collection_association.rb +32 -32
- data/lib/datastax_rails/associations/builder/has_and_belongs_to_many.rb +21 -21
- data/lib/datastax_rails/associations/builder/has_many.rb +39 -40
- data/lib/datastax_rails/associations/builder/has_one.rb +30 -31
- data/lib/datastax_rails/associations/builder/singular_association.rb +31 -33
- data/lib/datastax_rails/associations/collection_association.rb +129 -135
- data/lib/datastax_rails/associations/collection_proxy.rb +21 -21
- data/lib/datastax_rails/associations/has_and_belongs_to_many_association.rb +26 -26
- data/lib/datastax_rails/associations/has_many_association.rb +38 -38
- data/lib/datastax_rails/associations/has_one_association.rb +31 -32
- data/lib/datastax_rails/associations/singular_association.rb +31 -30
- data/lib/datastax_rails/associations.rb +27 -24
- data/lib/datastax_rails/attribute_assignment.rb +17 -17
- data/lib/datastax_rails/attribute_methods/definition.rb +4 -4
- data/lib/datastax_rails/attribute_methods/dirty.rb +34 -33
- data/lib/datastax_rails/attribute_methods/primary_key.rb +3 -8
- data/lib/datastax_rails/attribute_methods/read.rb +10 -12
- data/lib/datastax_rails/attribute_methods/typecasting.rb +36 -35
- data/lib/datastax_rails/attribute_methods/write.rb +5 -6
- data/lib/datastax_rails/attribute_methods.rb +52 -56
- data/lib/datastax_rails/base.rb +122 -125
- data/lib/datastax_rails/callbacks.rb +15 -9
- data/lib/datastax_rails/cassandra_only_model.rb +6 -6
- data/lib/datastax_rails/collection.rb +5 -7
- data/lib/datastax_rails/column.rb +130 -118
- data/lib/datastax_rails/connection/statement_cache.rb +3 -3
- data/lib/datastax_rails/connection.rb +42 -33
- data/lib/datastax_rails/cql/alter_column_family.rb +19 -21
- data/lib/datastax_rails/cql/base.rb +8 -11
- data/lib/datastax_rails/cql/column_family.rb +11 -10
- data/lib/datastax_rails/cql/consistency.rb +2 -2
- data/lib/datastax_rails/cql/create_column_family.rb +15 -15
- data/lib/datastax_rails/cql/create_index.rb +5 -5
- data/lib/datastax_rails/cql/create_keyspace.rb +7 -7
- data/lib/datastax_rails/cql/delete.rb +16 -29
- data/lib/datastax_rails/cql/drop_column_family.rb +2 -2
- data/lib/datastax_rails/cql/drop_index.rb +2 -2
- data/lib/datastax_rails/cql/drop_keyspace.rb +2 -2
- data/lib/datastax_rails/cql/insert.rb +10 -16
- data/lib/datastax_rails/cql/select.rb +21 -33
- data/lib/datastax_rails/cql/truncate.rb +2 -2
- data/lib/datastax_rails/cql/update.rb +16 -24
- data/lib/datastax_rails/cql/use_keyspace.rb +2 -2
- data/lib/datastax_rails/cql.rb +2 -2
- data/lib/datastax_rails/dynamic_model.rb +32 -29
- data/lib/datastax_rails/errors.rb +6 -6
- data/lib/datastax_rails/grouped_collection.rb +3 -3
- data/lib/datastax_rails/inheritance.rb +9 -9
- data/lib/datastax_rails/payload_model.rb +24 -20
- data/lib/datastax_rails/persistence.rb +116 -110
- data/lib/datastax_rails/railtie.rb +7 -7
- data/lib/datastax_rails/reflection.rb +61 -59
- data/lib/datastax_rails/relation/batches.rb +12 -13
- data/lib/datastax_rails/relation/facet_methods.rb +44 -33
- data/lib/datastax_rails/relation/finder_methods.rb +95 -91
- data/lib/datastax_rails/relation/modification_methods.rb +5 -5
- data/lib/datastax_rails/relation/search_methods.rb +102 -102
- data/lib/datastax_rails/relation/spawn_methods.rb +25 -24
- data/lib/datastax_rails/relation/stats_methods.rb +9 -8
- data/lib/datastax_rails/relation.rb +165 -170
- data/lib/datastax_rails/rsolr_client_wrapper.rb +3 -3
- data/lib/datastax_rails/schema/cassandra.rb +44 -43
- data/lib/datastax_rails/schema/migrator.rb +52 -52
- data/lib/datastax_rails/schema/solr.rb +55 -47
- data/lib/datastax_rails/schema_cache.rb +1 -3
- data/lib/datastax_rails/scoping/default.rb +2 -3
- data/lib/datastax_rails/scoping/named.rb +3 -5
- data/lib/datastax_rails/scoping.rb +11 -12
- data/lib/datastax_rails/serialization.rb +34 -31
- data/lib/datastax_rails/serializers/xml_serializer.rb +178 -175
- data/lib/datastax_rails/timestamps.rb +4 -4
- data/lib/datastax_rails/types/dirty_collection.rb +57 -57
- data/lib/datastax_rails/types/dynamic_list.rb +1 -1
- data/lib/datastax_rails/types/dynamic_map.rb +5 -7
- data/lib/datastax_rails/types/dynamic_set.rb +2 -2
- data/lib/datastax_rails/util/solr_repair.rb +3 -3
- data/lib/datastax_rails/validations/associated.rb +8 -6
- data/lib/datastax_rails/validations/uniqueness.rb +8 -8
- data/lib/datastax_rails/validations.rb +9 -10
- data/lib/datastax_rails/version.rb +2 -1
- data/lib/datastax_rails/wide_storage_model.rb +6 -6
- data/lib/datastax_rails.rb +13 -9
- data/lib/schema_migration.rb +3 -3
- data/spec/datastax_rails/associations/belongs_to_association_spec.rb +2 -2
- data/spec/datastax_rails/associations/collection_association_spec.rb +14 -14
- data/spec/datastax_rails/associations/has_many_association_spec.rb +20 -20
- data/spec/datastax_rails/associations_spec.rb +11 -11
- data/spec/datastax_rails/attribute_methods_spec.rb +25 -25
- data/spec/datastax_rails/base_spec.rb +24 -24
- data/spec/datastax_rails/callbacks_spec.rb +21 -21
- data/spec/datastax_rails/column_spec.rb +133 -132
- data/spec/datastax_rails/connection/statement_cache_spec.rb +2 -2
- data/spec/datastax_rails/cql/base_spec.rb +4 -4
- data/spec/datastax_rails/cql/delete_spec.rb +19 -0
- data/spec/datastax_rails/cql/select_spec.rb +8 -8
- data/spec/datastax_rails/cql/update_spec.rb +8 -10
- data/spec/datastax_rails/dynamic_model_spec.rb +36 -22
- data/spec/datastax_rails/inheritance_spec.rb +11 -14
- data/spec/datastax_rails/persistence_spec.rb +73 -74
- data/spec/datastax_rails/relation/batches_spec.rb +13 -13
- data/spec/datastax_rails/relation/facet_methods_spec.rb +43 -35
- data/spec/datastax_rails/relation/finder_methods_spec.rb +77 -78
- data/spec/datastax_rails/relation/modification_methods_spec.rb +19 -19
- data/spec/datastax_rails/relation/search_methods_spec.rb +160 -160
- data/spec/datastax_rails/relation/spawn_methods_spec.rb +18 -18
- data/spec/datastax_rails/relation_spec.rb +119 -116
- data/spec/datastax_rails/schema/migrator_spec.rb +30 -30
- data/spec/datastax_rails/schema/solr_spec.rb +15 -15
- data/spec/datastax_rails/scoping/default_spec.rb +9 -9
- data/spec/datastax_rails/types/dynamic_list_spec.rb +12 -12
- data/spec/datastax_rails/types/dynamic_map_spec.rb +10 -10
- data/spec/datastax_rails/types/dynamic_set_spec.rb +22 -10
- data/spec/datastax_rails/validations/uniqueness_spec.rb +25 -25
- data/spec/datastax_rails/wide_storage_model_spec.rb +11 -0
- data/spec/datastax_rails_spec.rb +2 -2
- data/spec/dummy/config/application.rb +2 -3
- data/spec/dummy/config/boot.rb +1 -1
- data/spec/dummy/config/environments/development.rb +3 -3
- data/spec/dummy/config/environments/test.rb +1 -1
- data/spec/dummy/config/initializers/session_store.rb +1 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +1 -1
- data/spec/factories/audit_logs.rb +6 -0
- data/spec/factories/hobbies.rb +6 -0
- data/spec/factories/people.rb +5 -0
- data/spec/feature/dynamic_fields_spec.rb +4 -4
- data/spec/feature/overloaded_tables_spec.rb +11 -12
- data/spec/spec_helper.rb +17 -14
- data/spec/support/datastax_test_hook.rb +2 -2
- data/spec/support/default_consistency_shared_examples.rb +11 -11
- data/spec/support/models.rb +31 -32
- metadata +40 -6
- data/lib/datastax_rails/attribute_methods/before_type_cast.rb +0 -71
- data/lib/datastax_rails/log_subscriber.rb +0 -0
- data/spec/dummy/ks/migrate/20111117224534_models.rb +0 -20
@@ -12,9 +12,7 @@ module DatastaxRails
|
|
12
12
|
end
|
13
13
|
|
14
14
|
@columns_hash = Hash.new do |h, table_name|
|
15
|
-
h[table_name] = Hash[columns[table_name].map { |col|
|
16
|
-
[col.name, col]
|
17
|
-
}]
|
15
|
+
h[table_name] = Hash[columns[table_name].map { |col| [col.name, col] }]
|
18
16
|
end
|
19
17
|
|
20
18
|
@primary_keys = Hash.new do |h, table_name|
|
@@ -7,7 +7,7 @@ module DatastaxRails
|
|
7
7
|
|
8
8
|
included do
|
9
9
|
# Stores the default scope for the class
|
10
|
-
class_attribute :default_scopes, :
|
10
|
+
class_attribute :default_scopes, instance_writer: false
|
11
11
|
self.default_scopes = []
|
12
12
|
end
|
13
13
|
|
@@ -102,7 +102,7 @@ module DatastaxRails
|
|
102
102
|
evaluate_default_scope { default_scope }
|
103
103
|
elsif default_scopes.any?
|
104
104
|
evaluate_default_scope do
|
105
|
-
default_scopes.
|
105
|
+
default_scopes.reduce(relation) do |default_scope, scope|
|
106
106
|
if scope.is_a?(Hash)
|
107
107
|
default_scope.apply_finder_options(scope)
|
108
108
|
elsif !scope.is_a?(Relation) && scope.respond_to?(:call)
|
@@ -135,7 +135,6 @@ module DatastaxRails
|
|
135
135
|
self.ignore_default_scope = false
|
136
136
|
end
|
137
137
|
end
|
138
|
-
|
139
138
|
end
|
140
139
|
end
|
141
140
|
end
|
@@ -186,13 +186,11 @@ module DatastaxRails
|
|
186
186
|
singleton_class.send(:redefine_method, name, &scope_proc)
|
187
187
|
end
|
188
188
|
|
189
|
-
|
189
|
+
protected
|
190
190
|
|
191
191
|
def valid_scope_name?(name)
|
192
|
-
|
193
|
-
logger.warn
|
194
|
-
"Overwriting existing method #{self.name}.#{name}."
|
195
|
-
end
|
192
|
+
logger && respond_to?(name, true) &&
|
193
|
+
logger.warn("Creating scope :#{name}. Overwriting existing method #{self.name}.#{name}.")
|
196
194
|
end
|
197
195
|
end
|
198
196
|
end
|
@@ -57,11 +57,10 @@ module DatastaxRails
|
|
57
57
|
# end
|
58
58
|
#
|
59
59
|
# *Note*: the +:find+ scope also has effect on update and deletion methods, like +update_all+ and +delete_all+.
|
60
|
-
def with_scope(scope = {}, action = :merge, &
|
60
|
+
def with_scope(scope = {}, action = :merge, &_block) # rubocop:disable Style/CyclomaticComplexity
|
61
61
|
# If another DatastaxRails class has been passed in, get its current scope
|
62
62
|
scope = scope.current_scope if !scope.is_a?(Relation) && scope.respond_to?(:current_scope)
|
63
|
-
|
64
|
-
previous_scope = self.current_scope
|
63
|
+
previous_scope = current_scope
|
65
64
|
|
66
65
|
if scope.is_a?(Hash)
|
67
66
|
# Dup first and second level of hash (method and params).
|
@@ -70,16 +69,16 @@ module DatastaxRails
|
|
70
69
|
scope[method] = params.dup unless params == true
|
71
70
|
end
|
72
71
|
|
73
|
-
scope.assert_valid_keys([
|
72
|
+
scope.assert_valid_keys([:find, :create])
|
74
73
|
relation = construct_finder_arel(scope[:find] || {})
|
75
74
|
relation.default_scoped = true unless action == :overwrite
|
76
75
|
|
77
76
|
if previous_scope && previous_scope.create_with_value && scope[:create]
|
78
77
|
scope_for_create = if action == :merge
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
78
|
+
previous_scope.create_with_value.merge(scope[:create])
|
79
|
+
else
|
80
|
+
scope[:create]
|
81
|
+
end
|
83
82
|
|
84
83
|
relation = relation.create_with(scope_for_create)
|
85
84
|
else
|
@@ -106,8 +105,9 @@ module DatastaxRails
|
|
106
105
|
# Works like with_scope, but discards any nested properties.
|
107
106
|
def with_exclusive_scope(method_scoping = {}, &block)
|
108
107
|
if method_scoping.values.any? { |e| e.is_a?(DatastaxRails::Relation) }
|
109
|
-
|
110
|
-
New finder API can not be used with_exclusive_scope. You can either call unscoped to get
|
108
|
+
fail ArgumentError, <<-MSG
|
109
|
+
New finder API can not be used with_exclusive_scope. You can either call unscoped to get
|
110
|
+
an anonymous scope not bound to the default_scope:
|
111
111
|
|
112
112
|
User.unscoped.where(:active => true)
|
113
113
|
|
@@ -137,13 +137,12 @@ module DatastaxRails
|
|
137
137
|
relation = scope.merge(relation) if scope
|
138
138
|
relation
|
139
139
|
end
|
140
|
-
|
141
140
|
end
|
142
141
|
|
143
142
|
def populate_with_current_scope_attributes
|
144
143
|
return unless self.class.scope_attributes?
|
145
144
|
|
146
|
-
self.class.scope_attributes.each do |att,value|
|
145
|
+
self.class.scope_attributes.each do |att, value|
|
147
146
|
send("#{att}=", value) if respond_to?("#{att}=")
|
148
147
|
end
|
149
148
|
end
|
@@ -12,52 +12,55 @@ module DatastaxRails
|
|
12
12
|
hash = super(options)
|
13
13
|
|
14
14
|
serializable_add_includes(options) do |association, records, opts|
|
15
|
-
hash[association] = records.is_a?(Enumerable)
|
16
|
-
|
17
|
-
|
15
|
+
hash[association] = if records.is_a?(Enumerable)
|
16
|
+
records.map { |r| r.serializable_hash(opts) }
|
17
|
+
else
|
18
|
+
records.serializable_hash(opts)
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
22
|
hash
|
21
23
|
end
|
22
|
-
|
24
|
+
|
23
25
|
def as_json(options = {})
|
24
26
|
json = super(options)
|
25
|
-
json.each {|k,v| json[k] = v.to_s if v.is_a?(::Cql::Uuid)}
|
27
|
+
json.each { |k, v| json[k] = v.to_s if v.is_a?(::Cql::Uuid) }
|
26
28
|
end
|
27
29
|
|
28
30
|
private
|
29
|
-
# Add associations specified via the <tt>:include</tt> option.
|
30
|
-
#
|
31
|
-
# Expects a block that takes as arguments:
|
32
|
-
# +association+ - name of the association
|
33
|
-
# +records+ - the association record(s) to be serialized
|
34
|
-
# +opts+ - options for the association records
|
35
|
-
def serializable_add_includes(options = {})
|
36
|
-
return unless include_associations = options.delete(:include)
|
37
31
|
|
38
|
-
|
39
|
-
|
32
|
+
# Add associations specified via the <tt>:include</tt> option.
|
33
|
+
#
|
34
|
+
# Expects a block that takes as arguments:
|
35
|
+
# +association+ - name of the association
|
36
|
+
# +records+ - the association record(s) to be serialized
|
37
|
+
# +opts+ - options for the association records
|
38
|
+
def serializable_add_includes(options = {})
|
39
|
+
include_associations = options.delete(:include)
|
40
|
+
return unless include_associations
|
40
41
|
|
41
|
-
|
42
|
-
|
42
|
+
base_only_or_except = { except: options[:except],
|
43
|
+
only: options[:only] }
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
when :has_many, :has_and_belongs_to_many
|
47
|
-
send(association).to_a
|
48
|
-
when :has_one, :belongs_to
|
49
|
-
send(association)
|
50
|
-
end
|
45
|
+
include_has_options = include_associations.is_a?(Hash)
|
46
|
+
associations = include_has_options ? include_associations.keys : Array.wrap(include_associations)
|
51
47
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
48
|
+
associations.each do |association|
|
49
|
+
records = case self.class.reflect_on_association(association).macro
|
50
|
+
when :has_many, :has_and_belongs_to_many
|
51
|
+
send(association).to_a
|
52
|
+
when :has_one, :belongs_to
|
53
|
+
send(association)
|
54
|
+
end
|
58
55
|
|
59
|
-
|
56
|
+
next unless records
|
57
|
+
association_options = include_has_options ? include_associations[association] : base_only_or_except
|
58
|
+
opts = options.merge(association_options)
|
59
|
+
yield(association, records, opts)
|
60
60
|
end
|
61
|
+
|
62
|
+
options[:include] = include_associations
|
63
|
+
end
|
61
64
|
end
|
62
65
|
end
|
63
66
|
|
@@ -2,175 +2,176 @@ require 'active_support/core_ext/array/wrap'
|
|
2
2
|
require 'active_support/core_ext/hash/conversions'
|
3
3
|
|
4
4
|
module DatastaxRails
|
5
|
+
# Builds an XML document to represent the model. Some configuration is
|
6
|
+
# available through +options+. However more complicated cases should
|
7
|
+
# override DatastaxRails::Base#to_xml.
|
8
|
+
#
|
9
|
+
# By default the generated XML document will include the processing
|
10
|
+
# instruction and all the object's attributes. For example:
|
11
|
+
#
|
12
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
13
|
+
# <topic>
|
14
|
+
# <title>The First Topic</title>
|
15
|
+
# <author-name>David</author-name>
|
16
|
+
# <id type="integer">1</id>
|
17
|
+
# <approved type="boolean">false</approved>
|
18
|
+
# <replies-count type="integer">0</replies-count>
|
19
|
+
# <bonus-time type="datetime">2000-01-01T08:28:00+12:00</bonus-time>
|
20
|
+
# <written-on type="datetime">2003-07-16T09:28:00+1200</written-on>
|
21
|
+
# <content>Have a nice day</content>
|
22
|
+
# <author-email-address>david@loudthinking.com</author-email-address>
|
23
|
+
# <parent-id></parent-id>
|
24
|
+
# <last-read type="date">2004-04-15</last-read>
|
25
|
+
# </topic>
|
26
|
+
#
|
27
|
+
# This behavior can be controlled with <tt>:only</tt>, <tt>:except</tt>,
|
28
|
+
# <tt>:skip_instruct</tt>, <tt>:skip_types</tt>, <tt>:dasherize</tt> and <tt>:camelize</tt> .
|
29
|
+
# The <tt>:only</tt> and <tt>:except</tt> options are the same as for the
|
30
|
+
# +attributes+ method. The default is to dasherize all column names, but you
|
31
|
+
# can disable this setting <tt>:dasherize</tt> to +false+. Setting <tt>:camelize</tt>
|
32
|
+
# to +true+ will camelize all column names - this also overrides <tt>:dasherize</tt>.
|
33
|
+
# To not have the column type included in the XML output set <tt>:skip_types</tt> to +true+.
|
34
|
+
#
|
35
|
+
# For instance:
|
36
|
+
#
|
37
|
+
# topic.to_xml(:skip_instruct => true, :except => [ :id, :bonus_time, :written_on, :replies_count ])
|
38
|
+
#
|
39
|
+
# <topic>
|
40
|
+
# <title>The First Topic</title>
|
41
|
+
# <author-name>David</author-name>
|
42
|
+
# <approved type="boolean">false</approved>
|
43
|
+
# <content>Have a nice day</content>
|
44
|
+
# <author-email-address>david@loudthinking.com</author-email-address>
|
45
|
+
# <parent-id></parent-id>
|
46
|
+
# <last-read type="date">2004-04-15</last-read>
|
47
|
+
# </topic>
|
48
|
+
#
|
49
|
+
# To include first level associations use <tt>:include</tt>:
|
50
|
+
#
|
51
|
+
# firm.to_xml :include => [ :account, :clients ]
|
52
|
+
#
|
53
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
54
|
+
# <firm>
|
55
|
+
# <id type="integer">1</id>
|
56
|
+
# <rating type="integer">1</rating>
|
57
|
+
# <name>37signals</name>
|
58
|
+
# <clients type="array">
|
59
|
+
# <client>
|
60
|
+
# <rating type="integer">1</rating>
|
61
|
+
# <name>Summit</name>
|
62
|
+
# </client>
|
63
|
+
# <client>
|
64
|
+
# <rating type="integer">1</rating>
|
65
|
+
# <name>Microsoft</name>
|
66
|
+
# </client>
|
67
|
+
# </clients>
|
68
|
+
# <account>
|
69
|
+
# <id type="integer">1</id>
|
70
|
+
# <credit-limit type="integer">50</credit-limit>
|
71
|
+
# </account>
|
72
|
+
# </firm>
|
73
|
+
#
|
74
|
+
# Additionally, the record being serialized will be passed to a Proc's second
|
75
|
+
# parameter. This allows for ad hoc additions to the resultant document that
|
76
|
+
# incorporate the context of the record being serialized. And by leveraging the
|
77
|
+
# closure created by a Proc, to_xml can be used to add elements that normally fall
|
78
|
+
# outside of the scope of the model -- for example, generating and appending URLs
|
79
|
+
# associated with models.
|
80
|
+
#
|
81
|
+
# proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) }
|
82
|
+
# firm.to_xml :procs => [ proc ]
|
83
|
+
#
|
84
|
+
# <firm>
|
85
|
+
# # ... normal attributes as shown above ...
|
86
|
+
# <name-reverse>slangis73</name-reverse>
|
87
|
+
# </firm>
|
88
|
+
#
|
89
|
+
# To include deeper levels of associations pass a hash like this:
|
90
|
+
#
|
91
|
+
# firm.to_xml :include => {:account => {}, :clients => {:include => :address}}
|
92
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
93
|
+
# <firm>
|
94
|
+
# <id type="integer">1</id>
|
95
|
+
# <rating type="integer">1</rating>
|
96
|
+
# <name>37signals</name>
|
97
|
+
# <clients type="array">
|
98
|
+
# <client>
|
99
|
+
# <rating type="integer">1</rating>
|
100
|
+
# <name>Summit</name>
|
101
|
+
# <address>
|
102
|
+
# ...
|
103
|
+
# </address>
|
104
|
+
# </client>
|
105
|
+
# <client>
|
106
|
+
# <rating type="integer">1</rating>
|
107
|
+
# <name>Microsoft</name>
|
108
|
+
# <address>
|
109
|
+
# ...
|
110
|
+
# </address>
|
111
|
+
# </client>
|
112
|
+
# </clients>
|
113
|
+
# <account>
|
114
|
+
# <id type="integer">1</id>
|
115
|
+
# <credit-limit type="integer">50</credit-limit>
|
116
|
+
# </account>
|
117
|
+
# </firm>
|
118
|
+
#
|
119
|
+
# To include any methods on the model being called use <tt>:methods</tt>:
|
120
|
+
#
|
121
|
+
# firm.to_xml :methods => [ :calculated_earnings, :real_earnings ]
|
122
|
+
#
|
123
|
+
# <firm>
|
124
|
+
# # ... normal attributes as shown above ...
|
125
|
+
# <calculated-earnings>100000000000000000</calculated-earnings>
|
126
|
+
# <real-earnings>5</real-earnings>
|
127
|
+
# </firm>
|
128
|
+
#
|
129
|
+
# To call any additional Procs use <tt>:procs</tt>. The Procs are passed a
|
130
|
+
# modified version of the options hash that was given to +to_xml+:
|
131
|
+
#
|
132
|
+
# proc = Proc.new { |options| options[:builder].tag!('abc', 'def') }
|
133
|
+
# firm.to_xml :procs => [ proc ]
|
134
|
+
#
|
135
|
+
# <firm>
|
136
|
+
# # ... normal attributes as shown above ...
|
137
|
+
# <abc>def</abc>
|
138
|
+
# </firm>
|
139
|
+
#
|
140
|
+
# Alternatively, you can yield the builder object as part of the +to_xml+ call:
|
141
|
+
#
|
142
|
+
# firm.to_xml do |xml|
|
143
|
+
# xml.creator do
|
144
|
+
# xml.first_name "David"
|
145
|
+
# xml.last_name "Heinemeier Hansson"
|
146
|
+
# end
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# <firm>
|
150
|
+
# # ... normal attributes as shown above ...
|
151
|
+
# <creator>
|
152
|
+
# <first_name>David</first_name>
|
153
|
+
# <last_name>Heinemeier Hansson</last_name>
|
154
|
+
# </creator>
|
155
|
+
# </firm>
|
156
|
+
#
|
157
|
+
# As noted above, you may override +to_xml+ in your DatastaxRails::Base
|
158
|
+
# subclasses to have complete control about what's generated. The general
|
159
|
+
# form of doing this is:
|
160
|
+
#
|
161
|
+
# class IHaveMyOwnXML < DatastaxRails::Base
|
162
|
+
# def to_xml(options = {})
|
163
|
+
# options[:indent] ||= 2
|
164
|
+
# xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
165
|
+
# xml.instruct! unless options[:skip_instruct]
|
166
|
+
# xml.level_one do
|
167
|
+
# xml.tag!(:second_level, 'content')
|
168
|
+
# end
|
169
|
+
# end
|
170
|
+
# end
|
5
171
|
module Serialization
|
6
172
|
include ActiveModel::Serializers::Xml
|
7
173
|
|
8
|
-
#
|
9
|
-
# available through +options+. However more complicated cases should
|
10
|
-
# override DatastaxRails::Base#to_xml.
|
11
|
-
#
|
12
|
-
# By default the generated XML document will include the processing
|
13
|
-
# instruction and all the object's attributes. For example:
|
14
|
-
#
|
15
|
-
# <?xml version="1.0" encoding="UTF-8"?>
|
16
|
-
# <topic>
|
17
|
-
# <title>The First Topic</title>
|
18
|
-
# <author-name>David</author-name>
|
19
|
-
# <id type="integer">1</id>
|
20
|
-
# <approved type="boolean">false</approved>
|
21
|
-
# <replies-count type="integer">0</replies-count>
|
22
|
-
# <bonus-time type="datetime">2000-01-01T08:28:00+12:00</bonus-time>
|
23
|
-
# <written-on type="datetime">2003-07-16T09:28:00+1200</written-on>
|
24
|
-
# <content>Have a nice day</content>
|
25
|
-
# <author-email-address>david@loudthinking.com</author-email-address>
|
26
|
-
# <parent-id></parent-id>
|
27
|
-
# <last-read type="date">2004-04-15</last-read>
|
28
|
-
# </topic>
|
29
|
-
#
|
30
|
-
# This behavior can be controlled with <tt>:only</tt>, <tt>:except</tt>,
|
31
|
-
# <tt>:skip_instruct</tt>, <tt>:skip_types</tt>, <tt>:dasherize</tt> and <tt>:camelize</tt> .
|
32
|
-
# The <tt>:only</tt> and <tt>:except</tt> options are the same as for the
|
33
|
-
# +attributes+ method. The default is to dasherize all column names, but you
|
34
|
-
# can disable this setting <tt>:dasherize</tt> to +false+. Setting <tt>:camelize</tt>
|
35
|
-
# to +true+ will camelize all column names - this also overrides <tt>:dasherize</tt>.
|
36
|
-
# To not have the column type included in the XML output set <tt>:skip_types</tt> to +true+.
|
37
|
-
#
|
38
|
-
# For instance:
|
39
|
-
#
|
40
|
-
# topic.to_xml(:skip_instruct => true, :except => [ :id, :bonus_time, :written_on, :replies_count ])
|
41
|
-
#
|
42
|
-
# <topic>
|
43
|
-
# <title>The First Topic</title>
|
44
|
-
# <author-name>David</author-name>
|
45
|
-
# <approved type="boolean">false</approved>
|
46
|
-
# <content>Have a nice day</content>
|
47
|
-
# <author-email-address>david@loudthinking.com</author-email-address>
|
48
|
-
# <parent-id></parent-id>
|
49
|
-
# <last-read type="date">2004-04-15</last-read>
|
50
|
-
# </topic>
|
51
|
-
#
|
52
|
-
# To include first level associations use <tt>:include</tt>:
|
53
|
-
#
|
54
|
-
# firm.to_xml :include => [ :account, :clients ]
|
55
|
-
#
|
56
|
-
# <?xml version="1.0" encoding="UTF-8"?>
|
57
|
-
# <firm>
|
58
|
-
# <id type="integer">1</id>
|
59
|
-
# <rating type="integer">1</rating>
|
60
|
-
# <name>37signals</name>
|
61
|
-
# <clients type="array">
|
62
|
-
# <client>
|
63
|
-
# <rating type="integer">1</rating>
|
64
|
-
# <name>Summit</name>
|
65
|
-
# </client>
|
66
|
-
# <client>
|
67
|
-
# <rating type="integer">1</rating>
|
68
|
-
# <name>Microsoft</name>
|
69
|
-
# </client>
|
70
|
-
# </clients>
|
71
|
-
# <account>
|
72
|
-
# <id type="integer">1</id>
|
73
|
-
# <credit-limit type="integer">50</credit-limit>
|
74
|
-
# </account>
|
75
|
-
# </firm>
|
76
|
-
#
|
77
|
-
# Additionally, the record being serialized will be passed to a Proc's second
|
78
|
-
# parameter. This allows for ad hoc additions to the resultant document that
|
79
|
-
# incorporate the context of the record being serialized. And by leveraging the
|
80
|
-
# closure created by a Proc, to_xml can be used to add elements that normally fall
|
81
|
-
# outside of the scope of the model -- for example, generating and appending URLs
|
82
|
-
# associated with models.
|
83
|
-
#
|
84
|
-
# proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) }
|
85
|
-
# firm.to_xml :procs => [ proc ]
|
86
|
-
#
|
87
|
-
# <firm>
|
88
|
-
# # ... normal attributes as shown above ...
|
89
|
-
# <name-reverse>slangis73</name-reverse>
|
90
|
-
# </firm>
|
91
|
-
#
|
92
|
-
# To include deeper levels of associations pass a hash like this:
|
93
|
-
#
|
94
|
-
# firm.to_xml :include => {:account => {}, :clients => {:include => :address}}
|
95
|
-
# <?xml version="1.0" encoding="UTF-8"?>
|
96
|
-
# <firm>
|
97
|
-
# <id type="integer">1</id>
|
98
|
-
# <rating type="integer">1</rating>
|
99
|
-
# <name>37signals</name>
|
100
|
-
# <clients type="array">
|
101
|
-
# <client>
|
102
|
-
# <rating type="integer">1</rating>
|
103
|
-
# <name>Summit</name>
|
104
|
-
# <address>
|
105
|
-
# ...
|
106
|
-
# </address>
|
107
|
-
# </client>
|
108
|
-
# <client>
|
109
|
-
# <rating type="integer">1</rating>
|
110
|
-
# <name>Microsoft</name>
|
111
|
-
# <address>
|
112
|
-
# ...
|
113
|
-
# </address>
|
114
|
-
# </client>
|
115
|
-
# </clients>
|
116
|
-
# <account>
|
117
|
-
# <id type="integer">1</id>
|
118
|
-
# <credit-limit type="integer">50</credit-limit>
|
119
|
-
# </account>
|
120
|
-
# </firm>
|
121
|
-
#
|
122
|
-
# To include any methods on the model being called use <tt>:methods</tt>:
|
123
|
-
#
|
124
|
-
# firm.to_xml :methods => [ :calculated_earnings, :real_earnings ]
|
125
|
-
#
|
126
|
-
# <firm>
|
127
|
-
# # ... normal attributes as shown above ...
|
128
|
-
# <calculated-earnings>100000000000000000</calculated-earnings>
|
129
|
-
# <real-earnings>5</real-earnings>
|
130
|
-
# </firm>
|
131
|
-
#
|
132
|
-
# To call any additional Procs use <tt>:procs</tt>. The Procs are passed a
|
133
|
-
# modified version of the options hash that was given to +to_xml+:
|
134
|
-
#
|
135
|
-
# proc = Proc.new { |options| options[:builder].tag!('abc', 'def') }
|
136
|
-
# firm.to_xml :procs => [ proc ]
|
137
|
-
#
|
138
|
-
# <firm>
|
139
|
-
# # ... normal attributes as shown above ...
|
140
|
-
# <abc>def</abc>
|
141
|
-
# </firm>
|
142
|
-
#
|
143
|
-
# Alternatively, you can yield the builder object as part of the +to_xml+ call:
|
144
|
-
#
|
145
|
-
# firm.to_xml do |xml|
|
146
|
-
# xml.creator do
|
147
|
-
# xml.first_name "David"
|
148
|
-
# xml.last_name "Heinemeier Hansson"
|
149
|
-
# end
|
150
|
-
# end
|
151
|
-
#
|
152
|
-
# <firm>
|
153
|
-
# # ... normal attributes as shown above ...
|
154
|
-
# <creator>
|
155
|
-
# <first_name>David</first_name>
|
156
|
-
# <last_name>Heinemeier Hansson</last_name>
|
157
|
-
# </creator>
|
158
|
-
# </firm>
|
159
|
-
#
|
160
|
-
# As noted above, you may override +to_xml+ in your DatastaxRails::Base
|
161
|
-
# subclasses to have complete control about what's generated. The general
|
162
|
-
# form of doing this is:
|
163
|
-
#
|
164
|
-
# class IHaveMyOwnXML < DatastaxRails::Base
|
165
|
-
# def to_xml(options = {})
|
166
|
-
# options[:indent] ||= 2
|
167
|
-
# xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
168
|
-
# xml.instruct! unless options[:skip_instruct]
|
169
|
-
# xml.level_one do
|
170
|
-
# xml.tag!(:second_level, 'content')
|
171
|
-
# end
|
172
|
-
# end
|
173
|
-
# end
|
174
|
+
# See the module level documentation for an example of +to_xml+.
|
174
175
|
def to_xml(options = {}, &block)
|
175
176
|
options[:methods] ||= []
|
176
177
|
options[:methods] << :id
|
@@ -179,7 +180,8 @@ module DatastaxRails
|
|
179
180
|
end
|
180
181
|
end
|
181
182
|
|
182
|
-
|
183
|
+
# Implementation of ActiveModel's XML Serializer
|
184
|
+
class XmlSerializer < ActiveModel::Serializers::Xml::Serializer
|
183
185
|
def initialize(*args)
|
184
186
|
super
|
185
187
|
end
|
@@ -196,14 +198,14 @@ module DatastaxRails
|
|
196
198
|
options[:procs] = procs
|
197
199
|
end
|
198
200
|
|
199
|
-
# TODO This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well.
|
201
|
+
# TODO: This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well.
|
200
202
|
def add_associations(association, records, opts)
|
201
203
|
association_name = association.to_s.singularize
|
202
|
-
merged_options = options.merge(opts).merge!(:
|
204
|
+
merged_options = options.merge(opts).merge!(root: association_name, skip_instruct: true)
|
203
205
|
|
204
206
|
if records.is_a?(Enumerable)
|
205
207
|
tag = ActiveSupport::XmlMini.rename_key(association.to_s, options)
|
206
|
-
type = options[:skip_types] ? {
|
208
|
+
type = options[:skip_types] ? {} : { type: 'array' }
|
207
209
|
|
208
210
|
if records.empty?
|
209
211
|
@builder.tag!(tag, type)
|
@@ -214,19 +216,20 @@ module DatastaxRails
|
|
214
216
|
record_type = {}
|
215
217
|
else
|
216
218
|
record_class = (record.class.to_s.underscore == association_name) ? nil : record.class.name
|
217
|
-
record_type = {:
|
219
|
+
record_type = { type: record_class }
|
218
220
|
end
|
219
221
|
|
220
222
|
record.to_xml merged_options.merge(record_type)
|
221
223
|
end
|
222
224
|
end
|
223
225
|
end
|
224
|
-
elsif record = @serializable.send(association)
|
226
|
+
elsif (record = @serializable.send(association))
|
225
227
|
record.to_xml(merged_options)
|
226
228
|
end
|
227
229
|
end
|
228
230
|
|
229
|
-
|
231
|
+
# Implementation of ActiveModel's XML Serializer Attribute
|
232
|
+
class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute
|
230
233
|
def compute_type
|
231
234
|
klass = @serializable.class
|
232
235
|
type = if klass.serialized_attributes.key?(name.to_sym)
|
@@ -237,8 +240,8 @@ module DatastaxRails
|
|
237
240
|
NilClass
|
238
241
|
end
|
239
242
|
|
240
|
-
{ :
|
241
|
-
:
|
243
|
+
{ text: :string,
|
244
|
+
time: :datetime }[type] || type
|
242
245
|
end
|
243
246
|
protected :compute_type
|
244
247
|
end
|