approval 0.2.3 → 0.3.0

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: b11eef9bb8afb6a55fefa35bc8fef5132d1908d0
4
- data.tar.gz: 628a25ca361506832c1c709902af993c18c43d59
3
+ metadata.gz: 0f6a5f60b035099e2da46cd42dc3c09deafe3b8a
4
+ data.tar.gz: 920839f43297af114060d06f66f2256a22b2040b
5
5
  SHA512:
6
- metadata.gz: e0a6c2f36e2234bc1c3612f8e6b27886bba1c0bf801ead75bd82c95f8e755ba588641d2107a936b28e5d275ea0d450f2850ebf2e49af7748548769c7b62bc300
7
- data.tar.gz: 0bbd75b3e3e5dbdbbd7fa22e3dc4837134f19e895867293c51a99d0371e03044918e371d91a05e7b1fd4115c559f4a1267da90a54c64076fa5066b5646909a73
6
+ metadata.gz: cf0ef7bdf54a232f8e2e0bf200c952b5e5dedbfebc8d9606c405b135863387c2eb4b3732f1d93bf132d922a4371a9fa4a0da2edb77b43f3569524dced809faea
7
+ data.tar.gz: bdd3df5ceff8e92e949df3baa53860b1a374962a0564879520f4be02c07687fa1010fa6cb1b7bbd941c950706417efcadc25183fcbd184769f01724256b7e238
data/README.md CHANGED
@@ -30,7 +30,7 @@
30
30
  4. Add `acts_as_approval_resource` to the models you want use approval flow:
31
31
 
32
32
  ```ruby
33
- class Post < ApplicationRecord
33
+ class Book < ApplicationRecord
34
34
  acts_as_approval_resource
35
35
  end
36
36
  ```
@@ -44,7 +44,7 @@ You send request, but resources aren't created/updated/destroied.
44
44
  #### :pray: Create
45
45
 
46
46
  ```ruby
47
- staff = User.find_or_create_by(email: "staff@example.com")
47
+ staff = User.find_or_create_by(email: "staff@example.com")
48
48
 
49
49
  record = Book.new(name: "Ruby Way", price: 2980)
50
50
  request = staff.request_for_create(record, reason: "something")
@@ -58,13 +58,13 @@ request.save!
58
58
  #### :pray: Update
59
59
 
60
60
  ```ruby
61
- staff = User.find_or_create_by(email: "staff@example.com")
61
+ staff = User.find_or_create_by(email: "staff@example.com")
62
62
 
63
63
  record = Book.find(1).tap {|record| record.name = "new book title" }
64
64
  request = staff.request_for_update(record, reason: "something")
65
65
  request.save
66
66
 
67
- records = Book.where(id: 1, 2, 3).map {|record| record.price *= 0.5 }
67
+ records = Book.where(id: [1, 2, 3]).each {|record| record.price *= 0.5 }
68
68
  request = staff.request_for_update(records, reason: "something")
69
69
  request.save!
70
70
  ```
@@ -72,13 +72,13 @@ request.save!
72
72
  #### :pray: Destroy
73
73
 
74
74
  ```ruby
75
- staff = User.find_or_create_by(email: "staff@example.com")
75
+ staff = User.find_or_create_by(email: "staff@example.com")
76
76
 
77
77
  record = Book.find(1)
78
78
  request = staff.request_for_destroy(record, reason: "something")
79
79
  request.save
80
80
 
81
- records = Book.where(id: 1, 2, 3)
81
+ records = Book.where(id: [1, 2, 3])
82
82
  request = staff.request_for_destroy(records, reason: "something")
83
83
  request.save!
84
84
  ```
@@ -90,7 +90,7 @@ request.save!
90
90
  Then resources are created/updated/destroied, if respond user have approved the request.
91
91
 
92
92
  ```ruby
93
- admin = User.find_or_create_by(email: "admin@example.com")
93
+ admin = User.find_or_create_by(email: "admin@example.com")
94
94
 
95
95
  request = Approval::Request.first
96
96
  respond = admin.approve_request(request, reason: "something")
@@ -102,7 +102,7 @@ respond.save! # Create/Update/Destroy resources
102
102
  Then resources are not created/updated/destroied, if respond user have rejected the request.
103
103
 
104
104
  ```ruby
105
- admin = User.find_or_create_by(email: "admin@example.com")
105
+ admin = User.find_or_create_by(email: "admin@example.com")
106
106
 
107
107
  request = Approval::Request.first
108
108
  respond = admin.reject_request(request, reason: "something")
@@ -119,15 +119,21 @@ respond = staff.cancel_request(request, reason: "something")
119
119
  respond.save!
120
120
  ```
