sunstone 2.0.4 → 5.0.0.beta3

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: 9d7b7cb926a0045ee4a771a87ce5f3f3096fb035
4
- data.tar.gz: 0edf0869c5ac58e901579d47b8979ed4ecf98c39
3
+ metadata.gz: c5c130a7d5b7307e472bd22688ee0b8621db478e
4
+ data.tar.gz: a3fde9dce1b08795ea7ff9a1217921fb57c099ef
5
5
  SHA512:
6
- metadata.gz: 2bf1d1921cf1cad5967be3398b0a49de76cac94b65bc268952c549b994b1e48487913b062a29e33f4968c84fecb90aec0691f24cce06261c61f0a7cf2bce5ddb
7
- data.tar.gz: 8bce1e614955c036c7d46df1c109b2650dec40ad5d0b3168d9c33963005c94f91a80a6737d1b00b045ffafea006efc43faaef28f66053f811975e0efa33e2f46
6
+ metadata.gz: 383524737f0c0fefbec2c99d62d35ce23c6e3060f772e11ebac65418493cf2ee892e34cd637a6f86bbf5439275103c986887f4dd05494cb223a8cc51a9b67349
7
+ data.tar.gz: df9fe4e2e39011303804a12fe26b49b99c84c3651c017a202fbcec907b8439708f4ae04ca72400c47cc5031687de9c179495e23a5644a71ec6666ff69bcd1590
@@ -0,0 +1,46 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ class CollectionAssociation
4
+
5
+ def replace(other_array)
6
+ other_array.each { |val| raise_on_type_mismatch!(val) }
7
+ original_target = load_target.dup
8
+
9
+ if owner.instance_variable_get(:@updateing)
10
+ replace_common_records_in_memory(other_array, original_target)
11
+ concat(other_array - original_target)
12
+ other_array
13
+ elsif owner.new_record?
14
+ replace_records(other_array, original_target)
15
+ else
16
+ replace_common_records_in_memory(other_array, original_target)
17
+ if other_array != original_target
18
+ transaction { replace_records(other_array, original_target) }
19
+ else
20
+ other_array
21
+ end
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+
29
+ module ActiveRecord
30
+ module Persistence
31
+ # Updates the attributes of the model from the passed-in hash and saves the
32
+ # record, all wrapped in a transaction. If the object is invalid, the saving
33
+ # will fail and false will be returned.
34
+ def update(attributes)
35
+ @updateing = true
36
+ # The following transaction covers any possible database side-effects of the
37
+ # attributes assignment. For example, setting the IDs of a child collection.
38
+ with_transaction_returning_status do
39
+ assign_attributes(attributes)
40
+ save
41
+ end
42
+ ensure
43
+ @updateing = false
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,137 @@
1
+ module ActiveRecord
2
+ module AttributeMethods
3
+
4
+ protected
5
+
6
+ # Returns a Hash of the Arel::Attributes and attribute values that have been
7
+ # typecasted for use in an Arel insert/update method.
8
+ def arel_attributes_with_values(attribute_names)
9
+ attrs = {}
10
+ arel_table = self.class.arel_table
11
+
12
+ attribute_names.each do |name|
13
+ attrs[arel_table[name]] = typecasted_attribute_value(name)
14
+ end
15
+
16
+ if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
17
+ self.class.reflect_on_all_associations.each do |reflection|
18
+ if reflection.belongs_to?
19
+ add_attributes_for_belongs_to_association(reflection, attrs)
20
+ elsif reflection.has_one?
21
+ add_attributes_for_has_one_association(reflection, attrs)
22
+ elsif reflection.collection?
23
+ add_attributes_for_collection_association(reflection, attrs)
24
+ end
25
+ end
26
+ end
27
+
28
+ attrs
29
+ end
30
+
31
+ def add_attributes_for_belongs_to_association(reflection, attrs)
32
+ key = :"add_attributes_for_belongs_to_association#{reflection.name}"
33
+ @_already_called ||= {}
34
+ return if @_already_called[key]
35
+ @_already_called[key]=true
36
+ @_already_called[:"autosave_associated_records_for_#{reflection.name}"] = true
37
+
38
+ association = association_instance_get(reflection.name)
39
+ record = association && association.load_target
40
+ if record && !record.destroyed?
41
+ autosave = reflection.options[:autosave]
42
+
43
+ if autosave && record.marked_for_destruction?
44
+ self[reflection.foreign_key] = nil
45
+ record.destroy
46
+ elsif autosave != false
47
+ if record.new_record? || (autosave && record.changed_for_autosave?)
48
+ if record.new_record?
49
+ record.send(:arel_attributes_with_values_for_create, record.attribute_names).each do |k, v|
50
+ attrs[Arel::Attributes::Relation.new(k, reflection.name)] = v
51
+ end
52
+ else
53
+ record.send(:arel_attributes_with_values_for_update, record.attribute_names).each do |k, v|
54
+ attrs[Arel::Attributes::Relation.new(k, reflection.name)] = v
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ def add_attributes_for_has_one_association(reflection, attrs)
63
+ key = :"add_attributes_for_has_one_association#{reflection.name}"
64
+ @_already_called ||= {}
65
+ return if @_already_called[key]
66
+ @_already_called[key]=true
67
+ @_already_called[:"autosave_associated_records_for_#{reflection.name}"] = true
68
+
69
+ association = association_instance_get(reflection.name)
70
+ record = association && association.load_target
71
+
72
+ if record && !record.destroyed?
73
+ autosave = reflection.options[:autosave]
74
+
75
+ if autosave && record.marked_for_destruction?
76
+ record.destroy
77
+ elsif autosave != false
78
+ key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id
79
+
80
+ if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
81
+ unless reflection.through_reflection
82
+ record[reflection.foreign_key] = key
83
+ end
84
+
85
+ if record.new_record?
86
+ record.send(:arel_attributes_with_values_for_create, record.attribute_names).each do |k, v|
87
+ attrs[Arel::Attributes::Relation.new(k, reflection.name)] = v
88
+ end
89
+ else
90
+ record.send(:arel_attributes_with_values_for_update, record.attribute_names).each do |k, v|
91
+ attrs[Arel::Attributes::Relation.new(k, reflection.name)] = v
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ def add_attributes_for_collection_association(reflection, attrs)
100
+ key = :"add_attributes_for_collection_association#{reflection.name}"
101
+ @_already_called ||= {}
102
+ return if @_already_called[key]
103
+ @_already_called[key]=true
104
+ @_already_called[:"autosave_associated_records_for_#{reflection.name}"] = true
105
+ if reflection.is_a?(ActiveRecord::Reflection::HasAndBelongsToManyReflection)
106
+ @_already_called[:"autosave_associated_records_for_#{self.class.name.downcase.pluralize}_#{reflection.name}"] = true
107
+ end
108
+
109
+ if association = association_instance_get(reflection.name)
110
+ autosave = reflection.options[:autosave]
111
+ if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave)
112
+
113
+ records.each_with_index do |record, idx|
114
+ next if record.destroyed?
115
+
116
+ if record.new_record?
117
+ record.send(:arel_attributes_with_values_for_create, record.attribute_names).each do |k, v|
118
+ attrs[Arel::Attributes::Relation.new(k, reflection.name, idx)] = v
119
+ end
120
+ else
121
+ record.send(:arel_attributes_with_values_for_update, record.attribute_names).each do |k, v|
122
+ attrs[Arel::Attributes::Relation.new(k, reflection.name, idx)] = v
123
+ end
124
+ end
125
+
126
+ end
127
+ end
128
+
129
+ # reconstruct the scope now that we know the owner's id
130
+ association.reset_scope if association.respond_to?(:reset_scope)
131
+ end
132
+ end
133
+
134
+
135
+
136
+ end
137
+ end
@@ -9,7 +9,11 @@ module ActiveRecord
9
9
  # column_name.to_s
