conjoin 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,97 @@
1
+ require 'r18n-core'
2
+
3
+ # https://github.com/ai/r18n
4
+ module Conjoin
5
+ module I18N
6
+ include R18n::Helpers
7
+
8
+ def self.setup(app)
9
+ app.settings[:default_locale] = 'en-US'
10
+ app.settings[:translations] = File.join(app.root, 'i18n')
11
+ ::R18n::Filters.off :untranslated
12
+ ::R18n::Filters.on :untranslated_html
13
+ if Conjoin.env.test? or Conjoin.env.development?
14
+ ::R18n.clear_cache!
15
+ end
16
+ end
17
+
18
+ def set_locale(req, force_default = false)
19
+ ::R18n.set do
20
+ ::R18n::I18n.default = settings[:default_locale]
21
+ locale = get_locale_from_host
22
+ # You can add support for path language info :) Just do it and pull request it ;)
23
+ # locale = get_locale_from_path if locale.nil?
24
+ if locale.nil? and not force_default
25
+ locales = ::R18n::I18n.parse_http req.env['HTTP_ACCEPT_LANGUAGE']
26
+ if req.params['locale']
27
+ locales.insert 0, req.params['locale']
28
+ elsif req.session['locale']
29
+ locales.insert 0, req.session['locale']
30
+ end
31
+ else
32
+ locales = []
33
+ locales << locale
34
+ locales << settings[:default_locale]
35
+ end
36
+ ::R18n::I18n.new locales, settings[:translations]
37
+ end
38
+ end
39
+
40
+ def get_locale_from_host
41
+ # auxiliar method to get locale from the subdomain (assuming it is a valid locale).
42
+ data = req.host.split('.')[0]
43
+ data if ::R18n::Locale.exists? data
44
+ end
45
+ end
46
+ end
47
+
48
+ module R18n
49
+ class << self
50
+ def t(*params)
51
+ if params.first.is_a? String
52
+ params.first.split('.').inject(get.t) { |h, k| h[k.to_sym] }
53
+ else
54
+ get.t(*params)
55
+ end
56
+ end
57
+ end
58
+
59
+ # Override
60
+ # https://github.com/ai/r18n/blob/master/r18n-core/lib/r18n-core/locale.rb#L152
61
+ class Locale
62
+ # Convert +object+ to String. It support Fixnum, Bignum, Float, Time, Date
63
+ # and DateTime.
64
+ #
65
+ # For time classes you can set +format+ in standard +strftime+ form,
66
+ # <tt>:full</tt> (“01 Jule, 2009”), <tt>:human</tt> (“yesterday”),
67
+ # <tt>:standard</tt> (“07/01/09”) or <tt>:month</tt> for standalone month
68
+ # name. Default format is <tt>:standard</tt>.
69
+ def localize(obj, format = nil, *params)
70
+ case obj
71
+ when Integer
72
+ format_integer(obj)
73
+ when Float, BigDecimal
74
+ format_float(obj.to_f)
75
+ when Time, DateTime, Date
76
+ return strftime(obj, format) if format.is_a? String
77
+ return month_standalone[obj.month - 1] if :month == format
78
+ return obj.to_s if :human == format and not params.first.is_a? I18n
79
+
80
+ type = obj.is_a?(Date) ? 'date' : 'time'
81
+ format = :standard unless format
82
+
83
+ unless respond_to? "format_#{type}_#{format}"
84
+ raise ArgumentError, "Unknown time formatter #{format}"
85
+ end
86
+
87
+ send "format_#{type}_#{format}", obj, *params
88
+ else
89
+ obj.to_s
90
+ end
91
+ end
92
+
93
+ def format_time_time time, *params
94
+ format_time(time)[1..-1]
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,8 @@
1
+ require_relative 'radio'
2
+
3
+ module Conjoin
4
+ module FormBuilder
5
+ class BooleanInput < RadioInput
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class CheckboxInput < Input
4
+ def display
5
+ options[:value] = 'on' if data.value == true
6
+ options[:checked] = 'checked' if data.value
7
+ options[:type] = :checkbox
8
+ options[:class].gsub!(/form-control/, '')
9
+
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class DateInput < Input
4
+ def display
5
+ options[:date] = true
6
+ options[:value] = R18n.l options[:value]
7
+ super
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class DecimalInput < Input
4
+ def display
5
+ super
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class FileInput < Input
4
+ def display
5
+ key = options[:s3_upload_path].call(record)
6
+
7
+ mab do
8
+ unless options[:value]
9
+ div id: id, name: options[:name], class: 'file s3-uploader', value: options[:value]
10
+ end
11
+ input id: id, type: :hidden, name: options[:name], class: 'form-control file s3-uploader', value: options[:value]
12
+ text! S3Uploader.js_button(id, key, options[:callback_url], options[:callback_params])
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class HiddenInput < Input
4
+ def display
5
+ options[:type] = :hidden
6
+ super
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class IntegerInput < Input
4
+ def display
5
+ super
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class PasswordInput < Input
4
+ def display
5
+ options[:type] = :password
6
+ super
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class RadioInput < Input
4
+ def display
5
+ options[:type] = :radio
6
+ options[:class].gsub!(/form-control/, '')
7
+
8
+ radios = options[:radios] || [:yes, :no]
9
+
10
+ opts = options.dup
11
+
12
+ mab do
13
+ div class: 'form-control' do
14
+ radios.each_with_index do |name, i|
15
+ name = name.to_s
16
+ opts[:value] = name
17
+ opts[:id] = "#{options[:id]}_#{i}"
18
+
19
+ if (opts[:value] == 'no' and data.value == false) \
20
+ or (opts[:value] == 'yes' and data.value == true) \
21
+ or (opts[:value] == data.value)
22
+ opts[:checked] = 'checked'
23
+ else
24
+ opts.delete :checked
25
+ end
26
+
27
+ input opts
28
+ span name.humanize
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,67 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class SelectInput < Input
4
+ @select_options = {}
5
+
6
+ def display
7
+ mab do
8
+ # automatically add a prompt by default
9
+ options[:prompt] = true unless options.key? :prompt
10
+ options[:class] += ' select2'
11
+ selected_value = options.delete :value
12
+
13
+ select options do
14
+ if prompt = options.delete(:prompt)
15
+ opts = {
16
+ value: ''
17
+ }
18
+ opts['selected'] = 'selected' unless selected_value
19
+ option opts do
20
+ text prompt.to_s == 'true' ? 'Please Choose One.' : prompt
21
+ end
22
+ end
23
+
24
+ if not options[:group]
25
+ select_options.each do |name, value|
26
+ option render_opts(value, selected_value, opts) do
27
+ text name.titleize
28
+ end
29
+ end
30
+ else
31
+ select_options.each do |group_select, group|
32
+ optgroup label: group.to_s.titleize do
33
+ group_select.each do |value, name|
34
+ option render_opts(value, selected_value, opts) do
35
+ text name.titleize
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ def render_opts value, selected_value, opts
46
+ opts = {
47
+ value: value
48
+ }
49
+ if selected_value.is_a? ActiveRecord::Associations::CollectionProxy
50
+ opts['selected'] = 'selected' if selected_value.map(&:id).include? value
51
+ else
52
+ opts['selected'] = 'selected' if selected_value == value.to_s
53
+ end
54
+
55
+ opts
56
+ end
57
+
58
+ def self.select_options
59
+ @select_options
60
+ end
61
+
62
+ def select_options
63
+ self.class.select_options.invert
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,68 @@
1
+ require_relative 'select'
2
+
3
+ module Conjoin
4
+ module FormBuilder
5
+ class StateInput < SelectInput
6
+ @select_options = {
7
+ 'AL' => 'Alabama',
8
+ 'AK' => 'Alaska',
9
+ 'AS' => 'America Samoa',
10
+ 'AZ' => 'Arizona',
11
+ 'AR' => 'Arkansas',
12
+ 'CA' => 'California',
13
+ 'CO' => 'Colorado',
14
+ 'CT' => 'Connecticut',
15
+ 'DE' => 'Delaware',
16
+ 'DC' => 'District of Columbia',
17
+ 'FM' => 'Micronesia',
18
+ 'FL' => 'Florida',
19
+ 'GA' => 'Georgia',
20
+ 'GU' => 'Guam',
21
+ 'HI' => 'Hawaii',
22
+ 'ID' => 'Idaho',
23
+ 'IL' => 'Illinois',
24
+ 'IN' => 'Indiana',
25
+ 'IA' => 'Iowa',
26
+ 'KS' => 'Kansas',
27
+ 'KY' => 'Kentucky',
28
+ 'LA' => 'Louisiana',
29
+ 'ME' => 'Maine',
30
+ 'MH' => 'Islands',
31
+ 'MD' => 'Maryland',
32
+ 'MA' => 'Massachusetts',
33
+ 'MI' => 'Michigan',
34
+ 'MN' => 'Minnesota',
35
+ 'MS' => 'Mississippi',
36
+ 'MO' => 'Missouri',
37
+ 'MT' => 'Montana',
38
+ 'NE' => 'Nebraska',
39
+ 'NV' => 'Nevada',
40
+ 'NH' => 'New Hampshire',
41
+ 'NJ' => 'New Jersey',
42
+ 'NM' => 'New Mexico',
43
+ 'NY' => 'New York',
44
+ 'NC' => 'North Carolina',
45
+ 'ND' => 'North Dakota',
46
+ 'OH' => 'Ohio',
47
+ 'OK' => 'Oklahoma',
48
+ 'OR' => 'Oregon',
49
+ 'PW' => 'Palau',
50
+ 'PA' => 'Pennsylvania',
51
+ 'PR' => 'Puerto Rico',
52
+ 'RI' => 'Rhode Island',
53
+ 'SC' => 'South Carolina',
54
+ 'SD' => 'South Dakota',
55
+ 'TN' => 'Tennessee',
56
+ 'TX' => 'Texas',
57
+ 'UT' => 'Utah',
58
+ 'VT' => 'Vermont',
59
+ 'VI' => 'Virgin Island',
60
+ 'VA' => 'Virginia',
61
+ 'WA' => 'Washington',
62
+ 'WV' => 'West Virginia',
63
+ 'WI' => 'Wisconsin',
64
+ 'WY' => 'Wyoming'
65
+ }
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,9 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class StringInput < Input
4
+ def display
5
+ super
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Conjoin
2
+ module FormBuilder
3
+ class TimeInput < Input
4
+ def display
5
+ options[:time] = true
6
+ options[:value] = app.l options[:value], :time
7
+ super
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,40 @@
1
+ require "rack/protection"
2
+
3
+ module Conjoin
4
+ class Middleware
5
+ class << self
6
+ # taken from
7
+ # https://github.com/rkh/rack-protection/blob/master/lib/rack/protection.rb#L20
8
+ def new app, options = {}
9
+ # except = Array options[:except]
10
+ # use_these = Array options[:use]
11
+ Rack::Builder.new do
12
+ if not Conjoin.env.mounted?
13
+ use Rack::Session::Cookie, secret: ENV['SECRET_BASE_KEY']
14
+ end
15
+ # we need to disable session_hijacking because IE uses different headers
16
+ # for ajax request over standard ones.
17
+ # https://github.com/rkh/rack-protection/issues/11#issuecomment-9005539
18
+ use Rack::Protection, except: :session_hijacking
19
+
20
+ if not Conjoin.env.mounted? and Conjoin.env.development?
21
+ require 'rack-livereload'
22
+ use Rack::LiveReload
23
+ use Rack::Reloader
24
+ end
25
+
26
+ if Conjoin.env.test? or Conjoin.env.development?
27
+ require 'better_errors'
28
+ use BetterErrors::Middleware
29
+ # require 'pry'
30
+ # require 'pry-rescue'
31
+ # use PryRescue::Rack
32
+ end
33
+
34
+ # continue running the application
35
+ run app
36
+ end.to_app
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,117 @@
1
+ # https://gist.github.com/rmw/2710460
2
+ require 'hashie'
3
+
4
+ class Hash
5
+ # options:
6
+ # :exclude => [keys] - keys need to be symbols
7
+ def to_ostruct(options = {})
8
+ convert_to_ostruct_recursive(self, options)
9
+ end
10
+
11
+ def with_sym_keys
12
+ # self.inject({}) { |memo, (k,v)| memo[k.to_sym] = v; memo }
13
+ self.each_with_object({}) { |(k,v), memo| memo[k.to_sym] = v }
14
+ end
15
+
16
+ private
17
+
18
+ def convert_to_ostruct_recursive(obj, options)
19
+ result = obj
20
+ if result.is_a? Hash
21
+ result = result.dup.with_sym_keys
22
+ result.each do |key, val|
23
+ result[key] = convert_to_ostruct_recursive(val, options) unless options[:exclude].try(:include?, key)
24
+ end
25
+ result = OpenStruct.new result
26
+ elsif result.is_a? Array
27
+ result = result.map { |r| convert_to_ostruct_recursive(r, options) }
28
+ end
29
+ return result
30
+ end
31
+ end
32
+
33
+ class HashIndifferent < Hash
34
+ include Hashie::Extensions::MergeInitializer
35
+ include Hashie::Extensions::IndifferentAccess
36
+ end
37
+
38
+ class OpenStruct
39
+ def to_hash options = {}
40
+ convert_to_hash_recursive(self, options)
41
+ end
42
+
43
+ private
44
+
45
+ def convert_to_hash_recursive(obj, options)
46
+ result = obj
47
+ if result.is_a? OpenStruct
48
+ result = result.dup.to_h.with_sym_keys
49
+ result.each do |key, val|
50
+ result[key] = convert_to_hash_recursive(val, options) unless options[:exclude].try(:include?, key)
51
+ end
52
+ result = HashIndifferent.new result
53
+ elsif result.is_a? Array
54
+ result = result.map { |r| convert_to_hash_recursive(r, options) }
55
+ end
56
+ return result
57
+ end
58
+ end
59
+
60
+ # require 'spec_helper'
61
+ #
62
+ # describe Hash do
63
+ #
64
+ # describe "#to_ostruct_recursive" do
65
+ # describe "replace a nested hash" do
66
+ # before do
67
+ # @h = { :a => { :b => { :c => 1 } } }
68
+ # @o = @h.to_ostruct_recursive
69
+ # end
70
+ # it "should be an OpenStruct" do
71
+ # @o.is_a?(OpenStruct).should be_true
72
+ # end
73
+ # it "should have a nested OpenStruct" do
74
+ # @o.a.should be
75
+ # @o.a.is_a?(OpenStruct).should be_true
76
+ # end
77
+ # it "should have a nested nested OpenStruct" do
78
+ # @o.a.b.should be
79
+ # @o.a.b.is_a?(OpenStruct).should be_true
80
+ # end
81
+ # it "should have a nested nested nested value of 1" do
82
+ # @o.a.b.c.should be
83
+ # @o.a.b.c.should == 1
84
+ # end
85
+ # describe "exclude a key from being converted to an OpenStruct" do
86
+ # before do
87
+ # @o_exclude = @h.to_ostruct_recursive({ :exclude => [:b] })
88
+ # end
89
+ # it "should be an OpenStruct" do
90
+ # @o.is_a?(OpenStruct).should be_true
91
+ # end
92
+ # it "should have a nested OpenStruct" do
93
+ # @o.a.is_a?(OpenStruct).should be_true
94
+ # end
95
+ # it "should have a nested nested Hash" do
96
+ # @o_exclude.a.b.is_a?(Hash).should be_true
97
+ # @o_exclude.a.b.should == { :c => 1 }
98
+ # end
99
+ # end
100
+ # end
101
+ # describe "replace a nest hash in an array" do
102
+ # before do
103
+ # @h = { :a => [ {:a1 => 1 } ] }
104
+ # @o = @h.to_ostruct_recursive
105
+ # end
106
+ # it "should be an OpenStruct" do
107
+ # @o.is_a?(OpenStruct).should be_true
108
+ # end
109
+ # it "should have an array with 1 struct" do
110
+ # @o.a.is_a?(Array).should be_true
111
+ # @o.a.size.should == 1
112
+ # @o.a.first.is_a?(OpenStruct).should be_true
113
+ # @o.a.first.a1.should == 1
114
+ # end
115
+ # end
116
+ # end
117
+ # end