active_force 0.3.2 → 0.4.2

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: cb33c1d8bd10a5fe69b7afba5930afdce4fdbb6e
4
- data.tar.gz: 57968d2bb5ba4bcc75e266952167c99fa26735da
3
+ metadata.gz: 2db05b88b32eacda2b94f3dcbc47a72288b1f4e4
4
+ data.tar.gz: 4c57fa4fa03fcb50d8378854b99377d6403206e2
5
5
  SHA512:
6
- metadata.gz: 175aea8d469a6515b942e09a151f683eeeaa9cd9e4dab41858398d8d8f9f07dcde337808cdb3e7d73330494eb6ac71877fe7346717c95f511babd65c942d8c55
7
- data.tar.gz: 3abb42f544529ac5d460f157cb8ae00f5706f57e01004d34d22e41f64ddfd7f8888deb0b6421b7498c609ead4a0b0d7c3241e610e65cf4d81a6bd3d3d2414661
6
+ metadata.gz: 7629ee051094c5e4dbe73ee6c3c06fb31bbb1fa9cf5aea5705f661d5201dffa8eb9cc6d5fcc263e7ea90084f4bf30731749d206f2a8996a9c356cd876e4415ba
7
+ data.tar.gz: 21db5698eb4a8f6db16041cc70cd32a8d24520dc1655c7c6eb6bb3d2d1fa7d3b5e44c99e5ffbe93860c9bff2a19872edd5ceff8a20cdb8ee9d1512d103133223
data/.travis.yml CHANGED
@@ -2,7 +2,6 @@ language: ruby
2
2
  rvm:
3
3
  - 2.0.0
4
4
  - 2.1.1
5
- - rbx-2
6
5
  matrix:
7
6
  allow_failures:
8
7
  - rvm: rbx-2
data/README.md CHANGED
@@ -23,7 +23,7 @@ And then execute:
23
23
  Or install it yourself as:
24
24
 
25
25
  $ gem install active_force
26
-
26
+
27
27
  Rails:
28
28
 
29
29
  ```ruby
@@ -38,22 +38,33 @@ Restforce.log = true if Rails.env.development?
38
38
 
39
39
  ```ruby
40
40
  class Page < ActiveForce::SObject
41
-
41
+
42
42
  end
43
43
  ```
44
44
 
45
45
  ### Add Attributes
46
46
  ```ruby
47
47
  class Page < ActiveForce::SObject
48
- #field, attribute name. from: 'Name in Salesforce database'
48
+ #field, :attribute_name, from: 'Name_In_Salesforce_Database'
49
49
  field :id, from: 'Id'
50
- field :name, from: 'Medication__c'
50
+ field :name, from: 'Medication__c'
51
51
  self.fields = mappings.values
52
52
  #set SalesForce table name.
53
53
  self.table_name = 'Patient_Medication__c'
54
54
  end