10
10
  # end
11
11
  # end
12
-
12
+
13
+ if loaded? && (column_names - @klass.column_names).empty?
14
+ return @records.pluck(*column_names)
15
+ end
16
+
13
17
  if has_include?(column_names.first)
14
18
  construct_relation_for_association_calculations.pluck(*column_names)
15
19
  else
@@ -20,13 +20,12 @@ module ActiveRecord
20
20
  []
21
21
  else
22
22
  arel = relation.arel
23
- rows = connection.select_all(arel, 'SQL', arel.bind_values + relation.bind_values)
23
+ rows = connection.select_all(arel, 'SQL', arel.bind_values + relation.bound_attributes)
24
24
  if join_dependency
25
25
  join_dependency.instantiate(rows, aliases)
26
26
  else
27
27
  instantiate_with_associations(rows, relation)
28
28
  end
29
-
30
29
  end
31
30
  end
32
31
  end
@@ -58,7 +57,7 @@ module ActiveRecord
58
57
  other = parent.association(reflection.name)
59
58
  other.loaded!
60
59
  else
61
- if parent.association_cache.key?(reflection.name)
60
+ if parent.association_cached?(reflection.name)
62
61
  model = parent.association(reflection.name).target
63
62
  construct(model, attributes.select{|k,v| !reflection.klass.column_names.include?(k.to_s) }, seen, model_cache)
