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

Added update_or_create method #4

Merged
merged 4 commits into from Jul 28, 2017
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Expand Up @@ -37,9 +37,16 @@ Add this line to your application's deploy.rb file:
The below example ensures that there are 3 users existing in the database after running the 'rake reference_data:load'

### db/reference/000_users.rb
Easy::ReferenceData.refresh User, :system_code, 'nigel', name: 'Nigel Ramsay', email: 'nigel.ramsay@mailinator.com'
Easy::ReferenceData.refresh User, :system_code, 'fred', name: 'Fred Schmitt', email: 'fred.schmitt@mailinator.com'
Easy::ReferenceData.refresh User, :system_code, 'bert', name: 'Bert Symthe', email: 'bert.smythe@mailinator.com'
Easy::ReferenceData.update_or_create User, {system_code: 'nigel', name: 'Nigel Ramsay', email: 'nigel.ramsay@mailinator.com'}, keys: [:system_code]
Easy::ReferenceData.update_or_create User, {system_code: 'fred', name: 'Fred Schmitt', email: 'fred.schmitt@mailinator.com'}, keys: [:system_code]
Easy::ReferenceData.update_or_create User, {system_code: 'bert', name: 'Bert Symthe', email: 'bert.smythe@mailinator.com'}, keys: [:system_code]

Multiple keys can be used to identify records that would otherwise not have a unique attribute

### db/reference/000_prices.rb
Easy::ReferenceData.update_or_create Price, {product_id: 1, type: "Price::RetailPrice", price: 5}, keys: [:product_id, :type]
Easy::ReferenceData.update_or_create Price, {product_id: 1, type: "Price::CostPrice", price: 4}, keys: [:product_id, :type]
Easy::ReferenceData.update_or_create Price, {product_id: 2, type: "Price::RetailPrice", price: 5}, keys: [:product_id, :type]

## Contributing

Expand Down
26 changes: 13 additions & 13 deletions lib/easy/reference_data/refresh.rb
@@ -1,31 +1,31 @@
require 'active_support'

module Easy
module ReferenceData
def self.refresh(clazz, unique_attribute_symbol, unique_attribute_value, attributes)
record = clazz.where(unique_attribute_symbol => unique_attribute_value).first
self.update_or_create(clazz, attributes.merge(unique_attribute_symbol => unique_attribute_value), keys: [unique_attribute_symbol])
end

if record.nil?
record = clazz.new
record.send "#{unique_attribute_symbol}=", unique_attribute_value
end
def self.update_or_create(clazz, attributes, options)
unique_attribute_keys = options.fetch(:keys)

attributes.each_pair do |key, value|
record.send "#{key}=", value
end
record = clazz.where(attributes.slice(*unique_attribute_keys)).first_or_initialize

if record.new_record?
puts "..creating #{clazz}(#{unique_attribute_value})"
elsif record.changed?
puts "..updating #{clazz}(#{unique_attribute_value})"
$stderr.puts "..creating #{clazz}(#{attributes.slice(*unique_attribute_keys)})"
else
$stderr.puts "..updating #{clazz}(#{attributes.slice(*unique_attribute_keys)})"
end

begin
record.save!
record.update_attributes!(attributes)
rescue
puts "Save failed for #{record.class}[#{unique_attribute_symbol}: #{unique_attribute_value}] with attributes #{attributes.inspect}"
$stderr.puts "Save failed for #{record.class} with attributes #{attributes.inspect}"
raise
end

record
end

end
end
4 changes: 2 additions & 2 deletions lib/easy/reference_data/version.rb
@@ -1,5 +1,5 @@
module Easy
module ReferenceData
VERSION = "0.1.2"
VERSION = "1.0.0"
end
end
end
38 changes: 38 additions & 0 deletions spec/easy/reference_data/refresh_spec.rb
Expand Up @@ -3,6 +3,44 @@

RSpec.describe Easy::ReferenceData do

describe ".update_or_create" do
context "with a single unique attribute" do
context "and an existing record" do

it "does not change the record" do
user = User.create(system_code: 1)

expect{ Easy::ReferenceData.update_or_create(User, {system_code: 1}, keys: [:system_code])}.not_to change{ User.count }
end

context "with additional attribues" do
it "updates the existing record" do
user = User.create(system_code: 1, name: "Jo")

expect{ Easy::ReferenceData.update_or_create(User, {system_code: 1, name: "Jane"}, keys: [:system_code])}.to change{ user.reload.name }.to "Jane"
end
end
end

context "and no existing record" do
it "creates a new record" do
expect{ Easy::ReferenceData.update_or_create(User, {system_code: 1}, keys: [:system_code])}.to change{ User.count }
end
end

end

context "with multiple attributes" do
it "updates the matching record" do
jo_smith = User.create(system_code: 1, name: "Jo", email: "jo.smith@example.com")
jo_brown = User.create(system_code: 1, name: "Jo", email: "jo.brown@example.com")

expect{ Easy::ReferenceData.update_or_create(User, {name: "Jo", email: "jo.brown@example.com", system_code: 2}, keys: [:name, :email])}.to change{ jo_brown.reload.system_code }.to 2
end

end
end

describe ".refresh" do

context "with a unique attribue" do
Expand Down