Comments (13)
@DmitryTsepelev so I figured it out. It was pretty straight forward haha
It's the same approach you suggested. Only difference is I didn't override StoreModel module
I suggest you can also add it to the readme as an inheritance feature.
I'll close the issue now. Thanks again!
module ApplicationController
module_function
def helpers
Module.new do
module_function
def exclude_id_from_columns(model)
case model
when "team" then { name: { type: :string }, email: { type: :string } }
when "project" then { name: { type: :string }, client: { type: :string } }
end
end
def get_required_columns_by_validation(model, _type)
{ name: { type: :string } }
end
end
end
end
# app code
class ContentConfiguration
include StoreModel::Model
def self.configure_as(model)
ApplicationController.helpers.exclude_id_from_columns(model).each do |key, value|
attribute key.to_sym, value[:type].to_sym
end
ApplicationController.helpers.get_required_columns_by_validation(model, 'presence').each do |key, value|
validates key.to_sym, presence: true
end
end
end
class ProjectConfiguration < ContentConfiguration
configure_as('project')
end
class TeamConfiguration < ContentConfiguration
configure_as('team')
end
from store_model.
Good to know! I'll be very grateful if you could make a documentation PR with your snippet
from store_model.
Hi @JoeKaldas!
I believe you could do it using a plain Ruby: define a module with a method that initializes the attribute and validations by its name and call this method for each attribute:
module StoreModel
module Model
def attribute(attribute_name, attribute_type)
puts "attribute defined: #{attribute_name} (#{attribute_type})"
end
def validates(attribute_name, options)
puts "validation defined: #{attribute_name} (#{options})"
end
end
end
module SharedAttributeConfig
include StoreModel::Model
def attribute_with_shared_config(attribute_name)
attribute attribute_name, :string
validates attribute_name, presence: true
end
end
class MyModel
extend SharedAttributeConfig
attribute_with_shared_config :first
attribute_with_shared_config :second
end
from store_model.
Thank you for your answer. However I think you misunderstood me, let me explain more.
I have a single table database, called Content and this table has an enum column that tells me the record belongs to which "table". So let's say I have 2 enum keys "team" and "project"
And then a json column in content table that has the columns of each table team/project
So let's say team has name/email (again those are dynamic and could change)
And project has title/client
Let me share a bit of the code. So this is the team's configuration file
I have a json schema that I read from where everything is defined.
So Project's configuration would be exactly the same except that I want to set "model" variable to "project" instead
So I don't want to make another configuration that has exactly the same code, just with "model" variable changed
I just want to have one configuration and pass the model variable to it
I hope it's clear
class TeamConfiguration
model = 'team'
include StoreModel::Model
ApplicationController.helpers.exclude_id_from_columns(model).each do |key, value|
attribute key.to_sym, value[:type].to_sym
end
ApplicationController.helpers.get_required_columns_by_validation(model, 'presence').each do |key, value|
validates key.to_sym, presence: true
end
end
from store_model.
You cannot do it out of the box using the library DSL, but my initial approach still works, you can generate there configuration classes using inheritance/composition and helper method:
# fake code to make it runnable
module StoreModel
module Model
def self.included(base)
base.extend(Module.new do
def attribute(attribute_name, attribute_type)
puts "attribute defined: #{attribute_name} (#{attribute_type})"
end
def validates(attribute_name, options)
puts "validation defined: #{attribute_name} (#{options})"
end
end)
end
end
end
module ApplicationController
module_function
def helpers
Module.new do
module_function
def exclude_id_from_columns(model)
case model
when "team" then { name: { type: :string }, email: { type: :string } }
when "project" then { name: { type: :string }, client: { type: :string } }
end
end
def get_required_columns_by_validation(model, _type)
{ name: { type: :string } }
end
end
end
end
# app code
class ContentConfiguration
include StoreModel::Model
def self.configure_as(model)
ApplicationController.helpers.exclude_id_from_columns(model).each do |key, value|
attribute key.to_sym, value[:type].to_sym
end
ApplicationController.helpers.get_required_columns_by_validation(model, 'presence').each do |key, value|
validates key.to_sym, presence: true
end
end
end
class ProjectConfiguration < ContentConfiguration
configure_as('project')
end
class TeamConfiguration < ContentConfiguration
configure_as('team')
end
from store_model.
Thanks again.
I did the following
- Created a configurations folder under app
- Created 3 files under this folder. One for ContentConfiguration, TeamConfiguration, Project Configuration
- Here is TeamConfiguration for example
class TeamConfiguration < ContentConfiguration
configure_as('team')
end
And I have a team model that inherits from content model and has the following
class Team < Content
attribute :data, TeamConfiguration.to_type
end
But I'm getting following error:
undefined method `type' for TeamConfiguration:Class
Thanks again
from store_model.
Is there a line that calls this #type
method in the stacktrace?
from store_model.
Log doesn't say anything. Just this
But the puts for attributes and validations are printed
NoMethodError (undefined method `to_type' for TeamConfiguration:Class):
from store_model.
Looks like I figured it out, the only change is in the ContentConfiguration
class (see the comment):
# fake code to make it runnable
module StoreModel
module Model
def self.included(base)
base.include(Module.new do
def attribute(attribute_name, attribute_type)
puts "attribute defined: #{attribute_name} (#{attribute_type})"
end
def validates(attribute_name, options)
puts "validation defined: #{attribute_name} (#{options})"
end
end)
end
def to_type
puts "StoreModel::Model#to_type"
end
end
end
module ApplicationController
module_function
def helpers
Module.new do
module_function
def exclude_id_from_columns(model)
case model
when "team" then { name: { type: :string }, email: { type: :string } }
when "project" then { name: { type: :string }, client: { type: :string } }
end
end
def get_required_columns_by_validation(model, _type)
{ name: { type: :string } }
end
end
end
end
# app code
class ContentConfiguration
def self.configure_as(model)
self.class.include StoreModel::Model # this line was changed
ApplicationController.helpers.exclude_id_from_columns(model).each do |key, value|
attribute key.to_sym, value[:type].to_sym
end
ApplicationController.helpers.get_required_columns_by_validation(model, 'presence').each do |key, value|
validates key.to_sym, presence: true
end
end
end
class ProjectConfiguration < ContentConfiguration
configure_as('project')
end
class TeamConfiguration < ContentConfiguration
configure_as('team')
end
from store_model.
Hello, now I'm getting the following error and the stacktrace
NameError (undefined local variable or method `attributes' for #<Class:0x00007fb9490c5260>)
Did you mean? attribute
Traceback (most recent call last):
35: from bin/rails:6:in `<main>'
34: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:324:in `require'
33: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:291:in `load_dependency'
32: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:324:in `block in require'
31: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
30: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
29: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
28: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
27: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
26: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.0.3.4/lib/rails/commands.rb:18:in `<main>'
25: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.0.3.4/lib/rails/command.rb:46:in `invoke'
24: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.0.3.4/lib/rails/command/base.rb:69:in `perform'
23: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/thor-1.0.1/lib/thor.rb:392:in `dispatch'
22: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/thor-1.0.1/lib/thor/invocation.rb:127:in `invoke_command'
21: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/thor-1.0.1/lib/thor/command.rb:27:in `run'
20: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.0.3.4/lib/rails/commands/console/console_command.rb:102:in `perform'
19: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.0.3.4/lib/rails/commands/console/console_command.rb:19:in `start'
18: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/railties-6.0.3.4/lib/rails/commands/console/console_command.rb:70:in `start'
17: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb.rb:400:in `start'
16: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb.rb:471:in `run'
15: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb.rb:471:in `catch'
14: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb.rb:472:in `block in run'
13: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb.rb:537:in `eval_input'
12: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb/ruby-lex.rb:150:in `each_top_level_statement'
11: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb/ruby-lex.rb:150:in `catch'
10: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb/ruby-lex.rb:151:in `block in each_top_level_statement'
9: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb/ruby-lex.rb:151:in `loop'
8: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb/ruby-lex.rb:154:in `block (2 levels) in each_top_level_statement'
7: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb/ruby-lex.rb:182:in `lex'
6: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb.rb:518:in `block in eval_input'
5: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb.rb:704:in `signal_status'
4: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb.rb:519:in `block (2 levels) in eval_input'
3: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/irb/input-method.rb:290:in `gets'
2: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/forwardable.rb:230:in `input='
1: from /Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/2.7.0/reline.rb:133:in `input='
/Users/joekaldas/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/store_model-0.8.0/lib/store_model/model.rb:40:in `==': undefined local variable or method `attributes' for #<Class:0x00007fb94d8bf778> (NameError)
Did you mean? attribute
from store_model.
Hi @DmitryTsepelev
Any help with the previous error?
from store_model.
Sorry, we have a loooong New Year holiday season here in Russia 🙃
So it looks like something is wrong in the order of calls, and in order to debug that I'll have to rebuild the app from scratch (which is kinda time consuming), so let me explain what I tried to do and it will probably help you to fix the problem.
There is a base class (ContentConfiguration
) which has the class method configure_as
. Each child class calls the method and passes the name of the entity to it. The method does two things:
- Configures the class to be a
StoreModel
(something might be wrong here, you could try to use a regularinclude
in each child model - Configures validations according to the helper methods
from store_model.
It's okay! Appreciate the response :)
Yes I understand the approach you're using. Was just stuck since the error is store model related.
But I'll look into it and let you know if I reach anything.
Thanks a lot again!
from store_model.
Related Issues (20)
- Encrypt attributes HOT 2
- Aliasing an attribute HOT 1
- GraphQL input type fails to cast HOT 4
- ArgumentError: wrong number of arguments (given 1, expected 0) in random model HOT 3
- Assignment Doesn't work in OneOf case HOT 3
- Delegation of `fetch` to `attributes` causes issues HOT 2
- NameError: uninitialized constant StoreModel::Types::ArrayType HOT 3
- Default values for attributes when retrieving the store model HOT 1
- Decoding Custom Types HOT 1
- Allow an option to disallow "UnknownAttributes" behavior HOT 1
- ActiveRecord validation contexts don't propagate HOT 1
- Override methods HOT 3
- Broken defaults in 2.0 HOT 2
- Attribute encryption with ActiveRecord::Encryption HOT 1
- StoreModel Stringifying json when saving. HOT 14
- accepts_nested_attributes_for allow partial updates HOT 2
- [QUESTION] How preserve data on update? HOT 1
- JSON deserializing empty string, leads to nil error
- Optional tracking of parent functionality HOT 4
- Registering StoreModels as ActiveModel types
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from store_model.