121
121
 
122
+ ### Comment
123
+
124
+ ```ruby
125
+ admin = User.find_or_create_by(email: "admin@example.com")
126
+
127
+ request = Approval::Request.first
128
+ admin.approval_comments.create(request: request, content: "Hello")
129
+ ```
130
+
122
131
  ### Configuration
123
132
 
124
133
  ```ruby
125
134
  # config/initializers/approval.rb
126
135
 
127
136
  Approval.configure do |config|
128
- # Your user model name (e.g. User, AdminUser, Member, default: User)
129
- config.user_class_name = "User"
130
-
131
137
  # Maximum characters of comment for reason (default: 2000)
132
138
  config.comment_maximum = 2000
133
139
 
@@ -2,13 +2,11 @@ module Approval
2
2
  class Config
3
3
  attr_accessor(
4
4
  :comment_maximum,
5
- :user_class_name,
6
5
  :permit_to_respond_to_own_request,
7
6
  )
8
7
 
9
8
  def initialize
10
9
  @comment_maximum = 2000
11
- @user_class_name = "User"
12
10
  @permit_to_respond_to_own_request = false
13
11
  end
14
12
 
@@ -5,7 +5,7 @@ module Approval
5
5
  class_methods do
6
6
  def acts_as_approval_resource(ignore_fields: [])
7
7
  include ::Approval::Mixins::Resource
8
- append_ignore_fields(ignore_fields)
8
+ assign_ignore_fields(ignore_fields)
9
9
  end
10
10
 
11
11
  def acts_as_approval_user
@@ -3,22 +3,26 @@ module Approval
3
3
  module Resource
4
4
  extend ActiveSupport::Concern
5
5
 
6
- DEFAULT_IGNORE_FIELDS = %w[id created_at updated_at].freeze
7
-
8
6
  included do
9
7
  class_attribute :approval_ignore_fields
8
+ self.approval_ignore_fields = %w[id created_at updated_at]
9
+
10
10
  has_many :approval_items, class_name: :"Approval::Item", as: :resource
11
11
  end
12
12
 
13
13
  class_methods do
14
- def append_ignore_fields(ignore_fields = [])
15
- self.approval_ignore_fields = DEFAULT_IGNORE_FIELDS.dup.concat(ignore_fields).map(&:to_s).uniq
14
+ def assign_ignore_fields(ignore_fields = [])
15
+ self.approval_ignore_fields = approval_ignore_fields.concat(ignore_fields).map(&:to_s).uniq
16
16
  end
17
17
  end
18
18
 
19
- def params_for_approval
19
+ def create_params_for_approval
20
20
  attributes.except(*approval_ignore_fields).compact
21
21
  end
22
+
23
+ def update_params_for_approval
24
+ changes.except(*approval_ignore_fields).each_with_object({}) { |(k, v), h| h[k] = v.last }.compact
25
+ end
22
26
  end
23
27
  end
24
28
  end
@@ -6,6 +6,9 @@ module Approval
6
6
  included do
7
7
  has_many :approval_requests, class_name: :"Approval::Request", foreign_key: :request_user_id
8
8
  has_many :approval_comments, class_name: :"Approval::Comment", foreign_key: :user_id
9
+
10
+ Approval::Request.define_user_association(self)
11
+ Approval::Comment.define_user_association(self)
9
12
  end
10
13
 
11
14
  def request_for_create(records, reason:)
@@ -2,8 +2,13 @@ module Approval
2
2
  class Comment < ::ActiveRecord::Base
3
3
  self.table_name_prefix = "approval_".freeze
4
4
 
5
+ class << self
6
+ def define_user_association(klass)
7
+ belongs_to :user, class_name: klass.to_s
8
+ end
9
+ end
10
+
5
11
  belongs_to :request, class_name: :"Approval::Request", inverse_of: :comments
6
- belongs_to :user, class_name: Approval.config.user_class_name
7
12
 
8
13
  validates :content, presence: true, length: { maximum: Approval.config.comment_maximum }
9
14
  end
@@ -15,6 +15,7 @@ module Approval
15
15
  validates :resource_id, unless: :create_event?
16
16
  validates :resource_type
17
17
  validates :event, inclusion: { in: EVENTS }
18
+ validates :params, if: :update_event?
18
19
  end
19
20
 
20
21
  validate :ensure_resource_be_valid
@@ -2,9 +2,13 @@ module Approval
2
2
  class Request < ::ActiveRecord::Base
3
3
  self.table_name_prefix = "approval_".freeze
4
4
 
5
- with_options class_name: Approval.config.user_class_name do
6
- belongs_to :request_user
7
- belongs_to :respond_user, optional: true
5
+ class << self
6
+ def define_user_association(klass)
7
+ with_options class_name: klass.to_s do
8
+ belongs_to :request_user
9
+ belongs_to :respond_user, optional: true
10
+ end
11
+ end
8
12
  end
9
13
 
10
14
  with_options dependent: :destroy, inverse_of: :request do
@@ -18,7 +22,6 @@ module Approval
18
22
 
19
23
  with_options presence: true do
20
24
  validates :state
21
- validates :request_user
22
25
  validates :respond_user, unless: :pending?
23
26
  validates :comments
24
27
  validates :items
@@ -4,14 +4,14 @@ module Approval
4
4
  private
5
5
 
6
6
  def prepare
7
- ::ActiveRecord::Base.transaction do
7
+ ::Approval::Request.transaction do
8
8
  request = user.approval_requests.new
9
9
  request.comments.new(user: user, content: reason)
10
10
  Array(records).each do |record|
11
11
  request.items.new(
12
12
  event: "create",
13
13
  resource_type: record.class.to_s,
14
- params: record.params_for_approval,
14
+ params: record.create_params_for_approval,
15
15
  )
16
16
  end
17
17
  yield(request)
@@ -4,7 +4,7 @@ module Approval
4
4
  private
5
5
 
6
6
  def prepare
7
- ::ActiveRecord::Base.transaction do
7
+ ::Approval::Request.transaction do
8
8
  request = user.approval_requests.new
9
9
  request.comments.new(user: user, content: reason)
10
10
  Array(records).each do |record|
@@ -4,7 +4,7 @@ module Approval
4
4
  private
5
5
 
6
6
  def prepare
7
- ::ActiveRecord::Base.transaction do
7
+ ::Approval::Request.transaction do
8
8
  request = user.approval_requests.new
9
9
  request.comments.new(user: user, content: reason)
10
10
  Array(records).each do |record|
@@ -12,7 +12,7 @@ module Approval
12
12
  event: "update",
13
13
  resource_type: record.class.to_s,
14
14
  resource_id: record.id,
15
- params: record.params_for_approval,
15
+ params: record.update_params_for_approval,
16
16
  )
17
17
  end
18
18
  yield(request)
@@ -6,7 +6,7 @@ module Approval
6
6
  private
7
7
 
8
8
  def prepare
9
- ::ActiveRecord::Base.transaction do
9
+ ::Approval::Request.transaction do
10
10
  request.lock!
11
11
  request.assign_attributes(state: :approved, approved_at: Time.current, respond_user: user)
12
12
  request.comments.new(user: user, content: reason)
@@ -4,7 +4,7 @@ module Approval
4
4
  private
5
5
 
6
6
  def prepare
7
- ::ActiveRecord::Base.transaction do
7
+ ::Approval::Request.transaction do
8
8
  request.lock!
9
9
  request.assign_attributes(state: :cancelled, cancelled_at: Time.current, respond_user: user)
10
10
  request.comments.new(user: user, content: reason)
@@ -6,7 +6,7 @@ module Approval
6
6
  private
7
7
 
8
8
  def prepare
9
- ::ActiveRecord::Base.transaction do
9
+ ::Approval::Request.transaction do
10
10
  request.lock!
11
11
  request.assign_attributes(state: :rejected, rejected_at: Time.current, respond_user: user)
12
12
  request.comments.new(user: user, content: reason)
@@ -1,3 +1,3 @@
1
1
  module Approval
2
- VERSION = "0.2.3".freeze
2
+ VERSION = "0.3.0".freeze
3
3
  end
@@ -1,7 +1,4 @@
1
1
  Approval.configure do |config|
2
- # Your user model name (e.g. User, AdminUser, Member, default: User)
3
- config.user_class_name = "User"
4
-
5
2
  # Maximum characters of comment for reason (default: 2000)
6
3
  config.comment_maximum = 2000
7
4
 
@@ -3,25 +3,28 @@ require "spec_helper"
3
3
  RSpec.describe Book, type: :model do
4
4
  it { is_expected.to have_many(:approval_items).class_name("Approval::Item") }
5
5
 
6
- describe ".append_ignore_fields" do
7
- subject { described_class.append_ignore_fields(ignore_fields) }
6
+ describe ".assign_ignore_fields" do
7
+ subject { described_class.assign_ignore_fields(ignore_fields) }
8
8
 
9
- context "when ignore_fields are blank" do
10
- let(:ignore_fields) { [] }
11
- it { is_expected.to match_array Approval::Mixins::Resource::DEFAULT_IGNORE_FIELDS }
12
- end
13
-
14
- context "when ignore_fields are present" do
15
- let(:ignore_fields) { ["published_at"] }
16
- it { is_expected.to match_array Approval::Mixins::Resource::DEFAULT_IGNORE_FIELDS.dup.concat(["published_at"]) }
9
+ context "when ignore_fields are duplicated symbolized value" do
10
+ let(:ignore_fields) { %i[id id created_at updated_at] }
11
+ it { is_expected.to match_array %w[id created_at updated_at] }
17
12
  end
18
13
  end
19
14
 
20
- describe "#params_for_approval" do
15
+ describe "#create_params_for_approval" do
21
16
  let(:book) { build :book }
22
17
  let(:result) { book.attributes.except("id", "created_at", "updated_at") }
23
18
 
24
- subject { book.params_for_approval }
19
+ subject { book.create_params_for_approval }
20
+ it { is_expected.to eq result }
21
+ end
22
+
23
+ describe "#update_params_for_approval" do
24
+ let(:book) { create(:book).tap { |book| book.name = "changed name" } }
25
+ let(:result) { { "name" => "changed name" } }
26
+
27
+ subject { book.update_params_for_approval }
25
28
  it { is_expected.to eq result }
26
29
  end
27
30
  end
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  RSpec.describe Approval::Comment, type: :model do
4
4
  it { is_expected.to belong_to(:request).class_name("Approval::Request").inverse_of(:comments) }
5
- it { is_expected.to belong_to(:user).class_name(Approval.config.user_class_name) }
5
+ it { is_expected.to belong_to(:user).class_name("User") }
6
6
 
7
7
  it { is_expected.to validate_presence_of(:content) }
8
8
  it { is_expected.to validate_length_of(:content).is_at_most(Approval.config.comment_maximum) }
@@ -9,13 +9,23 @@ RSpec.describe Approval::RequestForm::Update do
9
9
  subject { form.save }
10
10
 
11
11
  context "when records is single" do
12
- let(:records) { create :book }
12
+ let(:records) do
13
+ book = create(:book)
14
+ book.name = "changed name"
15
+ book
16
+ end
17
+
13
18
  it { expect { subject }.not_to raise_error }
14
19
  it { expect { subject }.to change { Approval::Item.count }.from(0).to(1) }
15
20
  end
16
21
 
17
22
  context "when records is multiple" do
18
- let(:records) { create_list :book, 3 }
23
+ let(:records) do
24
+ books = create_list(:book, 3)
25
+ books.map.with_index { |book, i| book.name = "changed name #{i}" }
26
+ books
27
+ end
28
+
19
29
  it { expect { subject }.not_to raise_error }
20
30
  it { expect { subject }.to change { Approval::Item.count }.from(0).to(3) }
21
31
  end
@@ -2,8 +2,8 @@ require "spec_helper"
2
2
 
3
3
  RSpec.describe Approval::Request, type: :model do
4
4
  describe "Association" do
5
- it { is_expected.to belong_to(:request_user).class_name(Approval.config.user_class_name) }
6
- it { is_expected.to belong_to(:respond_user).class_name(Approval.config.user_class_name) }
5
+ it { is_expected.to belong_to(:request_user).class_name("User") }
6
+ it { is_expected.to belong_to(:respond_user).class_name("User") }
7
7
  it { is_expected.to have_many(:comments).class_name("::Approval::Comment").dependent(:destroy) }
8
8
  it { is_expected.to have_many(:items).class_name("::Approval::Item").dependent(:destroy) }
9
9
  end
@@ -12,7 +12,6 @@ RSpec.describe Approval::Request, type: :model do
12
12
 
13
13
  describe "Validation" do
14
14
  it { is_expected.to validate_presence_of(:state) }
15
- it { is_expected.to validate_presence_of(:request_user) }
16
15
  it { is_expected.to validate_presence_of(:comments) }
17
16
  it { is_expected.to validate_presence_of(:items) }
18
17
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: approval
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoshiyuki Hirano
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-01 00:00:00.000000000 Z
11
+ date: 2017-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler