active_force 0.3.2 → 0.4.2

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: 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