55
55
  ```
56
- ### Relation ships
56
+ ### Validations
57
+ You can use any validation that active record has (except for validates_associated), just by adding them to your class:
58
+
59
+ ```ruby
60
+ validates :name, :login, :email, presence: true
61
+ validates :text, length: { minimum: 2 }
62
+ validates :text, format: { with: /\A[a-zA-Z]+\z/, message: "only allows letters" }
63
+ validates :size, inclusion: { in: %w(small medium large),
64
+ message: "%{value} is not a valid size" }
65
+ ```
66
+
67
+ ### Relationships
57
68
 
58
69
  #### Has Many
59
70
 
@@ -73,7 +84,7 @@ you could send a option parameter in the declaration.
73
84
  class Account < ActiveForce::SObject
74
85
  has_many :medications,
75
86
  where: "(Date_Discontinued__c > #{ Date.today.strftime("%Y-%m-%d") } or Date_Discontinued__c = NULL)"
76
-
87
+
77
88
  has_many :today_log_entrys,
78
89
  model: DailyLogEntry,
79
90
  where: "Date__c = #{ Time.now.in_time_zone.strftime("%Y-%m-%d") }"
data/active_force.gemspec CHANGED
@@ -6,7 +6,7 @@ require 'active_force/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "active_force"
8
8
  spec.version = ActiveForce::VERSION
9
- spec.authors = ["Eloy Espinaco", "Pablo Oldani"]
9
+ spec.authors = ["Eloy Espinaco", "Pablo Oldani", "Armando Andini", "José Piccioni"]
10
10
  spec.email = "eloyesp@gmail.com"
11
11
  spec.description = %q{Use SalesForce as an ActiveModel}
12
12
  spec.summary = %q{Help you implement models persisting on Sales Force within Rails using RESTForce}
@@ -0,0 +1,62 @@
1
+ require 'active_force/query'
2
+
3
+ module ActiveForce
4
+ class ActiveQuery < Query
5
+
6
+ attr_reader :sobject
7
+
8
+ delegate :sfdc_client, :build, :table_name, :mappings, to: :sobject
9
+
10
+ def initialize sobject
11
+ @sobject = sobject
12
+ super table_name
13
+ fields sobject.fields
14
+ end
15
+
16
+ def to_a
17
+ result.to_a.map do |mash|
18
+ build mash
19
+ end
20
+ end
21
+
22
+ def count
23
+ super
24
+ sfdc_client.query(to_s).first.expr0
25
+ end
26
+
27
+ def all
28
+ to_a
29
+ end
30
+
31
+ def limit limit
32
+ super
33
+ limit == 1 ? to_a.first : self
34
+ end
35
+
36
+ def where conditions
37
+ return super unless conditions.is_a? Hash
38
+ conditions.each do |key, value|
39
+ super "#{ mappings[key] } = #{ enclose_value value }"
40
+ end
41
+ self
42
+ end
43
+
44
+ def find_by conditions
45
+ where(conditions).limit 1
46
+ end
47
+
48
+ private
49
+
50
+ def enclose_value value
51
+ if value.is_a? String
52
+ "'#{value}'"
53
+ else
54
+ value.to_s
55
+ end
56
+ end
57
+
58
+ def result
59
+ sfdc_client.query(self.to_s)
60
+ end
61
+ end
62
+ end
@@ -8,30 +8,14 @@ module ActiveForce
8
8
 
9
9
  private
10
10
 
11
- def build
12
- super
13
- define_query_method
14
- end
15
-
16
- def define_query_method
11
+ def define_relation_method
17
12
  association = self
18
- @parent.send :define_method, query_method_name do
13
+ @parent.send :define_method, @relation_name do
19
14
  query = association.relation_model.query
20
15
  query.options association.options
21
16
  query.where "#{ association.foreign_key } = '#{ self.id }'"
22
17
  end
23
18
  end
24
-
25
- def define_relation_method
26
- association = self
27
- @parent.send :define_method, @relation_name do
28
- association.relation_model.send_query send(association.query_method_name)
29
- end
30
- end
31
-
32
- def query_method_name
33
- "#{ @relation_name }_query"
34
- end
35
19
  end
36
20
  end
37
21
  end
@@ -10,7 +10,7 @@ module ActiveForce
10
10
  end
11
11
 
12
12
  def fields fields_collection = []
13
- @query_fields = @query_fields + fields_collection.to_a
13
+ @query_fields += fields_collection.to_a
14
14
  end
15
15
 
16
16
  def all
@@ -20,7 +20,7 @@ module ActiveForce
20
20
  def to_s
21
21
  <<-SOQL.gsub(/\s+/, " ").strip
22
22
  SELECT
23
- #{ @query_fields.uniq.join(', ') }
23
+ #{ build_select }
24
24
  FROM
25
25
  #{ @table }
26
26
  #{ build_where }
@@ -88,6 +88,10 @@ module ActiveForce
88
88
  end
89
89
 
90
90
  protected
91
+ def build_select
92
+ @query_fields.uniq.join(', ')
93
+ end
94
+
91
95
  def build_where
92
96
  "WHERE #{ @conditions.join(' AND ') }" unless @conditions.empty?
93
97
  end
@@ -1,9 +1,8 @@
1
1
  require 'active_model'
2
2
  require 'active_attr'
3
3
  require 'active_attr/dirty'
4
- require 'active_force/query'
4
+ require 'active_force/active_query'
5
5
  require 'active_force/association'
6
- require 'active_force/finders'
7
6
  require 'yaml'
8
7
 
9
8
  module ActiveForce
@@ -11,62 +10,33 @@ module ActiveForce
11
10
  include ActiveAttr::Model
12
11
  include ActiveAttr::Dirty
13
12
  include ActiveForce::Association
14
- include ActiveForce::Finders
15
13
 
16
14
  STANDARD_TYPES = %w[ Account Contact Opportunity Campaign]
17
15
 
18
16
  class_attribute :mappings, :fields, :table_name
19
17
 
18
+ class << self
19
+ delegate :where, :first, :last, :all, :find, :find_by, :count, :to => :query
20
+ end
21
+
20
22
  # The table name to used to make queries.
21
23
  # It is derived from the class name adding the "__c" when needed.
22
24
  def self.table_name
23
- @table_name ||= if STANDARD_TYPES.include? self.name
24
- self.name
25
- else
26
- "#{self.name}__c"
27
- end
25
+ @table_name ||= custom_table_name || "#{ self.name }__c"
28
26
  end
29
27
 
30
- def self.build sobject
31
- return unless sobject
32
- model = new
28
+ def self.build sf_table_description
29
+ return unless sf_table_description
30
+ sobject = new
33
31
  mappings.each do |attr, sf_field|
34
- model[attr] = sobject[sf_field]
32
+ sobject[attr] = sf_table_description[sf_field]
35
33
  end
36
- model.changed_attributes.clear
37
- model
34
+ sobject.changed_attributes.clear
35
+ sobject
38
36
  end
39
37
 
40
38
  def self.query
41
- query = ActiveForce::Query.new(table_name)
42
- query.fields fields
43
- query
44
- end
45
-
46
- def self.first
47
- send_query(query.first).first
48
- end
49
-
50
- def self.last
51
- send_query(query.last).first
52
- end
53
-
54
- def self.all
55
- send_query query
56
- end
57
-
58
- def self.count
59
- sfdc_client.query(query.count).first.expr0
60
- end
61
-
62
- def self.send_query query
63
- sfdc_client.query(query.to_s).to_a.map do |mash|
64
- build mash
65
- end
66
- end
67
-
68
- def self.find id
69
- send_query(query.find(id)).first
39
+ ActiveForce::ActiveQuery.new self
70
40
  end
71
41
 
72
42
  def update_attributes! attributes = {}
@@ -139,7 +109,13 @@ module ActiveForce
139
109
  @mappings ||= {}
140
110
  end
141
111
 
112
+
142
113
  private
114
+
115
+ def self.custom_table_name
116
+ self.name if STANDARD_TYPES.include? self.name
117
+ end
118
+
143
119
  def read_value field
144
120
  if self.class.attributes[field][:sf_type] == :multi_picklist
145
121
  attribute(field.to_s).reject(&:empty?).join(';')
@@ -1,3 +1,3 @@
1
1
  module ActiveForce
2
- VERSION = "0.3.2"
2
+ VERSION = "0.4.2"
3
3
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'active_force/active_query'
3
+
4
+ describe ActiveForce::ActiveQuery do
5
+ let(:sobject){
6
+ sobject = double("sobject")
7
+ sobject.stub(:table_name).and_return "table_name"
8
+ sobject.stub(:fields).and_return []
9
+ sobject
10
+ }
11
+
12
+ let(:client){
13
+ double("client")
14
+ }
15
+
16
+ before do
17
+ @active_query = ActiveForce::ActiveQuery.new(sobject)
18
+ @active_query.stub(:sfdc_client).and_return client
19
+ @active_query.stub(:build).and_return Object.new
20
+ end
21
+
22
+ describe "to_a" do
23
+ before do
24
+ expect(client).to receive(:query)
25
+ end
26
+
27
+ it "should return an array of objects" do
28
+ result = @active_query.where("Text_Label = 'foo'").to_a
29
+ expect(result).to be_a Array
30
+ end
31
+
32
+ it "should allow to chain query methods" do
33
+ result = @active_query.where("Text_Label = 'foo'").where("Checkbox_Label = true").to_a
34
+ expect(result).to be_a Array
35
+ end
36
+
37
+ end
38
+ end
@@ -44,44 +44,46 @@ describe ActiveForce::SObject do
44
44
  expect(post).to respond_to(:comments)
45
45
  end
46
46
 
47
- it "should return a Query object" do
48
- post.comments_query.class.should be ActiveForce::Query
47
+ it "should return a ActiveQuery object" do
48
+ expect(post.comments).to be_a ActiveForce::ActiveQuery
49
49
  end
50
50
 
51
51
  describe 'to_s' do
52
52
  it "should retrun a OSQL statment" do
53
- post.comments_query.to_s.should ==
53
+ post.comments.to_s.should ==
54
54
  "SELECT Id FROM Comment__c WHERE Post__c = '1'"
55
55
  end
56
56
  end
57
+
57
58
  end
58
59
 
59
60
  describe 'has_many(options)' do
60
61
 
61
62
  it 'should allow to send a different query table name' do
62
63
  Post.has_many :ugly_comments, { model: Comment }
63
- post.comments_query.to_s.should ==
64
+ post.comments.to_s.should ==
64
65
  "SELECT Id FROM Comment__c WHERE Post__c = '1'"
65
66
  end
66
67
 
67
68
  it 'should allow to change the foreign key' do
68
69
  Post.has_many :comments, { foreign_key: 'Post' }
69
- post.comments_query.to_s.should ==
70
+ post.comments.to_s.should ==
70
71
  "SELECT Id FROM Comment__c WHERE Post = '1'"
71
72
  end
72
73
 
73
74
  it 'should allow to add a where condition' do
74
75
  Post.has_many :comments, { where: '1 = 1' }
75
- post.comments_query.to_s.should ==
76
+ post.comments.to_s.should ==
76
77
  "SELECT Id FROM Comment__c WHERE 1 = 1 AND Post__c = '1'"
77
78
  end
78
79
 
79
80
  it 'should use a convention name for the foreign key' do
80
81
  Comment.field :post_id, from: 'PostId'
81
82
  Post.has_many :comments
82
- post.comments_query.to_s.should ==
83
+ post.comments.to_s.should ==
83
84
  "SELECT Id FROM Comment__c WHERE PostId = '1'"
84
85
  end
86
+
85
87
  end
86
88
 
87
89
  describe "belongs_to" do
File without changes
@@ -1,6 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ActiveForce::SObject do
4
+ let(:sobject_hash) { YAML.load(fixture('sobject/single_sobject_hash')) }
4
5
 
5
6
  before do
6
7
  ::Client = double('Client')
@@ -18,7 +19,6 @@ describe ActiveForce::SObject do
18
19
  end
19
20
 
20
21
  describe ".build" do
21
- let(:sobject_hash) { YAML.load(fixture('sobject/single_sobject_hash')) }
22
22
 
23
23
  it "build a valid sobject from a JSON" do
24
24
  expect(Whizbang.build sobject_hash).to be_an_instance_of Whizbang
@@ -72,19 +72,26 @@ describe ActiveForce::SObject do
72
72
  end
73
73
 
74
74
  it "sends the query to the client" do
75
- Client.should_receive(:query).and_return(count_response)
75
+ expect(Client).to receive(:query).and_return(count_response)
76
76
  expect(Whizbang.count).to eq(1)
77
77
  end
78
78
 
79
79
  end
80
80
 
81
+ # describe "first" do
82
+ # it "should return the first value" do
83
+ # binding.pry
84
+ # expect(Whizbang.first).to eq(1)
85
+ # end
86
+ # end
87
+
81
88
  describe "#find_by" do
82
89
  it "responds to find_by" do
83
90
  Whizbang.should respond_to(:find_by)
84
91
  end
85
92
 
86
93
  it "should query the client, with the SFDC field names and correctly enclosed values" do
87
- Client.should_receive(:query).with("SELECT Id FROM Whizbang__c WHERE Id = 123 AND Text_Label = 'foo'")
94
+ Client.should_receive(:query).with("SELECT Id FROM Whizbang__c WHERE Id = 123 AND Text_Label = 'foo' LIMIT 1")
88
95
  Whizbang.find_by id: 123, text: "foo"
89
96
  end
90
97
  end
metadata CHANGED
@@ -1,15 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_force
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eloy Espinaco
8
8
  - Pablo Oldani
9
+ - Armando Andini
10
+ - José Piccioni
9
11
  autorequire:
10
12
  bindir: bin
11
13
  cert_chain: []
12
- date: 2014-08-08 00:00:00.000000000 Z
14
+ date: 2014-08-15 00:00:00.000000000 Z
13
15
  dependencies:
14
16
  - !ruby/object:Gem::Dependency
15
17
  name: active_attr
@@ -112,22 +114,23 @@ files:
112
114
  - active_force.gemspec
113
115
  - lib/active_attr/dirty.rb
114
116
  - lib/active_force.rb
117
+ - lib/active_force/active_query.rb
115
118
  - lib/active_force/association.rb
116
119
  - lib/active_force/association/association.rb
117
120
  - lib/active_force/association/belongs_to_association.rb
118
121
  - lib/active_force/association/has_many_association.rb
119
- - lib/active_force/finders.rb
120
122
  - lib/active_force/query.rb
121
123
  - lib/active_force/sobject.rb
122
124
  - lib/active_force/version.rb
123
125
  - lib/generators/active_force/active_force_model/USAGE
124
126
  - lib/generators/active_force/active_force_model/active_force_model_generator.rb
125
127
  - lib/generators/active_force/active_force_model/templates/model.rb.erb
128
+ - spec/active_force/active_query_spec.rb
126
129
  - spec/active_force/association_spec.rb
130
+ - spec/active_force/query_spec.rb
127
131
  - spec/active_force/sobject/table_name_spec.rb
128
132
  - spec/active_force/sobject_spec.rb
129
133
  - spec/active_force_spec.rb
130
- - spec/active_query/query_spec.rb
131
134
  - spec/fixtures/sobject/single_sobject_hash.yml
132
135
  - spec/spec_helper.rb
133
136
  - spec/support/fixture_helpers.rb
@@ -157,11 +160,12 @@ signing_key:
157
160
  specification_version: 4
158
161
  summary: Help you implement models persisting on Sales Force within Rails using RESTForce
159
162
  test_files:
163
+ - spec/active_force/active_query_spec.rb
160
164
  - spec/active_force/association_spec.rb
165
+ - spec/active_force/query_spec.rb
161
166
  - spec/active_force/sobject/table_name_spec.rb
162
167
  - spec/active_force/sobject_spec.rb
163
168
  - spec/active_force_spec.rb
164
- - spec/active_query/query_spec.rb
165
169
  - spec/fixtures/sobject/single_sobject_hash.yml
166
170
  - spec/spec_helper.rb
167
171
  - spec/support/fixture_helpers.rb
@@ -1,37 +0,0 @@
1
- module ActiveForce
2
- module Finders
3
- module ClassMethods
4
- def find_by conditions
5
- query = self.query
6
- query_conditions(conditions).each do |query_condition|
7
- query = query.where query_condition
8
- end
9
- send_query(query).first
10
- end
11
-
12
- private
13
-
14
- #maps a hash key => value to a string 'key = value'
15
- def query_conditions conditions
16
- conditions.map do |key, value|
17
- "#{ mappings[key] } = #{ enclose_value value }"
18
- end
19
- end
20
-
21
- # encloses the value in quotes if it's a string
22
- def enclose_value value
23
- if value.is_a? String
24
- "'#{value}'"
25
- else
26
- value.to_s
27
- end
28
- end
29
-
30
- end
31
-
32
- def self.included mod
33
- mod.extend ClassMethods
34
- end
35
-
36
- end
37
- end