stateful_field_for 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 00e7a7cbc4bee02957da2fa1a4f4d898747a6aad
4
+ data.tar.gz: f760d30c688490fbd49db1be2d16f792cb084ccc
5
+ SHA512:
6
+ metadata.gz: e33b5b26affe43e1b4cac65ff6ef010f7fa6459c46ed8cbbf88e37b8ade7809063293245e49d1627da80cbf2d327164768a22435cb26a3ed80af490b9e2f1a92
7
+ data.tar.gz: 5fbd107d095b9a6122d8e3a38d2ea37a6c5ff0dcfed1cf4e5542cb49dc7851caedd8ea9cfc2b29e2ceaa2980c07cb113aa297c2fd1793548361d3f5c610c01b3
@@ -0,0 +1,50 @@
1
+ # StatefulFieldFor
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
4
+
5
+ Provide the bang and predicate methods for Active Record.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem "stateful_field_for"
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install stateful_field_for
22
+
23
+ ## Usage
24
+
25
+ ```diff
26
+ class Picture < ApplicationRecord
27
+ + stateful_field_for :hidden_at, scope: true do
28
+ + enable :hide, to: :hidden
29
+ + disable :show, to: :visible, initial: true
30
+ + end
31
+ end
32
+ ```
33
+
34
+ Then you can use the bang and predicate methods:
35
+
36
+ ```ruby
37
+ picture = Picture.create
38
+
39
+ picture.show!
40
+ picture.hidden? # false
41
+ picture.visible? # true
42
+
43
+ picture.hide!
44
+ picture.hidden? # true
45
+ picture.visible? # false
46
+ ```
47
+
48
+ ## License
49
+
50
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -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
@@ -0,0 +1,13 @@
1
+ require "stateful_field_for/version"
2
+
3
+ module StatefulFieldFor
4
+ def stateful_field_for(attr_name, options = {}, &block)
5
+ definition = Definition.new(attr_name, options)
6
+ definition.instance_eval(&block)
7
+ const_set definition.module_name, definition._module
8
+ include definition._module
9
+ end
10
+ end
11
+
12
+ require "stateful_field_for/definition"
13
+ require "stateful_field_for/railtie" if defined?(Rails)
@@ -0,0 +1,97 @@
1
+ module StatefulFieldFor
2
+ class Definition
3
+ attr_reader :attr_name, :prefix, :suffix, :scope, :logic
4
+
5
+ def initialize(attr_name, options = {})
6
+ @attr_name = attr_name
7
+ @prefix = options[:prefix]
8
+ @suffix = options[:suffix]
9
+ @scope = options[:scope] || false
10
+ @logic = (options[:type] == :date) ? "Date.today" : "Time.current"
11
+ end
12
+
13
+ def _module
14
+ @_module ||= Module.new do
15
+ def self.included(klass)
16
+ __define_scope_for_activate(klass) if respond_to?(:__define_scope_for_activate)
17
+ __define_scope_for_deactivate(klass) if respond_to?(:__define_scope_for_deactivate)
18
+ __define_after_initialize(klass) if respond_to?(:__define_after_initialize)
19
+ end
20
+ end
21
+ end
22
+
23
+ def module_name
24
+ "generated_#{attr_name}_stateful_methods".split("_").map(&:camelize).join
25
+ end
26
+
27
+ private
28
+
29
+ def enable(event_basename, to: nil, initial: false)
30
+ event = format_name(event_basename)
31
+ state = to.nil? ? event : format_name(to)
32
+
33
+ _module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
34
+ def #{state}?
35
+ !#{attr_name}.nil?
36
+ end
37
+
38
+ def #{event}
39
+ self.#{attr_name} = #{logic}
40
+ end
41
+
42
+ def #{event}!(options = {})
43
+ #{event}
44
+ save!(options)
45
+ end
46
+ RUBY
47
+
48
+ _module.module_eval <<-RUBY, __FILE__, __LINE__ + 1 if scope
49
+ def self.__define_scope_for_activate(klass)
50
+ klass.scope :#{state}, -> { where.not(#{attr_name}: nil) }
51
+ end
52
+ RUBY
53
+
54
+ _module.module_eval <<-RUBY, __FILE__, __LINE__ + 1 if initial
55
+ def self.__define_after_initialize(klass)
56
+ klass.after_initialize :#{event}
57
+ end
58
+ RUBY
59
+ end
60
+
61
+ def disable(event_basename, to: nil, initial: false)
62
+ event = format_name(event_basename)
63
+ state = to.nil? ? event : format_name(to)
64
+
65
+ _module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
66
+ def #{state}?
67
+ #{attr_name}.nil?
68
+ end
69
+
70
+ def #{event}
71
+ self.#{attr_name} = nil
72
+ end
73
+
74
+ def #{event}!(options = {})
75
+ #{event}
76
+ save!(options)
77
+ end
78
+ RUBY
79
+
80
+ _module.module_eval <<-RUBY, __FILE__, __LINE__ + 1 if scope
81
+ def self.__define_scope_for_deactivate(klass)
82
+ klass.scope :#{state}, -> { where(#{attr_name}: nil) }
83
+ end
84
+ RUBY
85
+
86
+ _module.module_eval <<-RUBY, __FILE__, __LINE__ + 1 if initial
87
+ def self.__define_after_initialize(klass)
88
+ klass.after_initialize :#{event}
89
+ end
90
+ RUBY
91
+ end
92
+
93
+ def format_name(basename)
94
+ [prefix, basename, suffix].compact.join("_")
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,9 @@
1
+ module StatefulFieldFor
2
+ class Railtie < ::Rails::Railtie
3
+ initializer :stateful_field_for do
4
+ ActiveSupport.on_load :active_record do
5
+ extend StatefulFieldFor
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module StatefulFieldFor
2
+ VERSION = "0.1.0".freeze
3
+ end
@@ -0,0 +1,37 @@
1
+ require "active_record"
2
+ require "action_controller"
3
+ require "stateful_field_for"
4
+
5
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
6
+
7
+ module FakeApp
8
+ class Application < Rails::Application
9
+ config.eager_load = false
10
+ end
11
+ end
12
+
13
+ FakeApp::Application.initialize!
14
+
15
+ class CreateTables < ActiveRecord::Migration[5.1]
16
+ def change
17
+ create_table :pictures do |t|
18
+ t.string :title
19
+ t.datetime :published_at
20
+ t.datetime :hidden_at
21
+
22
+ t.timestamps
23
+ end
24
+ end
25
+ end
26
+
27
+ class Picture < ActiveRecord::Base
28
+ stateful_field_for :published_at, scope: true do
29
+ enable :publish, to: :published, initial: true
30
+ disable :unpublish, to: :unpublished
31
+ end
32
+
33
+ stateful_field_for :hidden_at do
34
+ enable :hide, to: :hidden
35
+ disable :show, to: :visible
36
+ end
37
+ end
@@ -0,0 +1 @@
1
+ run Rails.application
File without changes
@@ -0,0 +1,85 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Picture do
4
+ context "scope" do
5
+ let!(:published_records) { Array.new(3) { Picture.create(published_at: Time.current) } }
6
+ let!(:unpublished_records) { Array.new(3) { Picture.create.tap(&:unpublish!) } }
7
+
8
+ describe ".published" do
9
+ subject { Picture.published.pluck(:id) }
10
+ it { is_expected.to match_array published_records.map(&:id) }
11
+ end
12
+
13
+ describe ".unpublished" do
14
+ subject { Picture.unpublished.pluck(:id) }
15
+ it { is_expected.to match_array unpublished_records.map(&:id) }
16
+ end
17
+ end
18
+
19
+ context "callback" do
20
+ let(:instance) { Picture.new }
21
+ subject { instance.published? }
22
+ it { is_expected.to be true }
23
+ end
24
+
25
+ context "predicate" do
26
+ let(:published) { Picture.new(published_at: Time.current) }
27
+ let(:unpublished) { Picture.new.tap(&:unpublish) }
28
+ let(:hidden) { Picture.new(hidden_at: Time.current) }
29
+ let(:visible) { Picture.new(hidden_at: nil) }
30
+
31
+ describe "#published?" do
32
+ it { expect(published.published?).to be true }
33
+ it { expect(unpublished.published?).to be false }
34
+ end
35
+
36
+ describe "#unpublished?" do
37
+ it { expect(unpublished.unpublished?).to be true }
38
+ it { expect(published.unpublished?).to be false }
39
+ end
40
+
41
+ describe "#hidden?" do
42
+ it { expect(hidden.hidden?).to be true }
43
+ it { expect(visible.hidden?).to be false }
44
+ end
45
+
46
+ describe "#visible?" do
47
+ it { expect(visible.visible?).to be true }
48
+ it { expect(hidden.visible?).to be false }
49
+ end
50
+ end
51
+
52
+ context "bang" do
53
+ let(:published) { Picture.new(published_at: Time.current) }
54
+ let(:hidden) { Picture.new(hidden_at: Time.current) }
55
+ let(:visible) { Picture.new(hidden_at: nil) }
56
+
57
+ describe "#publish!" do
58
+ let(:instance) { Picture.new(published_at: nil) }
59
+ before { instance.publish! }
60
+ it { expect(instance.published?).to be true }
61
+ it { expect(instance.persisted?).to be true }
62
+ end
63
+
64
+ describe "#unpublish!" do
65
+ let(:instance) { Picture.new(published_at: Time.current) }
66
+ before { instance.unpublish! }
67
+ it { expect(instance.unpublished?).to be true }
68
+ it { expect(instance.persisted?).to be true }
69
+ end
70
+
71
+ describe "#hide!" do
72
+ let(:instance) { Picture.new(hidden_at: nil) }
73
+ before { instance.hide! }
74
+ it { expect(instance.hidden?).to be true }
75
+ it { expect(instance.persisted?).to be true }
76
+ end
77
+
78
+ describe "#show!" do
79
+ let(:instance) { Picture.new(hidden_at: Time.current) }
80
+ before { instance.show! }
81
+ it { expect(instance.visible?).to be true }
82
+ it { expect(instance.persisted?).to be true }
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,22 @@
1
+ require "bundler/setup"
2
+ # load Rails first
3
+ require "rails"
4
+
5
+ # needs to load the app next
6
+ require_relative "fake_app/application"
7
+
8
+ require "stateful_field_for"
9
+ require "rspec/rails"
10
+ require "pry"
11
+
12
+ RSpec.configure do |config|
13
+ config.example_status_persistence_file_path = ".rspec_status"
14
+ config.disable_monkey_patching!
15
+ config.use_transactional_fixtures = true
16
+
17
+ config.expect_with :rspec do |c|
18
+ c.syntax = :expect
19
+ end
20
+ end
21
+
22
+ CreateTables.migrate(:up) unless ActiveRecord::Base.connection.table_exists?("pictures")
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe StatefulFieldFor do
4
+ it "has a version number" do
5
+ expect(StatefulFieldFor::VERSION).not_to be nil
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stateful_field_for
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yoshiyuki Hirano
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-10-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.15'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.15'
41
+ description: Provide the bang and predicate methods for Active Record
42
+ email:
43
+ - yhirano@me.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - README.md
49
+ - Rakefile
50
+ - lib/stateful_field_for.rb
51
+ - lib/stateful_field_for/definition.rb
52
+ - lib/stateful_field_for/railtie.rb
53
+ - lib/stateful_field_for/version.rb
54
+ - spec/fake_app/application.rb
55
+ - spec/fake_app/config.ru
56
+ - spec/fake_app/log/development.log
57
+ - spec/model_spec.rb
58
+ - spec/spec_helper.rb
59
+ - spec/stateful_field_for_spec.rb
60
+ homepage: https://github.com/yhirano55/stateful_field_for
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 2.2.0
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.6.13
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Provide the bang and predicate methods for Active Record
84
+ test_files:
85
+ - spec/fake_app/application.rb
86
+ - spec/fake_app/config.ru
87
+ - spec/fake_app/log/development.log
88
+ - spec/model_spec.rb
89
+ - spec/spec_helper.rb
90
+ - spec/stateful_field_for_spec.rb