action_component 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 743d176be9df1da38d3b0aa1b4609505ea8de03a
4
+ data.tar.gz: 7be1460ea0d7b0f68e58bb90a70ec78ff8ee6013
5
+ SHA512:
6
+ metadata.gz: 92ba9a92079dc33beaac95607f98dcad316b559540dfcc54be48cec5a7bb3f4759cf283fd8af3292fcc8e914777dfa77b36fd9be0ce397432d64ea5e565dba1c
7
+ data.tar.gz: 7e540ab4fc1fd22440286c3e1bee0293e1f069f7c2f59fe03afb90851e738d9148202374260d0dc661dfc1596bde57625b3fb7cc110abf51699a5026b7b9d685
@@ -0,0 +1 @@
1
+ *.gem
@@ -0,0 +1,87 @@
1
+ # ActionComponent
2
+
3
+ A React-style component system for Ruby on Rails.
4
+
5
+ This gem should be considered "alpha" as it currently has no tests.
6
+
7
+ ## Examples
8
+
9
+ ### Example 1: Integrating components into a standard Rails app
10
+
11
+ ```html+erb
12
+ <!-- app/views/posts/show.html.erb -->
13
+
14
+ <div class="post">
15
+ <h2><%= @post.title %></h2>
16
+ <%= render_component AuthorComponent, author: @post.author %>
17
+
18
+ <%= simple_format @post.content %>
19
+ </div>
20
+ ```
21
+
22
+ ```ruby
23
+ # app/components/author_component.rb
24
+
25
+ class AuthorComponent < ActionComponent::Base
26
+ def load
27
+ @post_count = @author.posts.published.count
28
+ end
29
+
30
+ def view
31
+ div(class: 'author') do
32
+ insert image_tag(@author, alt: @author.name)
33
+
34
+ div link_to(@author.name, @author), class: 'name'
35
+
36
+ div pluralize(@post_count, 'post'), class: 'post-count'
37
+
38
+ stars
39
+ end
40
+ end
41
+
42
+ def stars
43
+ div class: 'stars' do
44
+ @author.stars.times { span "*" }
45
+ end
46
+ end
47
+ end
48
+ ```
49
+
50
+ ### Example 2: Using components instead of views
51
+
52
+ ```ruby
53
+ # app/controllers/posts_controller.rb
54
+
55
+ class PostsController < ApplicationController
56
+ def show
57
+ post = Post.find(params[:id])
58
+
59
+ render_component PostComponent, post: post
60
+ end
61
+ end
62
+ ```
63
+
64
+ ```ruby
65
+ # app/components/post_component.rb
66
+
67
+ class PostComponent < ActionComponent::Base
68
+ def view
69
+ div(class: 'post') do
70
+ h2(@post.title)
71
+
72
+ component AuthorComponent, author: @post.author
73
+
74
+ insert simple_format(@post.content)
75
+ end
76
+ end
77
+ end
78
+ ```
79
+
80
+ ## Contributing
81
+
82
+ Pull requests welcome! If you're thinking of contributing a new feature, or
83
+ significantly changing an existing feature, please propose it as an issue.
84
+
85
+ ## Licence
86
+
87
+ MIT. Copyright Roger Nesbitt.
@@ -0,0 +1,24 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ require "action_component/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "action_component"
7
+ s.version = ActionComponent::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.licenses = ['MIT']
10
+ s.authors = ["Roger Nesbitt"]
11
+ s.email = ["roger@seriousorange.com"]
12
+ s.homepage = "https://github.com/mogest/action_component"
13
+ s.summary = %q{React-style components for Rails}
14
+ s.description = %q{React-style components for Rails, mixing together the controller and a DSL language for HTML views.}
15
+
16
+ s.add_dependency "actionpack", ">= 4"
17
+ s.add_dependency "activesupport", ">= 4"
18
+
19
+ s.add_development_dependency "rspec"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- spec/*`.split("\n")
23
+ s.require_paths = ["lib"]
24
+ end
@@ -0,0 +1,8 @@
1
+ module ActionComponent
2
+ end
3
+
4
+ require 'action_component/action_controller_rendering'
5
+ require 'action_component/action_view_rendering'
6
+ require 'action_component/base'
7
+ require 'action_component/railtie'
8
+ require 'action_component/version'
@@ -0,0 +1,21 @@
1
+ module ActionComponent
2
+ module ActionControllerRendering
3
+ private
4
+
5
+ def render_component(component_class, opts = {})
6
+ @_component_class = component_class
7
+ @_component_options = opts
8
+
9
+ render_opts = {
10
+ inline: "<% render_component(@_component_class, @_component_options) %>",
11
+ layout: true
12
+ }
13
+
14
+ [:content_type, :layout, :location, :status, :formats].each do |option|
15
+ render_opts[option] = opts[option] if opts.member?(option)
16
+ end
17
+
18
+ render render_opts
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ module ActionComponent
2
+ module ActionViewRendering
3
+ def render_component(component_class, opts = {})
4
+ component_class.render(self, opts)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,107 @@
1
+ module ActionComponent
2
+ RenderError = Class.new(StandardError)
3
+
4
+ ELEMENTS = %w(
5
+ html head title base link meta style
6
+ script noscript
7
+ body section nav article aside h1 h2 h3 h4 h5 h6 hgroup header footer address
8
+ p hr br pre blockquote ol ul li dl dt dd figure figcaption div
9
+ a em strong small s cite q dfn abbr time code var samp kbd sub sup i b u mark rt rp bdi bdo span
10
+ ins del
11
+ img iframe embed object param video audio source track canvas map area
12
+ table caption colgroup col tbody thead tfoot tr td th
13
+ form fieldset legend label input button select datalist optgroup option textarea keygen output progress meter
14
+ details summary command menu
15
+ )
16
+
17
+ class Base
18
+ delegate :concat, to: :@_view
19
+
20
+ def self.define_tags(*element_names)
21
+ element_names.each do |element_name|
22
+ define_method(element_name) do |*args, &block|
23
+ element(element_name, *args, &block)
24
+ end
25
+
26
+ private element_name
27
+ end
28
+ end
29
+
30
+ define_tags *ActionComponent::ELEMENTS
31
+
32
+ def self.render(view, opts = {})
33
+ component = new(view, opts)
34
+ component.load
35
+ component.view
36
+ end
37
+
38
+ def initialize(view, opts = {})
39
+ opts.each do |key, value|
40
+ instance_variable_set("@#{key}", value)
41
+ end
42
+
43
+ @_view = view
44
+ end
45
+
46
+ def load
47
+ end
48
+
49
+ def view
50
+ raise "#{self.class.name} must define a view method to be a valid component"
51
+ end
52
+
53
+ private
54
+
55
+ def method_missing(method, *args, &block)
56
+ if @_view.respond_to?(method)
57
+ @_view.send(method, *args, &block)
58
+ else
59
+ super
60
+ end
61
+ end
62
+
63
+ def render(*args)
64
+ @_view.concat(@_view.render(*args))
65
+ end
66
+
67
+ def component(component, opts = {})
68
+ self.class.render(@_view, opts)
69
+ end
70
+
71
+ alias_method :render_component, :component
72
+
73
+ def text(content)
74
+ @_view.concat content
75
+ end
76
+
77
+ alias_method :text_node, :text
78
+ alias_method :insert, :text
79
+
80
+ def doctype(text = "html")
81
+ @_view.concat("<!doctype #{h(text)}>".html_safe)
82
+ end
83
+
84
+ def element(name, first = nil, second = nil, &block)
85
+ if first.is_a?(Hash)
86
+ opts = first
87
+ else
88
+ opts = second
89
+ text = first
90
+ end
91
+
92
+ output = if text && block
93
+ raise ActionComponent::RenderError, "An element cannot have both text and a block supplied; choose one or the other"
94
+ elsif text
95
+ @_view.content_tag name, text, opts
96
+ elsif block
97
+ @_view.content_tag name, opts, &block
98
+ else
99
+ @_view.tag name, opts
100
+ end
101
+
102
+ @_view.concat(output)
103
+
104
+ nil
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,15 @@
1
+ module ActionComponent
2
+ class Railtie < Rails::Railtie
3
+ initializer "action_component.add_to_action_controller" do
4
+ ActiveSupport.on_load(:action_controller) do
5
+ include ActionComponent::ActionControllerRendering
6
+ end
7
+ end
8
+
9
+ initializer "action_component.add_to_action_view" do
10
+ ActiveSupport.on_load(:action_view) do
11
+ include ActionComponent::ActionViewRendering
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module ActionComponent
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: action_component
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Roger Nesbitt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionpack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: React-style components for Rails, mixing together the controller and
56
+ a DSL language for HTML views.
57
+ email:
58
+ - roger@seriousorange.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - README.md
65
+ - action_component.gemspec
66
+ - lib/action_component.rb
67
+ - lib/action_component/action_controller_rendering.rb
68
+ - lib/action_component/action_view_rendering.rb
69
+ - lib/action_component/base.rb
70
+ - lib/action_component/railtie.rb
71
+ - lib/action_component/version.rb
72
+ homepage: https://github.com/mogest/action_component
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.5.1
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: React-style components for Rails
96
+ test_files: []