64
63
  end
@@ -0,0 +1,21 @@
1
+ module ActiveRecord
2
+ # = Active Record \Persistence
3
+ module Persistence
4
+ private
5
+
6
+ def create_or_update(*args)
7
+ raise ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly?
8
+ result = new_record? ? _create_record : _update_record(*args)
9
+ result != false
10
+ rescue Sunstone::Exception::BadRequest => e
11
+ JSON.parse(e.message)['errors'].each do |field, message|
12
+ if message.is_a?(Array)
13
+ message.each { |m| errors.add(field, m) }
14
+ else
15
+ errors.add(field, message)
16
+ end
17
+ end
18
+ raise ActiveRecord::RecordInvalid
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,6 @@
1
1
  module ActiveRecord
2
2
  module QueryMethods
3
-
3
+
4
4
  def reverse_sql_order(order_query)
5
5
  order_query = [arel_table[primary_key].asc] if order_query.empty?
6
6
 
@@ -18,6 +18,13 @@ module ActiveRecord
18
18
  end
19
19
  end
20
20
  end
21
-
21
+
22
+ def joins(*args)
23
+ # If a joins happen with sunstone messes up visitor / collector
24
+ return self if klass.connection.class.name == "ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter"
25
+ check_if_method_has_arguments!(:joins, args)
26
+ spawn.joins!(*args)
27
+ end
28
+
22
29
  end
23
30
  end
@@ -12,13 +12,13 @@ module ActiveRecord
12
12
  end
13
13
 
14
14
  arel = relation.arel
15
- binds = (arel.bind_values + relation.bind_values).dup
16
- binds.map! { |bv| connection.quote(*bv.reverse) }
15
+ binds = connection.prepare_binds_for_database(arel.bind_values + relation.bound_attributes)
16
+ binds.map! { |bv| connection.quote(bv) }
17
17
  collect = visitor.accept(arel.ast, Arel::Collectors::Bind.new)
18
18
  collect.substitute_binds(binds).join
19
19
  end
20
20
  end
21
21
 
22
-
22
+
23
23
  end
24
24
  end
@@ -16,7 +16,7 @@ module ActiveRecord
16
16
  end
17
17
 
18
18
  def sql_for(binds, connection)
19
- binds = binds.dup
19
+ binds = connection.prepare_binds_for_database(binds)
20
20
 
21
21
  if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
22
22
  @values.compile(binds)
@@ -1,7 +1,20 @@
1
1
  class NilClass
2
2
 
3
3
  def to_query(namespace)
4
- namespace
4
+ namespace.to_s
5
5
  end
6
6
 
7
+ end
8
+
9
+ class Hash
10
+
11
+ def to_query(namespace = nil)
12
+ collect do |key, value|
13
+ # unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
14
+ value.to_query(namespace ? "#{namespace}[#{key}]" : key)
15
+ # end
16
+ end.compact.sort! * '&'
17
+ end
18
+
19
+ alias_method :to_param, :to_query
7
20
  end
