Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/rails 7 and adding features #3

Merged
merged 11 commits into from
Feb 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

## Not released

## 0.9.0

* Add support for Rails 7 and update Restforce dependency to newer version. (https://github.com/Beyond-Finance/active_force/pull/3)
* Add `has_one` association. (https://github.com/Beyond-Finance/active_force/pull/3)
* Model generator enhancements (https://github.com/Beyond-Finance/active_force/pull/3):
* automatically add types to fields
* sort fields alphabetically
* add `table_name` to class
* add optional namespace parameter so generated models can be namespaced
* Add get/set via `[]` and `[]=` for `SObject` attributes. (https://github.com/Beyond-Finance/active_force/pull/3)

## 0.7.1

* Allow sfdc_client to be set. ([#92][])
Expand Down
1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
source 'https://rubygems.org'

# Specify your gem's dependencies in active_force.gemspec
gem "codeclimate-test-reporter", group: :test, require: nil
gemspec
24 changes: 19 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
A ruby gem to interact with [SalesForce][1] as if it were Active Record. It
uses [Restforce][2] to interact with the API, so it is fast and stable.

### Heroku Fork
### Beyond Finance Fork

This version is forked from the work done by
https://github.com/ionia-corporation/active_force with upgrades for Rails 5, as
https://github.com/heroku/active_force which was in turn forked from
https://github.com/ionia-corporation/active_force.
It includes upgrades for Rails 7, as
well as additional functionality.

## Installation

Add this line to your application's `Gemfile`:

gem 'active_force', github: "heroku/active_force"
gem 'active_force', github: "Beyond-Finance/active_force"

And then execute:

Expand Down Expand Up @@ -100,6 +102,10 @@ Altenative you can try the generator. (requires setting up the connection)

rails generate active_force_model Medication__c

The model generator also supports an optional namespace which will add a namespace to the generated model

rails generate active_force_model Medication__c SomeNamespace

### Associations

#### Has Many
Expand All @@ -123,6 +129,14 @@ class Account < ActiveForce::SObject
end
```

#### Has One

```ruby
class Car < ActiveForce::SObject
has_one :engine, model: CarEngine
end
```

#### Belongs to

```ruby
Expand Down Expand Up @@ -169,12 +183,12 @@ class Account < ActiveForce::SObject
def self.decorate account_records
# Perform other API call once for all account_records ids
other_things = OtherAPI.find_things_with_ids(account_records.map{ |a| a["Id"] } )
account_records.map do |a|
account_records.map do |a|
# Find other_thing that corresponds to the current account_record
other_thing_for_account = other_things.detect{ |o| o["Id"] == a["Id"]}

# make updates to each record
a.merge_in_other_stuff(other_thing_for_account)
a.merge_in_other_stuff(other_thing_for_account)
end # the mapped array will be returned
end
end
Expand Down
7 changes: 3 additions & 4 deletions active_force.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ Gem::Specification.new do |spec|

spec.required_ruby_version = '>= 1.9.3'

spec.add_dependency 'activemodel', '~> 5.2'
spec.add_dependency 'activesupport', '~> 5.2'
spec.add_dependency 'restforce', '~> 2.5'
spec.add_development_dependency 'bundler', '~> 1.16'
spec.add_dependency 'activemodel', '~> 7.0'
spec.add_dependency 'activesupport', '~> 7.0'
spec.add_dependency 'restforce', '>= 5'
spec.add_development_dependency 'rake', '>= 0'
spec.add_development_dependency 'rspec', '>= 0'
spec.add_development_dependency 'pry', '>= 0'
Expand Down
2 changes: 1 addition & 1 deletion lib/active_force/active_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ActiveQuery < Query
attr_reader :sobject

def_delegators :sobject, :sfdc_client, :build, :table_name, :mappings
def_delegators :to_a, :each, :map, :inspect
def_delegators :to_a, :each, :map, :inspect, :pluck, :each_with_object

def initialize sobject
@sobject = sobject
Expand Down
5 changes: 5 additions & 0 deletions lib/active_force/association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'active_force/association/eager_load_projection_builder'
require 'active_force/association/relation_model_builder'
require 'active_force/association/has_many_association'
require 'active_force/association/has_one_association'
require 'active_force/association/belongs_to_association'

module ActiveForce
Expand All @@ -21,6 +22,10 @@ def has_many relation_name, options = {}
associations[relation_name] = HasManyAssociation.new(self, relation_name, options)
end

def has_one relation_name, options = {}
associations[relation_name] = HasOneAssociation.new(self, relation_name, options)
end

def belongs_to relation_name, options = {}
associations[relation_name] = BelongsToAssociation.new(self, relation_name, options)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/active_force/association/association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def foreign_key
end

def relationship_name
options[:relationship_name] || relation_model.table_name
options[:relationship_name] || relation_model.to_s.constantize.table_name
end

###
Expand Down
8 changes: 8 additions & 0 deletions lib/active_force/association/eager_load_projection_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ def projections
end
end

class HasOneAssociationProjectionBuilder < AbstractProjectionBuilder
def projections
query = Query.new association.sfdc_association_field
query.fields association.relation_model.fields
["(#{query.to_s})"]
end
end

class BelongsToAssociationProjectionBuilder < AbstractProjectionBuilder
def projections
association.relation_model.fields.map do |field|
Expand Down
29 changes: 29 additions & 0 deletions lib/active_force/association/has_one_association.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module ActiveForce
module Association
class HasOneAssociation < Association
private

def default_foreign_key
infer_foreign_key_from_model @parent
end

def define_relation_method
association = self
_method = @relation_name
@parent.send :define_method, _method do
association_cache.fetch(_method) do
association_cache[_method] = association.relation_model.to_s.constantize.find_by(association.foreign_key => self.id)
end
end

@parent.send :define_method, "#{_method}=" do |other|
value_to_set = other.nil? ? nil : self.id
# Do we change the object that was passed in or do we modify the already associated object?
obj_to_change = value_to_set ? other : self.send(association.relation_name)
obj_to_change.send "#{ association.foreign_key }=", value_to_set
association_cache[_method] = other
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/active_force/association/relation_model_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def call

class BuildFromNilClass < AbstractBuildFrom
def call
association.is_a?(BelongsToAssociation) ? nil : []
association.is_a?(HasManyAssociation) ? [] : nil
end
end

Expand Down
30 changes: 0 additions & 30 deletions lib/active_force/attributable.rb

This file was deleted.

34 changes: 16 additions & 18 deletions lib/active_force/sobject.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
require 'active_model'
require 'active_force/active_query'
require 'active_force/attributable'
require 'active_force/association'
require 'active_force/mapping'
require 'yaml'
Expand All @@ -12,11 +11,12 @@ module ActiveForce
class RecordInvalid < StandardError;end

class SObject
include ActiveModel::API
include ActiveModel::AttributeMethods
include ActiveModel::Attributes
include ActiveModel::Model
include ActiveModel::Dirty
extend ActiveModel::Callbacks
include ActiveForce::Attributable
extend ActiveForce::Association

define_model_callbacks :build, :create, :update, :save, :destroy
Expand Down Expand Up @@ -82,7 +82,7 @@ def update_attributes! attributes = {}

def update_attributes attributes = {}
update_attributes! attributes
rescue Faraday::Error::ClientError, RecordInvalid => error
rescue Faraday::ClientError, RecordInvalid => error
handle_save_error error
end

Expand All @@ -101,7 +101,7 @@ def create!

def create
create!
rescue Faraday::Error::ClientError, RecordInvalid => error
rescue Faraday::ClientError, RecordInvalid => error
handle_save_error error
self
end
Expand Down Expand Up @@ -132,7 +132,7 @@ def save!

def save
save!
rescue Faraday::Error::ClientError, RecordInvalid => error
rescue Faraday::ClientError, RecordInvalid => error
handle_save_error error
end

Expand All @@ -146,25 +146,15 @@ def persisted?

def self.field field_name, args = {}
mapping.field field_name, args
cast_type = args.fetch(:as, :string)
attribute field_name, cast_type
define_attribute_methods field_name
define_attribute_reader field_name
define_attribute_writer field_name, args
end

def modified_attributes
attributes.select{ |attr, key| changed.include? attr.to_s }
end

def self.attribute_names
mapping.mappings.keys.map(&:to_s)
end

def attributes
mappings.keys.each_with_object(Hash.new) do |field, hsh|
hsh[field.to_s] = self.send(field)
end
end

def reload
association_cache.clear
reloaded = self.class.find(id)
Expand All @@ -187,6 +177,14 @@ def write_value key, value
send "#{field}=", value if field && respond_to?(field)
end

def [](name)
send(name.to_sym)
end

def []=(name,value)
send("#{name.to_sym}=", value)
end

private

def validate!
Expand All @@ -209,7 +207,7 @@ def association_cache
def logger_output action, exception, params = {}
logger = Logger.new(STDOUT)
logger.info("[SFDC] [#{self.class.model_name}] [#{self.class.table_name}] Error while #{ action }, params: #{params}, error: #{exception.inspect}")
errors[:base] << exception.message
errors.add(:base, exception.message)
false
end

Expand Down
2 changes: 1 addition & 1 deletion lib/active_force/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module ActiveForce
VERSION = "0.8.3"
VERSION = "0.9.0"
end
Loading