scoped_attributes 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 78381184544a7b5f61b066c19d17878251f8ae47c575386c44ec72a616c16b85
4
+ data.tar.gz: f149b82115e1aa5cd9caf2dede0e23a6375aa2eb03a4b22935583cf0afb1606d
5
+ SHA512:
6
+ metadata.gz: '086dfa13d6c36dd9c6ce46de3fe2844ff91de2cbf00258dbbe51418159fbf65590ee66d5f70fd95a480a8c254148cac24c6171ef02eacb5c7da3b12cfc98cbb8'
7
+ data.tar.gz: d67ccd206353b78b1ec44ee1a01bca25fea3282da4a1c0a462823eee9e0a82b7c6f0efa89d8a3cb701d7b633060db2a52c0ddeddc3fd92d7d0bdce659925b0f0
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.5
7
+ before_install: gem install bundler -v 2.0.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in scoped_attributes.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,50 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ scoped_attributes (0.1.0)
5
+ activesupport (>= 5.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (6.0.2)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (>= 0.7, < 2)
13
+ minitest (~> 5.1)
14
+ tzinfo (~> 1.1)
15
+ zeitwerk (~> 2.2)
16
+ concurrent-ruby (1.1.5)
17
+ diff-lcs (1.3)
18
+ i18n (1.7.0)
19
+ concurrent-ruby (~> 1.0)
20
+ minitest (5.13.0)
21
+ rake (10.5.0)
22
+ rspec (3.9.0)
23
+ rspec-core (~> 3.9.0)
24
+ rspec-expectations (~> 3.9.0)
25
+ rspec-mocks (~> 3.9.0)
26
+ rspec-core (3.9.0)
27
+ rspec-support (~> 3.9.0)
28
+ rspec-expectations (3.9.0)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.9.0)
31
+ rspec-mocks (3.9.0)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.9.0)
34
+ rspec-support (3.9.0)
35
+ thread_safe (0.3.6)
36
+ tzinfo (1.2.5)
37
+ thread_safe (~> 0.1)
38
+ zeitwerk (2.2.2)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ bundler (~> 2.0)
45
+ rake (~> 10.0)
46
+ rspec (~> 3.0)
47
+ scoped_attributes!
48
+
49
+ BUNDLED WITH
50
+ 2.0.2
data/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # ScopedAttributes
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'scoped_attributes'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install scoped_attributes
18
+
19
+ ## Usage
20
+
21
+ create scoped class
22
+
23
+ ```rb
24
+ class ApplicationScopedModel
25
+ include ScopedAttributes
26
+ roles :admin, :crew
27
+
28
+ def admin?
29
+ user.admin?
30
+ end
31
+
32
+ def crew?
33
+ !admin?
34
+ end
35
+ end
36
+ ```
37
+
38
+ ```rb
39
+ class ScopedCrew < ApplicationScopedModel
40
+ attribute :id
41
+ attribute :name
42
+ attribute :address, only: proc { me? || admin? } # Proc
43
+ attribute :evaluation, only: %i(admin) # role names (Array)
44
+
45
+ def me?
46
+ id == user.crew_id
47
+ end
48
+ end
49
+ ```
50
+
51
+ ### for ActiveRecord
52
+
53
+ usage
54
+
55
+ current_user is crew and crew is not me
56
+
57
+ ```rb
58
+ scoped_crew = ScopedCrew.new(Crew.find(1), current_user)
59
+ scoped_crew.name
60
+ # => "hoge"
61
+
62
+ scoped_crew.address
63
+ # => nil
64
+
65
+ scoped_crew.attributes
66
+ # => {:id=>1, :name=>"hoge"}
67
+
68
+ scoped_crew.to_model
69
+ => #<Crew:xxx id: 1, name: "hoge">
70
+
71
+ Crew.find(1).scoped
72
+ => #<Crew:xxx id: 1, name: "hoge">
73
+ ```
74
+
75
+ current_user is crew and crew is me
76
+ ```rb
77
+ scoped_crew = ScopedCrew.new(Crew.find(1), current_user)
78
+ scoped_crew.name
79
+ # => "hoge"
80
+
81
+ scoped_crew.address
82
+ # => "tokyo"
83
+
84
+ scoped_crew.attributes
85
+ # => {:id=>1, :name=>"hoge", :address=>"tokyo"}
86
+
87
+ scoped_crew.to_model
88
+ => #<Crew:xxx id: 1, name: "hoge", address: "tokyo">
89
+
90
+ Crew.find(1).scoped
91
+ => #<Crew:xxx id: 1, name: "hoge", address: "tokyo">
92
+ ```
93
+
94
+ current_user is admin
95
+
96
+ ```rb
97
+ scoped_crew = ScopedCrew.new(Crew.find(1), current_user)
98
+ scoped_crew.name
99
+ # => "hoge"
100
+
101
+ scoped_crew.address
102
+ # => "tokyo"
103
+
104
+ scoped_crew.attributes
105
+ # => {:id=>1, :name=>"hoge", :address=>"tokyo", :evaluation=>"SS"}
106
+
107
+ scoped_crew.to_model
108
+ => #<Crew:xxx id: 1, name: "hoge", address: "tokyo", evaluation: "SS">
109
+
110
+ Crew.find(1).scoped
111
+ => #<Crew:xxx id: 1, name: "hoge", address: "tokyo", evaluation: "SS">
112
+ ```
113
+
114
+ ## for pure object
115
+
116
+ ```rb
117
+ class ScopedCrew < ApplicationScopedModel
118
+ attribute :name
119
+ attribute :addres
120
+ attribute :evaluation, only: %i(admin)
121
+ end
122
+
123
+ class CustomCrew
124
+ attr_accessor :name, :address, :evaluation
125
+
126
+ def initialize(name, address, evaluation)
127
+ self.name = name
128
+ self.address = address
129
+ self.evaluation = evaluation
130
+ end
131
+ end
132
+
133
+ crew = CustomCrew.new("hoge", "tokyo", "SS")
134
+ scoped_crew = ScopedCrew.new(crew, current_user)
135
+ scoped_crew.attributes
136
+ # => {:name=>"hoge", :address=>"tokyo"}
137
+ ```
138
+
139
+
140
+ ## Development
141
+
142
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
143
+
144
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
145
+
146
+ ## Contributing
147
+
148
+ Bug reports and pull requests are welcome on GitHub at https://github.com/shunhikita/scoped_attributes.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "scoped_attributes"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,15 @@
1
+ require 'rails/railtie'
2
+
3
+ module ScopedAttributes
4
+ class Railtie < Rails::Railtie
5
+ initializer 'scoped_attributes.setup_orm' do
6
+ [:active_record].each do |orm|
7
+ ActiveSupport.on_load orm do
8
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
9
+ include ScopedAttributes::Scopable
10
+ RUBY
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ module ScopedAttributes
2
+ module Scopable
3
+ extend ActiveSupport::Concern
4
+
5
+ def scoped(user)
6
+ klass_name = "Scoped#{self.model_name}"
7
+ klass_name.constantize.new(self, user).to_model
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module ScopedAttributes
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,111 @@
1
+ require "scoped_attributes/version"
2
+ require "scoped_attributes/scopable"
3
+ require 'scoped_attributes/railtie' if defined?(Rails)
4
+ require "active_support/concern"
5
+
6
+ module ScopedAttributes
7
+ extend ActiveSupport::Concern
8
+ class Error < StandardError; end
9
+
10
+ def initialize(object, user)
11
+ self.object = object
12
+ self.user = user
13
+ end
14
+
15
+ included do
16
+ class_attribute :attributes_registry, instance_accessor: false
17
+ class_attribute :model_name, instance_accessor: true
18
+ self.attributes_registry = {}
19
+
20
+ attr_accessor :object, :user
21
+ end
22
+
23
+ class_methods do
24
+ def roles(*role_names)
25
+ role_names.each do |role_name|
26
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
27
+ def #{role_name}?
28
+ raise NotImplementedError.new("You must implement #{self.class}##{__method__}")
29
+ end
30
+ RUBY
31
+ end
32
+ end
33
+
34
+ def attribute(name, **options)
35
+ add_attribute_registry(name.to_sym, options)
36
+ define_attribute_reader(name.to_sym, options)
37
+ end
38
+
39
+ def add_attribute_registry(name, options)
40
+ self.attributes_registry.merge!(name => options)
41
+ end
42
+
43
+ def define_attribute_reader(name, options)
44
+ only = options.fetch(:only, nil)
45
+
46
+ define_method name do
47
+ object.public_send(name) if visible?(only)
48
+ end
49
+ end
50
+ end
51
+
52
+ def model
53
+ (self.class.model_name || self.class.name.gsub("Scoped", "")).safe_constantize
54
+ end
55
+
56
+ def as_json
57
+ attributes
58
+ end
59
+
60
+ def to_model
61
+ return nil if model.nil?
62
+
63
+ if object&.id.nil?
64
+ model.new(attributes)
65
+ else
66
+ model.select(attributes.keys).find_by(id: object.id)
67
+ end
68
+ end
69
+
70
+ def attributes(include_key: false)
71
+ attributes = {}
72
+ self.class.attributes_registry.each do |name, options|
73
+ only = options.fetch(:only, nil)
74
+
75
+ if visible?(only)
76
+ attributes[name] = object.public_send(name)
77
+ elsif include_key
78
+ attributes[name] = nil
79
+ end
80
+ end
81
+ attributes
82
+ end
83
+
84
+ private
85
+
86
+ def visible?(only)
87
+ return true if only.nil?
88
+
89
+ case only
90
+ when Array
91
+ only.any? { |role| public_send("#{role}?") }
92
+ when String
93
+ only.public_send(string)
94
+ when Proc
95
+ unbound_method = generate_method(:only_call, &only)
96
+ !!unbound_method.bind(self).call
97
+ else
98
+ false
99
+ end
100
+ end
101
+
102
+ def generate_method(method_name, &block)
103
+ method = nil
104
+ Module.new do
105
+ define_method method_name, &block
106
+ method = instance_method method_name
107
+ remove_method method_name
108
+ end
109
+ method
110
+ end
111
+ end
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "scoped_attributes/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "scoped_attributes"
7
+ spec.version = ScopedAttributes::VERSION
8
+ spec.authors = ["h1kita"]
9
+
10
+ spec.summary = "Support to attributes visible for each roles."
11
+ spec.description = "Support to attributes visible for each roles."
12
+
13
+ spec.metadata["source_code_uri"] = "https://github.com/shunhikita/scoped_attributes"
14
+
15
+ # Specify which files should be added to the gem when it is released.
16
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 2.0"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ spec.add_dependency "activesupport", ">= 5.0"
28
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: scoped_attributes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - h1kita
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-12-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ description: Support to attributes visible for each roles.
70
+ email:
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - ".gitignore"
76
+ - ".rspec"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - README.md
81
+ - Rakefile
82
+ - bin/console
83
+ - bin/setup
84
+ - lib/scoped_attributes.rb
85
+ - lib/scoped_attributes/railtie.rb
86
+ - lib/scoped_attributes/scopable.rb
87
+ - lib/scoped_attributes/version.rb
88
+ - scoped_attributes.gemspec
89
+ homepage:
90
+ licenses: []
91
+ metadata:
92
+ source_code_uri: https://github.com/shunhikita/scoped_attributes
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubygems_version: 3.0.3
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Support to attributes visible for each roles.
112
+ test_files: []