Skip to content

Instantly share code, notes, and snippets.

@0xDing
Created January 4, 2017 14:57
Show Gist options
  • Save 0xDing/dd46ba1f8422974141a2661cee8c9536 to your computer and use it in GitHub Desktop.
Save 0xDing/dd46ba1f8422974141a2661cee8c9536 to your computer and use it in GitHub Desktop.
Rails FormBuilder @ Gridforms
<%= lud_gridforms_for(@organization) do |f| %>
<%= f.row_for do %>
<%= f.text_field :name %>
<%= f.text_field :alias %>
<%= f.spec_info_select :characteristics, {span: 2}, {multiple: true} %>
<% end %>
<%= f.row_for do %>
<%= f.url_field :website %>
<%= f.spec_info_check_boxes :currencies %>
<%= f.spec_info_select :sectors, {span: 2}, {multiple: true} %>
<% end %>
<%= f.row_for span: 2 do %>
<%= f.spec_info_check_boxes :rounds %>
<%= f.spec_info_check_boxes :locations %>
<% end %>
<%= f.row_for span: 1 do %>
<%= f.text_field :address %>
<% end %>
<%= f.row_for span: 1 do %>
<%= f.text_area :intro, row: 5 %>
<% end %>
<% end %>
<form class="grid-form " id="new_organization" action="/organizations" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="authenticity_token" value="Et3W4TPbFztfHjhxmkiZItEDjl81xUtTjrCFYV87Ll82xJOtZW6AKH8t227lIANqf/GfyXBWEhqQGVCJjWUWNg==">
<div data-row-span="4">
<div data-field-span="1"><label for="organization_name">名称</label><input type="text" name="organization[name]" id="organization_name"></div>
<div data-field-span="1"><label for="organization_alias">别名</label><input type="text" name="organization[alias]" id="organization_alias"></div>
<div data-field-span="2"><label for="organization_characteristics">机构特点</label><input name="organization[characteristics][]" type="hidden" value=""><select multiple="" data-toggle="select" name="organization[characteristics][]" id="organization_characteristics" tabindex="-1" class="select2-hidden-accessible" aria-hidden="true"><option value="strategy">战略投资</option>
<option value="ashare">A股上市公司</option>
<option value="oversea">海外上市公司</option>
<option value="oldyuan">老牌人民币</option>
<option value="dollarfund">美元基金</option>
<option value="cutting">新锐基金</option>
<option value="newboard">新三板基金</option>
<option value="industry">产业基金</option>
<option value="unicorn">独角兽</option>
<option value="ownedstate">国有背景</option></select><span class="select2 select2-container select2-container--bootstrap" dir="ltr" style="width: 100%;"><span class="selection"><span class="select2-selection select2-selection--multiple" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="-1"><ul class="select2-selection__rendered"><li class="select2-search select2-search--inline"><input class="select2-search__field" type="search" tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" role="textbox" aria-autocomplete="list" placeholder="" style="width: 0.75em;"></li></ul></span></span><span class="dropdown-wrapper" aria-hidden="true"></span></span></div>
</div>
<div data-row-span="4">
<div data-field-span="1"><label for="organization_website">官网</label><input type="url" name="organization[website]" id="organization_website"></div>
<div data-field-span="1"><label for="organization_currencies">投资币种</label><input type="hidden" name="organization[currencies][]" value=""><label class="form-check-inline" for="organization_currencies_rmb"><input class="form-check-input" type="checkbox" value="rmb" name="organization[currencies][]" id="organization_currencies_rmb">人民币</label><label class="form-check-inline" for="organization_currencies_usd"><input class="form-check-input" type="checkbox" value="usd" name="organization[currencies][]" id="organization_currencies_usd">美元</label></div>
<div data-field-span="2"><label for="organization_sectors">投资领域</label><input name="organization[sectors][]" type="hidden" value=""><select multiple="" data-toggle="select" name="organization[sectors][]" id="organization_sectors" tabindex="-1" class="select2-hidden-accessible" aria-hidden="true"><option value="business_services">企业服务</option>
<option value="recreation">文化娱乐</option>
<option value="media">传媒</option>
<option value="agriculture">农业/农村</option>
<option value="consumer_products">消费升级</option>
<option value="e-commerce">电商</option>
<option value="education">教育</option>
<option value="finance">金融</option>
<option value="gaming">游戏</option>
<option value="hardware">智能硬件</option>
<option value="healthcare">医疗</option>
<option value="house">房产</option>
<option value="logistics">物流</option>
<option value="manufacturing">高科技</option>
<option value="food">本地生活</option>
<option value="sport">体育健身</option>
<option value="social">社交</option>
<option value="lady">女性</option>
<option value="vr_ar">VR/AR</option>
<option value="big_data">大数据</option>
<option value="ai">人工智能</option>
<option value="aboard">出海</option>
<option value="environmental">环境/能源</option>
<option value="insurance">互联网保险</option>
<option value="supply_chain">供应链</option>
<option value="decoration">装修</option>
<option value="recruitment">招聘</option>
<option value="automobile">汽车出行</option>
<option value="wanghong_eco">网红经济</option>
<option value="ad">营销广告</option>
<option value="travel">旅游</option>
<option value="v_sass">垂直SAAS</option>
<option value="tools">工具软件</option></select><span class="select2 select2-container select2-container--bootstrap" dir="ltr" style="width: 100%;"><span class="selection"><span class="select2-selection select2-selection--multiple" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="-1"><ul class="select2-selection__rendered"><li class="select2-search select2-search--inline"><input class="select2-search__field" type="search" tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" role="textbox" aria-autocomplete="list" placeholder="" style="width: 0.75em;"></li></ul></span></span><span class="dropdown-wrapper" aria-hidden="true"></span></span></div>
</div>
<div data-row-span="2">
<div data-field-span="1"><label for="organization_rounds">投资轮次</label><input type="hidden" name="organization[rounds][]" value=""><label class="form-check-inline" for="organization_rounds_angel"><input class="form-check-input" type="checkbox" value="angel" name="organization[rounds][]" id="organization_rounds_angel">天使/种子轮</label><label class="form-check-inline" for="organization_rounds_a"><input class="form-check-input" type="checkbox" value="a" name="organization[rounds][]" id="organization_rounds_a">PreA/A轮</label><label class="form-check-inline" for="organization_rounds_b"><input class="form-check-input" type="checkbox" value="b" name="organization[rounds][]" id="organization_rounds_b">B轮</label><label class="form-check-inline" for="organization_rounds_c"><input class="form-check-input" type="checkbox" value="c" name="organization[rounds][]" id="organization_rounds_c">C轮</label><label class="form-check-inline" for="organization_rounds_c_plus"><input class="form-check-input" type="checkbox" value="c_plus" name="organization[rounds][]" id="organization_rounds_c_plus">D轮及以上</label></div>
<div data-field-span="1"><label for="organization_locations">常驻地区</label><input type="hidden" name="organization[locations][]" value=""><label class="form-check-inline" for="organization_locations_beijing"><input class="form-check-input" type="checkbox" value="beijing" name="organization[locations][]" id="organization_locations_beijing">北京</label><label class="form-check-inline" for="organization_locations_shanghai"><input class="form-check-input" type="checkbox" value="shanghai" name="organization[locations][]" id="organization_locations_shanghai">上海</label><label class="form-check-inline" for="organization_locations_guangzhou"><input class="form-check-input" type="checkbox" value="guangzhou" name="organization[locations][]" id="organization_locations_guangzhou">广州</label><label class="form-check-inline" for="organization_locations_shenzhen"><input class="form-check-input" type="checkbox" value="shenzhen" name="organization[locations][]" id="organization_locations_shenzhen">深圳</label><label class="form-check-inline" for="organization_locations_hangzhou"><input class="form-check-input" type="checkbox" value="hangzhou" name="organization[locations][]" id="organization_locations_hangzhou">杭州</label><label class="form-check-inline" for="organization_locations_other"><input class="form-check-input" type="checkbox" value="other" name="organization[locations][]" id="organization_locations_other">其它地区</label></div>
</div>
<div data-row-span="1">
<div data-field-span="1"><label for="organization_address">总部地址</label><input type="text" name="organization[address]" id="organization_address"></div>
</div>
<div data-row-span="1">
<div data-field-span="1"><label for="organization_intro">简介</label><textarea row="5" name="organization[intro]" id="organization_intro"></textarea></div>
</div>
</form>
class GridformsFormBuilder < ActionView::Helpers::FormBuilder
delegate :content_tag, :concat, to: :@template
# <%= f.text_field :name %>
# <%= f.text_area :name, span: 2 %>
%w(text_field text_area url_field).each do |method_name|
define_method(method_name) do |method, *tag_value|
content_tag(:div, set_column(tag_value)) { label(method) + super(method, *tag_value) }
end
end
# <%= f.collection_check_boxes :rounds, SpecInfo.collection('rounds'), :first, :last %>
# <%= f.collection_radio_buttons :rounds, SpecInfo.collection('rounds'), :first, :last %>
%w(collection_check_boxes collection_radio_buttons).each do |method_name|
collection = (method_name == 'collection_check_boxes' ? :check_box : :radio_button)
# ref: http://v4-alpha.getbootstrap.com/components/forms/#checkboxes-and-radios
block = proc do |b|
b.label(class: 'form-check-inline') { b.send(collection, {class: 'form-check-input'}) + b.text }
end
# tag_value => collection, value_method, text_method, options = {}, html_options = {}
define_method(method_name) do |method, *tag_value|
content_tag(:div, set_column(tag_value[3])) { label(method) + super(method, *tag_value, &block) }
end
end
%w(select collection_select).each do |method_name|
if method_name == 'select'
# tag_value => choices = nil, options = {}, html_options = {}, &block
html_options = 2
options = 1
else
# tag_value => collection, value_method, text_method, options = {}, html_options = {}
html_options =4
options = 3
end
define_method(method_name) do |method, *tag_value|
tag_value[html_options].deep_merge!({data: {toggle: 'select'}})
content_tag(:div, set_column(tag_value[options])) { label(method) + super(method, *tag_value) }
end
end
%w(check_boxes radio_buttons select).each do |collection_type|
define_method("spec_info_#{collection_type}") do |method, options = {}, html_options ={}|
# params => method, collection, value_method, text_method, options = {}, html_options = {}
params=[
method,
SpecInfo.collection(method.to_s),
:first,
:last,
options,
html_options
]
send "collection_#{collection_type}", *params
end
end
#<%= f.row_for do %>
# <%= f.text_field :name %>
# <%= f.text_field :alias %>
# <%= f.select :characteristics, SpecInfo.collection('characteristics'), {span: 2}, {multiple: true} %>
#<% end %>
def row_for(options = {span: 4}, &block)
span = options.delete(:span)
options.deep_merge!({data: {row_span: span}})
content_tag :div, options, &block
end
private
def set_column(object)
{data: {field_span: object&.delete(:span) || 1}}
end
end
def lud_gridforms_for(object, options = {}, &block)
options[:html] ||= {}
options[:html][:class] = "grid-form #{options[:html][:class]}"
options[:builder] = GridformsFormBuilder
form_for(object, options, &block)
end
class SpecInfo
include Singleton
attr_reader :config_file
attr_accessor :spec_hash
class << self
delegate :spec_hash, to: :instance
# scope by dot(.) e.g. rounds.a
def i18n(*key)
opts = key.extract_options! || {}
key = key.compact.map(&:to_s).join('.')
scope = opts.delete(:scope)
key = [scope, key].join('.') if scope
type_key, enum_key = key.split('.')
spec_hash[type_key][enum_key] || opts[:default]
rescue => e
"#{e} spec_info找不到枚举值#{key}"
end
# noinspection RubyResolve
alias t i18n
def enums(key)
return {} if key.blank?
h = instance.fetch(key, {})
h.with_indifferent_access.freeze
end
def collection(key)
enums(key).to_a.freeze
end
def keys(tag)
return [] if tag.blank?
enums(tag).keys.map(&:to_s)
end
def values(tag)
return [] if tag.blank?
enums(tag).values
end
# 返回sample key,行为类似Array#sample
def sample(tag, count = nil)
ks = keys(tag)
count.nil? ? ks.sample : ks.sample(count)
end
## migrate from helpers and concerns
# tag: field round
# key: specification key, eg. rounds
def item(tag, key, opts = nil)
opts ||= {}
opts[:default] ||= tag
{enum: tag, zh_CN: t(key.to_s.pluralize, tag, opts)}
end
# rubocop:disable Style/MethodMissing
def method_missing(method, *args, &blk)
return instance.send(method, *args, &blk) if instance.respond_to?(method)
super
end
end
def initialize
@config_file = Rails.root.join('config', 'spec_info.yml')
@spec_hash = YAML.load(File.read(config_file)).with_indifferent_access
end
def method_missing(method, *args, &blk)
return spec_hash.send(method, *args, &blk) if spec_hash.respond_to?(method)
super
end
# rubocop:enable Style/MethodMissing
end
rounds:
angel: 天使/种子轮
a: PreA/A轮
b: B轮
c: C轮
c_plus: D轮及以上
locations:
beijing: 北京
shanghai: 上海
guangzhou: 广州
shenzhen: 深圳
hangzhou: 杭州
other: 其它地区
currencies:
rmb: 人民币
usd: 美元
characteristics:
strategy: 战略投资
ashare: A股上市公司
oversea: 海外上市公司
oldyuan: 老牌人民币
dollarfund: 美元基金
cutting: 新锐基金
newboard: 新三板基金
industry: 产业基金
unicorn: 独角兽
ownedstate: 国有背景
investor_titles:
partner: 合伙人
managing_director: 董事总经理
executive_director: 董事
vice_president: 副总裁
director: 投资总监
senior_associate: 高级投资经理
associate: 投资经理
analyst: 分析师
sectors:
business_services: 企业服务
recreation: 文化娱乐
media: 传媒
agriculture: 农业/农村
consumer_products: 消费升级
e-commerce: 电商
education: 教育
finance: 金融
gaming: 游戏
hardware: 智能硬件
healthcare: 医疗
house: 房产
logistics: 物流
manufacturing: 高科技
food: 本地生活
sport: 体育健身
social: 社交
lady: 女性
vr_ar: VR/AR
big_data: 大数据
ai: 人工智能
aboard: 出海
environmental: 环境/能源
insurance: 互联网保险
supply_chain: 供应链
decoration: 装修
recruitment: 招聘
automobile: 汽车出行
wanghong_eco: 网红经济
ad: 营销广告
travel: 旅游
v_sass: 垂直SAAS
tools: 工具软件
funding_status:
interesting:
pursue:
hold:
execution:
closing:
closed:
reviewing:
passed:
paid:
voting:
private_marketing:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment