Module: Brick
- Defined in:
- lib/brick/util.rb,
lib/brick/config.rb,
lib/brick/join_array.rb,
lib/brick/version_number.rb,
lib/brick/serializers/json.rb,
lib/brick/serializers/yaml.rb,
lib/brick/frameworks/cucumber.rb,
lib/brick/frameworks/rails/engine.rb,
lib/generators/brick/model_generator.rb,
lib/brick/frameworks/rails/controller.rb,
lib/generators/brick/install_generator.rb,
lib/brick/extensions.rb,
lib/brick.rb
Overview
:nodoc:
Defined Under Namespace
Modules: Cucumber, Extensions, Rails, RouteSet, Serializers, Util, VERSION Classes: Config, InstallGenerator, JoinArray, JoinHash, ModelGenerator
Class Attribute Summary collapse
-
.db_schemas ⇒ Object
Returns the value of attribute db_schemas.
Class Method Summary collapse
- ._add_bt_and_hm(fk, relations = nil) ⇒ Object
-
.additional_references=(ars) ⇒ Object
Additional table associations to use (Think of these as virtual foreign keys perhaps).
-
.config {|@config| ... } ⇒ Object
(also: configure)
private
Returns Brick’s global configuration object, a singleton.
-
.enable_controllers=(value) ⇒ Object
Switches Brick auto-controllers on or off, for all threads.
-
.enable_controllers? ⇒ Boolean
Returns ‘true` if Brick controllers are on, `false` otherwise.
-
.enable_models=(value) ⇒ Object
Switches Brick auto-models on or off, for all threads.
-
.enable_models? ⇒ Boolean
Returns ‘true` if Brick models are on, `false` otherwise.
-
.enable_routes=(value) ⇒ Object
Switches Brick auto-routes on or off, for all threads.
-
.enable_routes? ⇒ Boolean
Returns ‘true` if Brick routes are on, `false` otherwise.
-
.enable_views=(value) ⇒ Object
Switches Brick auto-views on or off, for all threads.
-
.enable_views? ⇒ Boolean
Returns ‘true` if Brick views are on, `false` otherwise.
-
.exclude_hms=(skips) ⇒ Object
Skip creating a has_many association for these (Uses the same exact three-part format as would define an additional_reference).
- .exclude_tables=(value) ⇒ Object
-
.gem_version ⇒ Object
Returns Brick’s ‘::Gem::Version`, convenient for comparisons.
- .get_bts_and_hms(model) ⇒ Object
-
.has_ones=(hos) ⇒ Object
Associations to treat as a has_one.
-
.load_additional_references ⇒ Object
Load additional references (virtual foreign keys) This is attempted early if a brick initialiser file is found, and then again as a failsafe at the end of our engine’s initialisation %%% Maybe look for differences the second time ‘round and just add new stuff instead of entirely deferring.
- .metadata_columns=(value) ⇒ Object
-
.model_descrips=(descrips) ⇒ Object
DSL templates for individual models to provide prettier descriptions of objects.
- .models_inherit_from=(value) ⇒ Object
- .not_nullables=(value) ⇒ Object
-
.relations ⇒ Object
All tables and views (what Postgres calls “relations” including column and foreign key info).
-
.serializer ⇒ Object
Get the Brick serializer used by all threads.
-
.serializer=(value) ⇒ Object
Set the Brick serializer.
- .set_db_schema(params) ⇒ Object
- .skip_database_views=(value) ⇒ Object
-
.skip_index_hms=(value) ⇒ Object
Skip showing counts for these specific has_many associations when building auto-generated #index views.
- .sti_models ⇒ Object
-
.sti_namespace_prefixes=(snp) ⇒ Object
Module prefixes to build out and associate with specific base STI models.
- .table_name_prefixes=(value) ⇒ Object
- .version ⇒ Object
Class Attribute Details
.db_schemas ⇒ Object
Returns the value of attribute db_schemas.
89 90 91 |
# File 'lib/brick.rb', line 89 def db_schemas @db_schemas end |
Class Method Details
._add_bt_and_hm(fk, relations = nil) ⇒ Object
941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 |
# File 'lib/brick/extensions.rb', line 941 def _add_bt_and_hm(fk, relations = nil) relations ||= ::Brick.relations bt_assoc_name = fk[1].underscore bt_assoc_name = bt_assoc_name[0..-4] if bt_assoc_name.end_with?('_id') bts = (relation = relations.fetch(fk[0], nil))&.fetch(:fks) { relation[:fks] = {} } primary_table = (is_class = fk[2].is_a?(Hash) && fk[2].key?(:class)) ? (primary_class = fk[2][:class].constantize).table_name : fk[2] hms = (relation = relations.fetch(primary_table, nil))&.fetch(:fks) { relation[:fks] = {} } unless is_class unless (cnstr_name = fk[3]) # For any appended references (those that come from config), arrive upon a definitely unique constraint name cnstr_base = cnstr_name = "(brick) #{fk[0]}_#{is_class ? fk[2][:class].underscore : fk[2]}" cnstr_added_num = 1 cnstr_name = "#{cnstr_base}_#{cnstr_added_num += 1}" while bts&.key?(cnstr_name) || hms&.key?(cnstr_name) missing = [] missing << fk[0] unless relations.key?(fk[0]) missing << primary_table unless is_class || relations.key?(primary_table) unless missing.empty? tables = relations.reject { |_k, v| v.fetch(:isView, nil) }.keys.sort puts "Brick: Additional reference #{fk.inspect} refers to non-existent #{'table'.pluralize(missing.length)} #{missing.join(' and ')}. (Available tables include #{tables.join(', ')}.)" return end unless (cols = relations[fk[0]][:cols]).key?(fk[1]) columns = cols.map { |k, v| "#{k} (#{v.first.split(' ').first})" } puts "Brick: Additional reference #{fk.inspect} refers to non-existent column #{fk[1]}. (Columns present in #{fk[0]} are #{columns.join(', ')}.)" return end if (redundant = bts.find { |_k, v| v[:inverse]&.fetch(:inverse_table, nil) == fk[0] && v[:fk] == fk[1] && v[:inverse_table] == primary_table }) if is_class && !redundant.last.key?(:class) redundant.last[:primary_class] = primary_class # Round out this BT so it can find the proper :source for a HMT association that references an STI subclass else puts "Brick: Additional reference #{fk.inspect} is redundant and can be removed. (Already established by #{redundant.first}.)" end return end end if (assoc_bt = bts[cnstr_name]) assoc_bt[:fk] = assoc_bt[:fk].is_a?(String) ? [assoc_bt[:fk], fk[1]] : assoc_bt[:fk].concat(fk[1]) assoc_bt[:assoc_name] = "#{assoc_bt[:assoc_name]}_#{fk[1]}" else assoc_bt = bts[cnstr_name] = { is_bt: true, fk: fk[1], assoc_name: bt_assoc_name, inverse_table: primary_table } end if is_class # For use in finding the proper :source for a HMT association that references an STI subclass assoc_bt[:primary_class] = primary_class # For use in finding the proper :inverse_of for a BT association that references an STI subclass # assoc_bt[:inverse_of] = primary_class.reflect_on_all_associations.find { |a| a.foreign_key == bt[1] } end return if is_class || ::Brick.config.exclude_hms&.any? { |exclusion| fk[0] == exclusion[0] && fk[1] == exclusion[1] && primary_table == exclusion[2] } cnstr_name = "hm_#{cnstr_name}" if (assoc_hm = hms.fetch(cnstr_name, nil)) assoc_hm[:fk] = assoc_hm[:fk].is_a?(String) ? [assoc_hm[:fk], fk[1]] : assoc_hm[:fk].concat(fk[1]) assoc_hm[:alternate_name] = "#{assoc_hm[:alternate_name]}_#{bt_assoc_name}" unless assoc_hm[:alternate_name] == bt_assoc_name assoc_hm[:inverse] = assoc_bt else assoc_hm = hms[cnstr_name] = { is_bt: false, fk: fk[1], assoc_name: fk[0], alternate_name: bt_assoc_name, inverse_table: fk[0], inverse: assoc_bt } hm_counts = relation.fetch(:hm_counts) { relation[:hm_counts] = {} } hm_counts[fk[0]] = hm_counts.fetch(fk[0]) { 0 } + 1 end assoc_bt[:inverse] = assoc_hm # hms[cnstr_name] << { is_bt: false, fk: fk[1], assoc_name: fk[0], alternate_name: bt_assoc_name, inverse_table: fk[0] } end |
.additional_references=(ars) ⇒ Object
Additional table associations to use (Think of these as virtual foreign keys perhaps)
222 223 224 225 226 227 228 229 |
# File 'lib/brick.rb', line 222 def additional_references=(ars) if ars ars = ars.call if ars.is_a?(Proc) ars = ars.to_a unless ars.is_a?(Array) ars = [ars] unless ars.empty? || ars.first.is_a?(Array) Brick.config.additional_references = ars end end |
.config {|@config| ... } ⇒ Object Also known as: configure
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns Brick’s global configuration object, a singleton. These settings affect all threads.
323 324 325 326 327 |
# File 'lib/brick.rb', line 323 def config @config ||= Brick::Config.instance yield @config if block_given? @config end |
.enable_controllers=(value) ⇒ Object
Switches Brick auto-controllers on or off, for all threads
153 154 155 |
# File 'lib/brick.rb', line 153 def enable_controllers=(value) Brick.config.enable_controllers = value end |
.enable_controllers? ⇒ Boolean
Returns ‘true` if Brick controllers are on, `false` otherwise. This affects all threads. Enabled by default.
160 161 162 |
# File 'lib/brick.rb', line 160 def enable_controllers? !!Brick.config.enable_controllers end |
.enable_models=(value) ⇒ Object
Switches Brick auto-models on or off, for all threads
140 141 142 |
# File 'lib/brick.rb', line 140 def enable_models=(value) Brick.config.enable_models = value end |
.enable_models? ⇒ Boolean
Returns ‘true` if Brick models are on, `false` otherwise. This affects all threads. Enabled by default.
147 148 149 |
# File 'lib/brick.rb', line 147 def enable_models? !!Brick.config.enable_models end |
.enable_routes=(value) ⇒ Object
Switches Brick auto-routes on or off, for all threads
179 180 181 |
# File 'lib/brick.rb', line 179 def enable_routes=(value) Brick.config.enable_routes = value end |
.enable_routes? ⇒ Boolean
Returns ‘true` if Brick routes are on, `false` otherwise. This affects all threads. Enabled by default.
186 187 188 |
# File 'lib/brick.rb', line 186 def enable_routes? !!Brick.config.enable_routes end |
.enable_views=(value) ⇒ Object
Switches Brick auto-views on or off, for all threads
166 167 168 |
# File 'lib/brick.rb', line 166 def enable_views=(value) Brick.config.enable_views = value end |
.enable_views? ⇒ Boolean
Returns ‘true` if Brick views are on, `false` otherwise. This affects all threads. Enabled by default.
173 174 175 |
# File 'lib/brick.rb', line 173 def enable_views? !!Brick.config.enable_views end |
.exclude_hms=(skips) ⇒ Object
Skip creating a has_many association for these (Uses the same exact three-part format as would define an additional_reference)
234 235 236 237 238 239 240 241 |
# File 'lib/brick.rb', line 234 def exclude_hms=(skips) if skips skips = skips.call if skips.is_a?(Proc) skips = skips.to_a unless skips.is_a?(Array) skips = [skips] unless skips.empty? || skips.first.is_a?(Array) Brick.config.exclude_hms = skips end end |
.exclude_tables=(value) ⇒ Object
196 197 198 |
# File 'lib/brick.rb', line 196 def exclude_tables=(value) Brick.config.exclude_tables = value end |
.gem_version ⇒ Object
Returns Brick’s ‘::Gem::Version`, convenient for comparisons. This is recommended over `::Brick::VERSION::STRING`.
304 305 306 |
# File 'lib/brick.rb', line 304 def gem_version ::Gem::Version.new(VERSION::STRING) end |
.get_bts_and_hms(model) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/brick.rb', line 104 def get_bts_and_hms(model) bts, hms = model.reflect_on_all_associations.each_with_object([{}, {}]) do |a, s| next if !const_defined?(a.name.to_s.singularize.camelize) && ::Brick.config.exclude_tables.include?(a.plural_name) # So that we can map an association name to any special alias name used in an AREL query ans = (model._assoc_names[a.name] ||= []) ans << a.klass unless ans.include?(a.klass) case a.macro when :belongs_to s.first[a.foreign_key] = [a.name, a.klass] when :has_many, :has_one # This gets has_many as well as has_many :through # %%% weed out ones that don't have an available model to reference s.last[a.name] = a end end # Mark has_manys that go to an associative ("join") table so that they are skipped in the UI, # as well as any possible polymorphic associations skip_hms = {} associatives = hms.each_with_object({}) do |hmt, s| if (through = hmt.last.[:through]) skip_hms[through] = nil s[hmt.first] = hms[through] # End up with a hash of HMT names pointing to join-table associations elsif hmt.last.inverse_of.nil? puts "SKIPPING #{hmt.last.name.inspect}" # %%% If we don't do this then below associative.name will find that associative is nil skip_hms[hmt.last.name] = nil end end skip_hms.each do |k, _v| puts hms.delete(k).inspect end [bts, hms, associatives] end |
.has_ones=(hos) ⇒ Object
Associations to treat as a has_one
251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/brick.rb', line 251 def has_ones=(hos) if hos hos = hos.call if hos.is_a?(Proc) hos = hos.to_a unless hos.is_a?(Array) hos = [hos] unless hos.empty? || hos.first.is_a?(Array) # Translate to being nested hashes Brick.config.has_ones = hos&.each_with_object(Hash.new { |h, k| h[k] = {} }) do |v, s| s[v.first][v[1]] = v[2] if v[1] s end end end |
.load_additional_references ⇒ Object
Load additional references (virtual foreign keys) This is attempted early if a brick initialiser file is found, and then again as a failsafe at the end of our engine’s initialisation %%% Maybe look for differences the second time ‘round and just add new stuff instead of entirely deferring
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/brick.rb', line 279 def load_additional_references return if @_additional_references_loaded if (ars = ::Brick.config.additional_references) ars.each { |fk| ::Brick._add_bt_and_hm(fk[0..2]) } @_additional_references_loaded = true end # Find associative tables that can be set up for has_many :through ::Brick.relations.each do |_key, tbl| tbl_cols = tbl[:cols].keys fks = tbl[:fks].each_with_object({}) { |fk, s| s[fk.last[:fk]] = [fk.last[:assoc_name], fk.last[:inverse_table]] if fk.last[:is_bt]; s } # Aside from the primary key and the metadata columns created_at, updated_at, and deleted_at, if this table only has # foreign keys then it can act as an associative table and thus be used with has_many :through. if fks.length > 1 && (tbl_cols - fks.keys - (::Brick.config. || []) - (tbl[:pkey].values.first || [])).length.zero? fks.each { |fk| tbl[:hmt_fks][fk.first] = fk.last } end end end |
.metadata_columns=(value) ⇒ Object
211 212 213 |
# File 'lib/brick.rb', line 211 def (value) Brick.config. = value end |
.model_descrips=(descrips) ⇒ Object
DSL templates for individual models to provide prettier descriptions of objects
266 267 268 |
# File 'lib/brick.rb', line 266 def model_descrips=(descrips) Brick.config.model_descrips = descrips end |
.models_inherit_from=(value) ⇒ Object
201 202 203 |
# File 'lib/brick.rb', line 201 def models_inherit_from=(value) Brick.config.models_inherit_from = value end |
.not_nullables=(value) ⇒ Object
216 217 218 |
# File 'lib/brick.rb', line 216 def not_nullables=(value) Brick.config.not_nullables = value end |
.relations ⇒ Object
All tables and views (what Postgres calls “relations” including column and foreign key info)
97 98 99 100 101 102 |
# File 'lib/brick.rb', line 97 def relations connections = Brick.instance_variable_get(:@relations) || Brick.instance_variable_set(:@relations, (connections = {})) # Key our list of relations for this connection off of the connection pool's object_id (connections[ActiveRecord::Base.connection_pool.object_id] ||= Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = {} } }) end |
.serializer ⇒ Object
Get the Brick serializer used by all threads.
316 317 318 |
# File 'lib/brick.rb', line 316 def serializer Brick.config.serializer end |
.serializer=(value) ⇒ Object
Set the Brick serializer. This setting affects all threads.
310 311 312 |
# File 'lib/brick.rb', line 310 def serializer=(value) Brick.config.serializer = value end |
.set_db_schema(params) ⇒ Object
91 92 93 94 |
# File 'lib/brick.rb', line 91 def set_db_schema(params) schema = params['_brick_schema'] || 'public' ActiveRecord::Base.connection.execute("SET SEARCH_PATH='#{schema}';") if schema && ::Brick.db_schemas&.include?(schema) end |
.skip_database_views=(value) ⇒ Object
191 192 193 |
# File 'lib/brick.rb', line 191 def skip_database_views=(value) Brick.config.skip_database_views = value end |
.skip_index_hms=(value) ⇒ Object
Skip showing counts for these specific has_many associations when building auto-generated #index views
245 246 247 |
# File 'lib/brick.rb', line 245 def skip_index_hms=(value) Brick.config.skip_index_hms = value end |
.sti_models ⇒ Object
84 85 86 |
# File 'lib/brick.rb', line 84 def self.sti_models @sti_models ||= {} end |
.sti_namespace_prefixes=(snp) ⇒ Object
Module prefixes to build out and associate with specific base STI models
272 273 274 |
# File 'lib/brick.rb', line 272 def sti_namespace_prefixes=(snp) Brick.config.sti_namespace_prefixes = snp end |