@@ -0,0 +1,30 @@
1
+ module Arel
2
+ module Attributes
3
+ class Relation < Attribute
4
+
5
+ attr_accessor :collection
6
+
7
+ def initialize(relation, name, collection = false)
8
+ self[:relation] = relation
9
+ self[:name] = name
10
+ @collection = collection
11
+ end
12
+
13
+ def able_to_type_cast?
14
+ false
15
+ end
16
+
17
+ def table_name
18
+ nil
19
+ end
20
+
21
+ def eql? other
22
+ self.class == other.class &&
23
+ self.relation == other.relation &&
24
+ self.name == other.name &&
25
+ self.collection == other.collection
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -2,16 +2,18 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  # Sunstone-specific extensions to column definitions in a table.
4
4
  class SunstoneColumn < Column #:nodoc:
5
- attr_accessor :array
6
-
7
- def initialize(name, cast_type, options={})
5
+ delegate :array, to: :sql_type_metadata
6
+ alias :array? :array
7
+
8
+ def initialize(name, sql_type_metadata, options={})
9
+ @name = name.freeze
10
+ @sql_type_metadata = sql_type_metadata
11
+ @null = options['null']
12
+ @default = options['default']
13
+ @default_function = nil
14
+ @collation = nil
15
+ @table_name = nil
8
16
  @primary_key = (options['primary_key'] == true)
9
- @array = !!options['array']
10
- if @array
11
- super(name, options['default'], Sunstone::Type::Array.new(cast_type), nil, options['null'])
12
- else
13
- super(name, options['default'], cast_type, nil, options['null'])
14
- end
15
17
  end
16
18
 
17
19
  def primary_key?
@@ -13,12 +13,7 @@ module ActiveRecord
13
13
  end
14
14
  end
15
15
 
16
- # Returns an ActiveRecord::Result instance.
17
- def select_all(arel, name = nil, binds = [], &block)
18
- exec_query(arel, name, binds)
19
- end
20
-
21
- def exec_query(arel, name = 'SAR', binds = [])
16
+ def exec_query(arel, name = 'SAR', binds = [], prepare: false)
22
17
  sar = to_sar(arel, binds)
23
18
  result = exec(sar, name)
24
19
 
@@ -15,7 +15,7 @@ module ActiveRecord
15
15
  def columns(table_name)
16
16
  # Limit, precision, and scale are all handled by the superclass.
17
17
  column_definitions(table_name).map do |column_name, options|
18
- new_column(column_name, lookup_cast_type(options['type']), options)
18
+ new_column(column_name, options)
19
19
  end
20
20
  end
21
21
 
@@ -34,8 +34,25 @@ module ActiveRecord
34
34
  Wankel.parse(@connection.get('/tables').body)
35
35
  end
36
36
 
37
- def new_column(name, cast_type, options={}) # :nodoc:
38
- SunstoneColumn.new(name, cast_type, options)
37
+ def views
38
+ []
39
+ end
40
+
41
+ def new_column(name, options)
42
+ sql_type_metadata = fetch_type_metadata(options)
43
+ SunstoneColumn.new(name, sql_type_metadata, options)
44
+ end
45
+
46
+ def fetch_type_metadata(options)
47
+ cast_type = lookup_cast_type(options['type'])
48
+ simple_type = SqlTypeMetadata.new(
49
+ sql_type: options['type'],
50
+ type: cast_type.type,
51
+ limit: cast_type.limit,
52
+ precision: cast_type.precision,
53
+ scale: cast_type.scale,
54
+ )
55
+ SunstoneSQLTypeMetadata.new(simple_type, options)
39
56
  end
40
57
 
41
58
  def column_name_for_operation(operation, node) # :nodoc:
@@ -46,7 +63,7 @@ module ActiveRecord
46
63
 
47
64
  # Returns just a table's primary key
48
65
  def primary_key(table)
49
- columns(table).find{ |c| c.primary_key? }.name
66
+ columns(table).find{ |c| c.primary_key? }.try(:name)
50
67
  end
51
68
 
52
69
  end