sunstone 2.0.4 → 5.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
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