Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 2 commits
  • 7 files changed
  • 0 commit comments
  • 1 contributor
View
5 Rakefile
@@ -9,7 +9,6 @@ rescue Bundler::BundlerError => e
exit e.status_code
end
require 'rake'
-require
begin
require 'jeweler'
@@ -41,8 +40,4 @@ namespace :features do
conn.execute('USE acts_as_account')
load(File.dirname(__FILE__) + '/db/schema.rb')
end
-
- Cucumber::Rake::Task.new(:run) do |t|
- t.cucumber_opts = "features --format pretty"
- end
end
View
2  VERSION
@@ -1 +1 @@
-1.1.5
+1.1.6
View
11 features/account/account_creation.feature
@@ -4,8 +4,13 @@ Feature: Creating an Account
Scenario: Every Holder should have a default Account
Then User A has an Account named default
-
- Scenario: Creating a second Accounts with the same name for a Holder returns original account
+
+ Scenario: Creating a second Accounts with the same name for a Holder returns original account
Given User A has an Account named default
And I create an Account named default for User A
- Then I get the original account
+ Then I get the original account
+
+ Scenario: Race condition while creating account
+ Given I have the same user in memory
+ And I disable the account existence check on those
+ When I call 'account' on both it should be possible
View
25 features/step_definitions/account_steps.rb
@@ -19,13 +19,13 @@ def german_date_time_to_local(datestring, timestring)
Then /^the account has (\d+) journals?$/ do |num_journals|
num_journals = num_journals.to_i
-
+
if num_journals == 1
@journal = @account.journals.first
else
@journals = @account.journals
end
-
+
assert_equal num_journals, @account.journals.count
end
@@ -56,7 +56,7 @@ def german_date_time_to_local(datestring, timestring)
to_account = Account.for(to)
Journal.current.transfer(amount.to_i, from_account, to_account, @reference, @valuta)
end
-
+
Then /^the balance\-sheet should be:$/ do |table|
table.hashes.each do |row|
assert_equal row['Balance'].to_i, User.find_by_name(row['User']).account.balance
@@ -103,7 +103,7 @@ def german_date_time_to_local(datestring, timestring)
Then /^all postings reference (\w+) with (\w+) (\w+)$/ do |reference_class, name, value|
reference = reference_class.constantize.find(:first, :conditions => "#{name} = #{value}")
Posting.all.each do |posting|
- assert_equal reference, posting.reference
+ assert_equal reference, posting.reference
end
end
@@ -121,7 +121,7 @@ def german_date_time_to_local(datestring, timestring)
Then /^(\w+) with (\w+) (\w+) references all postings$/ do |reference_class, name, value|
reference = reference_class.constantize.find(:first, :conditions => "#{name} = #{value}")
- assert_equal Posting.all, reference.postings
+ assert_equal Posting.all, reference.postings
end
Then /^the order of the postings is correct$/ do
@@ -130,4 +130,19 @@ def german_date_time_to_local(datestring, timestring)
assert from.amount < 0
assert to.amount > 0
end
+end
+
+Given /^I have the same user in memory$/ do
+ @user1 = User.first
+ @user2 = User.find(@user1.id)
+end
+
+Given /^I disable the account existence check on those$/ do
+ [@user1, @user2].each do |user|
+ user.instance_eval "def default_account ; end"
+ end
+end
+
+When /^I call 'account' on both it should be possible$/ do
+ [@user1, @user2].each { |user| user.account }
end
View
3  features/support/env.rb
@@ -2,9 +2,8 @@
World(Test::Unit::Assertions)
-ActiveRecord::Base.establish_connection(YAML.load_file(File.dirname(__FILE__) + '/../../db/database.yml')['acts_as_account'])
-
require File.dirname(__FILE__) + '/../../lib/acts_as_account'
+ActiveRecord::Base.establish_connection(YAML.load_file(File.dirname(__FILE__) + '/../../db/database.yml')['acts_as_account'])
#ActiveRecord::Base.logger = Logger.new(STDOUT)
View
36 lib/acts_as_account/account.rb
@@ -1,46 +1,46 @@
module ActsAsAccount
class Account < ActiveRecord::Base
set_table_name :acts_as_account_accounts
-
+
belongs_to :holder, :polymorphic => true
has_many :postings
has_many :journals, :through => :postings
- # TODO: discuss with norman:
+ # TODO: discuss with norman:
# validates_presence_of will force an ActiveRecord::find on the object
# but we have to create accounts for deleted holder!
#
# validates_presence_of :holder
-
+
class << self
-
+
def recalculate_all_balances
ActsAsAccount::Account.update_all(:balance => 0, :postings_count => 0, :last_valuta => nil)
sql = <<-EOT
- SELECT
- account_id as id,
+ SELECT
+ account_id as id,
count(*) as calculated_postings_count,
sum(amount) as calculated_balance,
max(valuta) as calculated_valuta
FROM
- acts_as_account_postings
- GROUP BY
- account_id
- HAVING
+ acts_as_account_postings
+ GROUP BY
+ account_id
+ HAVING
calculated_postings_count > 0
EOT
ActsAsAccount::Account.find_by_sql(sql).each do |account|
account.lock!
account.update_attributes(
- :balance => account.calculated_balance,
+ :balance => account.calculated_balance,
:postings_count => account.calculated_postings_count,
:last_valuta => account.calculated_valuta)
puts "account:#{account.id}, balance:#{account.balance}, postings_count:#{account.postings_count}, last_valuta:#{account.last_valuta}"
end
end
-
+
def for(name)
GlobalAccount.find_or_create_by_name(name.to_s).account
end
@@ -50,26 +50,26 @@ def create!(attributes = nil)
super
end
end
-
+
def create(attributes = nil)
find_on_error(attributes) do
super
end
end
-
+
def delete_account(number)
transaction do
account = find(number)
raise ActiveRecord::ActiveRecordError, "Cannot be deleted" unless account.deleteable?
-
+
account.holder.destroy if [ManuallyCreatedAccount, GlobalAccount].include?(account.holder.class)
account.destroy
end
end
-
+
def find_on_error(attributes)
yield
-
+
# Trying to create a duplicate key on a unique index raises StatementInvalid
rescue ActiveRecord::StatementInvalid => e
record = if attributes[:holder]
@@ -80,7 +80,7 @@ def find_on_error(attributes)
attributes[:holder_type], attributes[:holder_id], attributes[:name]
])
end
- record || raise
+ record || raise("Cannot find or create account with attributes #{attributes.inspect}")
end
end
View
8 lib/acts_as_account/active_record_extensions.rb
@@ -4,20 +4,20 @@ def self.included(base) # :nodoc:
base.extend ClassMethods
base.class_eval do
def account(name = :default)
- __send__("#{name}_account") || __send__("create_#{name}_account", :name => name.to_s)
+ __send__("#{name}_account") || __send__("create_#{name}_account", :name => name.to_s, :holder_id => self.id, :holder_type => self.class.to_s)
end
end
end
-
+
module ClassMethods
-
+
def has_account(name = :default)
has_one "#{name}_account", :conditions => "name = '#{name}'", :class_name => "ActsAsAccount::Account", :as => :holder
unless instance_methods.include?('accounts')
has_many :accounts, :class_name => "ActsAsAccount::Account", :as => :holder
end
end
-
+
def is_reference
has_many :postings, :class_name => "ActsAsAccount::Posting", :as => :reference
class_eval <<-EOS

No commit comments for this range

Something went wrong with that request. Please try again.