model_base_generators 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a9828c5069fa9a791bcadc2a8997f1314fdb5583
4
+ data.tar.gz: 9d7a3b8935357a7fddfe116443af571f0d2f0bf3
5
+ SHA512:
6
+ metadata.gz: 26f67945497b8986c14b2785281fafea3bec90c855d324946aba03653bd6a86cb6e2ebed34376f71da44a4fbf3241ef9e241738e25c177fe6d7100681af2e6a2
7
+ data.tar.gz: 004427808a77a01c6f0f207bf16940973dbb2cc8cac3aa64069b3e381d22584f70aa1e1679882b7f14e52d6616e14121f4fda7c06ac24841bb41e9690421a9db
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.13.2
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at akm2000@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in model_base.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'enumerize'
8
+ gem 'simplecov'
9
+ gem 'sqlite3'
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 akm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # model_base_generators
2
+
3
+ `model_base_generators` extends generators to use your models effectively.
4
+ It uses twitter-bootstrap-rails, rspec, factory_girl and so on.
5
+
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'model_base_generators'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ ## Usage
20
+
21
+ ### 1. Generate your model
22
+
23
+ ```bash
24
+ $ bin/rails g model Issue project:references{required} title:string status:integer
25
+ ```
26
+
27
+ ### 2. Make up your generated migration
28
+
29
+ Add `:null` option.
30
+
31
+ ```ruby
32
+ class CreateIssues < ActiveRecord::Migration[5.0]
33
+ def change
34
+ create_table :issues do |t|
35
+ t.references :project, null: false, foreign_key: true
36
+ t.string :title , null: false
37
+ t.integer :status, null: false
38
+
39
+ t.timestamps
40
+ end
41
+ end
42
+ end
43
+ ```
44
+
45
+ ### 3. Run migration
46
+
47
+ ```bash
48
+ $ bin/rails db:migrate
49
+ ```
50
+
51
+ ### 4. Generate controller and views
52
+
53
+ ```bash
54
+ $ bin/rails g scaffold_controller issues
55
+ ```
56
+
57
+ Run scaffold_controller **WITHOUT attributes**!
58
+
59
+
60
+
61
+ ## Development
62
+
63
+ 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.
64
+
65
+ 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).
66
+
67
+ ## Contributing
68
+
69
+ Bug reports and pull requests are welcome on GitHub at https://github.com/akm/model_base_generators. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
70
+
71
+
72
+ ## License
73
+
74
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
75
+
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 "model_base"
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
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,77 @@
1
+ require 'model_base'
2
+
3
+ require 'rails/generators/generated_attribute'
4
+
5
+ module ModelBase
6
+ class ColumnAttribute < ::Rails::Generators::GeneratedAttribute
7
+ attr_accessor :linkable
8
+ alias_method :linkable?, :linkable
9
+
10
+ attr_reader :reference
11
+ attr_reader :model, :column
12
+
13
+ def initialize(model, name, type, column: nil, reference: nil, index_type: false, attr_options: {})
14
+ super(name, type, index_type, attr_options)
15
+ @model = model
16
+ @reference = reference
17
+ @column = column
18
+ end
19
+
20
+ def ref_model
21
+ unless defined?(@ref_model)
22
+ @ref_model = reference.nil? ? nil : ModelBase::MetaModel.new(reference.class_name)
23
+ end
24
+ @ref_model
25
+ end
26
+
27
+ def required?
28
+ !column.try(:null)
29
+ end
30
+
31
+ def enumerized?
32
+ model.model_class.respond_to?(name) &&
33
+ defined?(Enumerize) && model.model_class.send(name).is_a?(Enumerize::Attribute)
34
+ end
35
+
36
+ def select_renderer
37
+ ref_model ? ReferenceSelectRenderer.new(self) :
38
+ enumerized? ? EnumerizedSelectRenderer.new(self) : nil
39
+ end
40
+
41
+ class AbstractSelectRenderer
42
+ attr_reader :column_attr
43
+ def initialize(column_attr)
44
+ @column_attr = column_attr
45
+ end
46
+
47
+ def render(form_name, target_name, options = {})
48
+ html = options.delete(:html) || {}
49
+ html_exp = html.empty? ? nil : html.inspect.gsub(/\A\{|\}\z/, '')
50
+ options.update(include_blank: !column_attr.required?)
51
+ options_exp = {}.inspect
52
+ r = render_core(form_name, target_name)
53
+ r << ", #{options_exp}"
54
+ r << ", #{html_exp}" unless html.empty?
55
+ r
56
+ end
57
+ end
58
+
59
+ class ReferenceSelectRenderer < AbstractSelectRenderer
60
+ def render_core(form_name, target_name, options = {})
61
+ ref_model = column_attr.ref_model
62
+ query =
63
+ ref_model.respond_to?(:choices_for) ?
64
+ "#{ref_model.name}.choices_for(#{taregt_name})" :
65
+ "#{ref_model.name}.all"
66
+ "#{form_name}.collection_select :#{column_attr.name}, #{query}, :id, :#{ref_model.title_column.name}"
67
+ end
68
+ end
69
+
70
+ class EnumerizedSelectRenderer < AbstractSelectRenderer
71
+ def render_core(form_name, target_name, options = {})
72
+ "#{form_name}.select :#{column_attr.name}, #{column_attr.model.name}.#{column_attr.name}.optoins"
73
+ end
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,21 @@
1
+ require 'model_base'
2
+
3
+ module ModelBase
4
+ class Configuration
5
+ include ActiveSupport::Configurable
6
+
7
+ config_accessor(:disabled){ false }
8
+
9
+ config_accessor(:excluded_columns) do
10
+ [
11
+ /.*_checksum/,
12
+ /.*_count/,
13
+ ] + %w[_id _type id created_at updated_at]
14
+ end
15
+
16
+ config_accessor(:title_column_candidates) do
17
+ ['name', 'title', 'email', 'display_name', 'display_title', /_name\z/, /_title\z/]
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ require 'model_base'
2
+
3
+ require 'rails/generators'
4
+
5
+ module ModelBase
6
+ module Generators
7
+ module ModelSupport
8
+ def self.included(klass)
9
+ klass.send :include, ::Rails::Generators::ResourceHelpers
10
+ end
11
+
12
+ def initialize(args, *options)
13
+ super(args, *options)
14
+ @model_name = (class_path + [@name.singularize.camelize]).join('::') unless @model_name
15
+ @model_name = @model_name.camelize
16
+ end
17
+
18
+ protected
19
+
20
+ def model
21
+ @model ||= ModelBase::MetaModel.new(@model_name)
22
+ end
23
+
24
+ def controller_routing_path
25
+ ActiveModel::Naming.route_key(@model_name.constantize)
26
+ end
27
+
28
+ def singular_controller_routing_path
29
+ ActiveModel::Naming.singular_route_key(@model_name.constantize)
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,76 @@
1
+ require "model_base"
2
+
3
+ module ModelBase
4
+ class MetaModel
5
+
6
+ attr_reader :name
7
+ def initialize(name)
8
+ @name = name
9
+ end
10
+
11
+ alias_method :class_name, :name
12
+
13
+ def plural_name
14
+ name.pluralize
15
+ end
16
+
17
+ def resource_name
18
+ name.demodulize.underscore
19
+ end
20
+
21
+ def plural_resource_name
22
+ resource_name.pluralize
23
+ end
24
+
25
+ def full_resource_name
26
+ name.underscore.gsub('/', '_').sub(/\A_/, '')
27
+ end
28
+
29
+ def plural_full_resource_name
30
+ full_resource_name.pluralize
31
+ end
32
+
33
+ def columns
34
+ @columns ||= retrieve_columns.reject {|c| excluded?(c.name) }
35
+ end
36
+
37
+ def model_class
38
+ @model_class ||= name.constantize
39
+ end
40
+
41
+ def active_record?
42
+ defined?(ActiveRecord) == "constant" && ActiveRecord.class == Module && model_class < ActiveRecord::Base
43
+ end
44
+
45
+ def retrieve_columns
46
+ raw_cols = active_record? ? model_class.columns : model_class.fields.map {|c| c[1] }
47
+ belongs_to_refs = model_class.reflections.values.select{|ref| ref.is_a?(ActiveRecord::Reflection::BelongsToReflection) }
48
+ cols = raw_cols.map do |col|
49
+ ref = belongs_to_refs.detect{|ref| ref.foreign_key == col.name}
50
+ ColumnAttribute.new(self, col.name, col.type, reference: ref)
51
+ end
52
+ @title_column = nil
53
+ ModelBase.config.title_column_candidates.each do |tcc|
54
+ @title_column = cols.detect{|col| tcc === col.name}
55
+ break if @title_column
56
+ end
57
+ @title_column.linkable = true if @title_column
58
+ cols
59
+ end
60
+
61
+ def excluded?(name)
62
+ ModelBase.config.excluded_columns.any?{|c| c === name}
63
+ end
64
+
65
+ def title_column
66
+ retrieve_columns unless defined?(@title_column)
67
+ @title_column
68
+ end
69
+
70
+ def display_columns
71
+ @dispaly_columns ||=
72
+ title_column ? columns : [new_attribute(:id, :integer, true)] + columns
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,13 @@
1
+ require 'model_base'
2
+
3
+ module ModelBase
4
+ class Railtie < Rails::Railtie
5
+
6
+ generators do |g|
7
+ unless ModelBase.config.disabled
8
+ ModelBase.enable!
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module ModelBase
2
+ VERSION = "0.1.0"
3
+ end
data/lib/model_base.rb ADDED
@@ -0,0 +1,28 @@
1
+ require "model_base/version"
2
+
3
+ module ModelBase
4
+
5
+ autoload :ColumnAttribute, 'model_base/column_attribute'
6
+ autoload :Configuration, 'model_base/config'
7
+ autoload :MetaModel , 'model_base/meta_model'
8
+
9
+ class << self
10
+ def configure
11
+ yield config
12
+ end
13
+
14
+ def config
15
+ @config ||= Configuration.new
16
+ end
17
+
18
+ def enable!
19
+ require 'model_base/generators/model_support'
20
+ ::Rails::Generators::NamedBase.prepend(::ModelBase::Generators::ModelSupport)
21
+ templates_dir = File::expand_path('../templates', __FILE__)
22
+ Rails::Generators.templates_path.unshift(templates_dir)
23
+ Rails::Generators.lookup(["rails:scaffold_controller"])
24
+ Rails::Generators::ScaffoldControllerGenerator.source_paths.unshift(templates_dir)
25
+ end
26
+ end
27
+ end
28
+ require 'model_base/railtie' if defined?(Rails)
@@ -0,0 +1,61 @@
1
+ <% if namespaced? -%>
2
+ require_dependency "<%= namespaced_path %>/application_controller"
3
+
4
+ <% end -%>
5
+ <% module_namespacing do -%>
6
+ class <%= controller_class_name %>Controller < ApplicationController
7
+ before_action :set_<%= singular_table_name %>, only: [:show, :update, :destroy]
8
+
9
+ # GET <%= route_url %>
10
+ def index
11
+ @<%= plural_table_name %> = <%= orm_class.all(class_name) %>
12
+
13
+ render json: <%= "@#{plural_table_name}" %>
14
+ end
15
+
16
+ # GET <%= route_url %>/1
17
+ def show
18
+ render json: <%= "@#{singular_table_name}" %>
19
+ end
20
+
21
+ # POST <%= route_url %>
22
+ def create
23
+ @<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
24
+
25
+ if @<%= orm_instance.save %>
26
+ render json: <%= "@#{singular_table_name}" %>, status: :created, location: <%= "@#{singular_table_name}" %>
27
+ else
28
+ render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity
29
+ end
30
+ end
31
+
32
+ # PATCH/PUT <%= route_url %>/1
33
+ def update
34
+ if @<%= orm_instance.update("#{singular_table_name}_params") %>
35
+ render json: <%= "@#{singular_table_name}" %>
36
+ else
37
+ render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity
38
+ end
39
+ end
40
+
41
+ # DELETE <%= route_url %>/1
42
+ def destroy
43
+ @<%= orm_instance.destroy %>
44
+ end
45
+
46
+ private
47
+ # Use callbacks to share common setup or constraints between actions.
48
+ def set_<%= singular_table_name %>
49
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
50
+ end
51
+
52
+ # Only allow a trusted parameter "white list" through.
53
+ def <%= "#{singular_table_name}_params" %>
54
+ <%- if attributes_names.empty? -%>
55
+ params.fetch(:<%= singular_table_name %>, {})
56
+ <%- else -%>
57
+ params.require(:<%= singular_table_name %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
58
+ <%- end -%>
59
+ end
60
+ end
61
+ <% end -%>
@@ -0,0 +1,72 @@
1
+ <% if namespaced? -%>
2
+ require_dependency "<%= namespaced_path %>/application_controller"
3
+
4
+ <% end -%>
5
+ <% module_namespacing do -%>
6
+ class <%= controller_class_name %>Controller < ApplicationController
7
+ include Authentication
8
+ load_and_authorize_resource except: [:index]
9
+
10
+ before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy]
11
+
12
+ # GET <%= route_url %>
13
+ def index
14
+ @<%= plural_table_name %> = <%= orm_class.all(class_name) %>
15
+ end
16
+
17
+ # GET <%= route_url %>/1
18
+ def show
19
+ end
20
+
21
+ # GET <%= route_url %>/new
22
+ def new
23
+ @<%= singular_table_name %> = <%= orm_class.build(class_name) %>
24
+ end
25
+
26
+ # GET <%= route_url %>/1/edit
27
+ def edit
28
+ end
29
+
30
+ # POST <%= route_url %>
31
+ def create
32
+ @<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
33
+
34
+ if @<%= orm_instance.save %>
35
+ redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully created.'" %>
36
+ else
37
+ render :new
38
+ end
39
+ end
40
+
41
+ # PATCH/PUT <%= route_url %>/1
42
+ def update
43
+ if @<%= orm_instance.update("#{singular_table_name}_params") %>
44
+ redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully updated.'" %>
45
+ else
46
+ render :edit
47
+ end
48
+ end
49
+
50
+ # DELETE <%= route_url %>/1
51
+ def destroy
52
+ @<%= orm_instance.destroy %>
53
+ redirect_to <%= index_helper %>_url, notice: <%= "'#{human_name} was successfully destroyed.'" %>
54
+ end
55
+
56
+ private
57
+
58
+ # Use callbacks to share common setup or constraints between actions.
59
+ def set_<%= singular_table_name %>
60
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
61
+ end
62
+
63
+ # Only allow a trusted parameter "white list" through.
64
+ def <%= "#{singular_table_name}_params" %>
65
+ <%- if model.columns.empty? -%>
66
+ params[:<%= singular_table_name %>]
67
+ <%- else -%>
68
+ params.require(:<%= singular_table_name %>).permit(<%= model.columns.map { |c| ":#{c.name}" }.join(', ') %>)
69
+ <%- end -%>
70
+ end
71
+ end
72
+ <% end -%>
@@ -0,0 +1,40 @@
1
+ <%%= form_for <%= model.full_resource_name %>, :html => { :class => "form-horizontal <%= model.full_resource_name %>" } do |f| %>
2
+
3
+ <%% if <%= model.full_resource_name %>.errors.any? %>
4
+ <div id="error_expl" class="panel panel-danger">
5
+ <div class="panel-heading">
6
+ <h3 class="panel-title"><%%= pluralize(<%= model.full_resource_name %>.errors.count, "error") %> prohibited this <%= model.full_resource_name %> from being saved:</h3>
7
+ </div>
8
+ <div class="panel-body">
9
+ <ul>
10
+ <%% <%= model.full_resource_name %>.errors.full_messages.each do |msg| %>
11
+ <li><%%= msg %></li>
12
+ <%% end %>
13
+ </ul>
14
+ </div>
15
+ </div>
16
+ <%% end %>
17
+
18
+ <%- model.columns.each do |column| -%>
19
+ <div class="form-group">
20
+ <%%= f.label :<%= column.name %>, :class => 'control-label col-lg-2' %>
21
+ <div class="col-lg-10">
22
+ <%- if r = column.select_renderer -%>
23
+ <%%= <%= r.render('f', model.full_resource_name, html: {class: 'form-control'}) %> %>
24
+ <%- else -%>
25
+ <%%= f.<%= column.field_type %> :<%= column.name %>, :class => 'form-control' %>
26
+ <%- end -%>
27
+ </div>
28
+ <%%=f.error_span(:<%= column.name %>) %>
29
+ </div>
30
+ <%- end -%>
31
+
32
+ <div class="form-group">
33
+ <div class="col-lg-offset-2 col-lg-10">
34
+ <%%= f.submit nil, :class => 'btn btn-primary' %>
35
+ <%%= link_to t('.cancel', :default => t("helpers.links.cancel")),
36
+ <%= controller_routing_path %>_path, :class => 'btn btn-default' %>
37
+ </div>
38
+ </div>
39
+
40
+ <%% end %>