Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
shotengai
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
shotengai
Commits
162a7325
Commit
162a7325
authored
Oct 16, 2017
by
ivan Lan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve the Harray & Improve json column format
parent
4a4d7457
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
191 additions
and
86 deletions
+191
-86
product_series_controller.rb
...hotengai/controller/merchant/product_series_controller.rb
+6
-4
products_controller.rb
lib/shotengai/controller/merchant/products_controller.rb
+0
-2
harray.rb
lib/shotengai/harray.rb
+24
-0
json_column.rb
lib/shotengai/json_column.rb
+130
-56
product.rb
lib/shotengai/product.rb
+5
-3
series.rb
lib/shotengai/series.rb
+16
-8
snapshot.rb
lib/shotengai/snapshot.rb
+10
-13
No files found.
lib/shotengai/controller/merchant/product_series_controller.rb
View file @
162a7325
...
...
@@ -39,9 +39,10 @@ module Shotengai
private
def
resource_params
spec_value
=
params
.
require
(
resource_key
).
fetch
(
:spec_value
,
nil
)
&
.
permit!
info_value
=
params
.
require
(
resource_key
).
fetch
(
:info_value
,
nil
)
&
.
permit!
remark_value
=
params
.
require
(
resource_key
).
fetch
(
:remark_value
,
nil
)
&
.
permit!
spec_value
=
params
.
require
(
resource_key
).
fetch
(
:spec_value
,
nil
)
&
.
map
(
&
:permit!
)
info_template
=
params
.
require
(
resource_key
).
fetch
(
:info_template
,
nil
)
&
.
map
(
&
:permit!
)
detail_info_template
=
params
.
require
(
resource_key
).
fetch
(
:detail_info_template
,
nil
)
&
.
map
(
&
:permit!
)
remark_value
=
params
.
require
(
resource_key
).
fetch
(
:remark_value
,
nil
)
&
.
map
(
&
:permit!
)
meta
=
params
.
require
(
resource_key
).
fetch
(
:meta
,
nil
)
&
.
permit!
# ????????!!!!!, spec_value: [:key, :val] 一样的输出值 却在test报错???
# QUESTION: WARNING: 文档bug吧?????
...
...
@@ -49,7 +50,8 @@ module Shotengai
:original_price
,
:price
,
:stock
#, spec_value: [:key, :val]
).
merge
(
{
spec_value:
spec_value
,
info_value:
info_value
,
remark_value:
remark_value
,
spec_value:
spec_value
,
info_template:
info_template
,
remark_value:
remark_value
,
detail_info_template:
detail_info_template
,
meta:
meta
}
)
...
...
lib/shotengai/controller/merchant/products_controller.rb
View file @
162a7325
...
...
@@ -65,7 +65,6 @@ module Shotengai
# spec = params.require(resource_key).fetch(:spec, nil).try(:permit!)
spec_template
=
params
.
require
(
resource_key
).
fetch
(
:spec_template
,
nil
)
&
.
map
(
&
:permit!
)
remark_template
=
params
.
require
(
resource_key
).
fetch
(
:remark_template
,
nil
)
&
.
map
(
&
:permit!
)
info_template
=
params
.
require
(
resource_key
).
fetch
(
:info_template
,
nil
)
&
.
map
(
&
:permit!
)
detail
=
params
.
require
(
resource_key
).
fetch
(
:detail
,
nil
)
&
.
permit!
meta
=
params
.
require
(
resource_key
).
fetch
(
:meta
,
nil
)
&
.
permit!
# NOTE: :catalog_list is a default catalog list for template example, maybe should move it to the template controller, but it need add controller template for every controller
...
...
@@ -78,7 +77,6 @@ module Shotengai
).
merge
(
{
spec_template:
spec_template
,
remark_template:
remark_template
,
info_template:
info_template
,
detail:
detail
,
meta:
meta
}
)
...
...
lib/shotengai/harray.rb
View file @
162a7325
module
Shotengai
class
Harray
<
Array
class
<<
self
def
encode
hash
Harray
.
new
(
hash
.
map
{
|
key
,
val
|
{
'key'
=>
key
,
'val'
=>
val
}
}
)
end
def
decode
harray
harray
&&
Harray
.
new
(
harray
).
decode
end
end
# def initialize
# # Add some validations
# end
def
keys
self
.
map
{
|
obj
|
obj
[
'key'
]
}
end
...
...
@@ -12,5 +28,13 @@ module Shotengai
self
.
each
{
|
obj
|
return
obj
[
'val'
]
if
obj
[
'key'
].
eql?
(
key
)
}
nil
end
def
decode
self
.
map
{
|
obj
|
{
obj
[
'key'
]
=>
obj
[
'val'
]
}
}.
reduce
(
&
:merge
)
end
def
hash_map
self
.
map
{
|
obj
|
yield
obj
[
'key'
],
obj
[
'val'
]}
end
end
end
lib/shotengai/json_column.rb
View file @
162a7325
...
...
@@ -4,96 +4,170 @@ module Shotengai
included
do
end
class_methods
do
def
custom_hash_columns
columns
,
options
=
{}
decode_or_not
=
options
[
:decode
]
class_methods
do
# Option decode: true means storing as hash
def
harray_setter
*
columns
,
decode:
false
columns
.
each
do
|
column
|
# QUESTION: 这样可以避免 send("#{column}="), 合适?
class_eval
%Q{
define_method('
#{
column
}
') do
super() || {}
end
if
#{
decode_or_not
}
define_method("
#{
column
}
_input=") do |val|
parsed_val = val && val.map{ |h| { (h[:key] || h['key']) => (h[:val] || h['val']) } }.reduce(&:merge)
self.
#{
column
}
= parsed_val
end
define_method("
#{
column
}
_output") do
self.
#{
column
}
.map {|key, val| { key: key, val: val } }
end
def
#{
column
}
= val
raise Shotengai::WebError.new('
#{
column
}
必须是个 Array', -1 , 401) unless val.nil? || Array === val
super(
#{
decode
}
? Harray.decode(val) : val)
end
}
end
end
def
hash_column
# like meta, detail these json using for code development
end
def
generate_hash_template_column_for
*
names
names
.
each
do
|
name
|
class_eval
%Q{
def
#{
name
}
_template
Shotengai::Harray.new(super() || [])
end
def
#{
name
}
_template= val
raise Shotengai::WebError.new('
#{
name
}
_val 必须是个 Array', -1 , 401) unless val.nil? || Array === val
super(val)
def
harray_getter
*
columns
,
decode:
false
columns
.
each
do
|
column
|
class_eval
%{
def #{column}
#{decode} ?
Shotengai::Harray.encode(super() || []) :
Shotengai::Harray.new(super() || [])
end
}
end
end
def
generate_hash_value_column_for
*
names
,
delegate_template_to:
nil
names
.
each
do
|
name
|
class_eval
%Q{
delegate :
#{
name
}
_template, to: :
#{
delegate_template_to
}
def
#{
name
}
{
template: self.
#{
name
}
_template.map { |x| x['key'] },
value: self.
#{
name
}
_value,
}
end
def
harray_accessor
*
columns
,
decode:
false
harray_getter
*
columns
,
decode:
decode
harray_setter
*
columns
,
decode:
decode
end
def
#{
name
}
_value= val
raise Shotengai::WebError.new('
#{
name
}
_val 必须是个 Hash', -1 , 401) unless val.nil? || Hash === val
super(val)
end
}
def
template_with_value
key
,
value:
"
#{
key
}
_value"
,
template:
"
#{
key
}
_template"
class_eval
%Q{
def
#{
key
}
{
template:
#{
template
}
,
value:
#{
value
}
,
}
end
}
end
def
template_with_value_getters
*
keys
,
value_in_template:
false
,
delegate_template_to:
nil
if
delegate_template_to
self
.
delegate
(
*
keys
.
map
{
|
key
|
"
#{
key
}
_template"
},
to:
delegate_template_to
)
end
keys
.
each
do
|
key
|
value
=
value_in_template
?
"
#{
key
}
_template.decode"
:
"
#{
key
}
_value"
self
.
template_with_value
key
,
value:
value
end
end
def
column_has_
children
column
,
options
ArgumentError
.
new
(
"Please give
#{
column
}
one child at least."
)
unless
options
[
:children
]
children_names
=
options
[
:children
].
map
(
&
:to_s
)
self_name
=
options
[
:as
]
||
self
.
model_name
.
singular
def
column_has_
implants
column
,
implants:
nil
,
as:
'host'
,
prefix:
'full_'
ArgumentError
.
new
(
"Please give
#{
column
}
one child at least."
)
unless
implants
ArgumentError
.
new
(
'Duplicate value in option :implants with option :as'
)
if
(
Array
(
implants
)
&
Array
(
as
)).
any?
chimera
=
"
#{
prefix
}#{
column
}
"
class_eval
%Q{
define_method('
full_
#{
column
}
') do
define_method('
#{
chimera
}
') do
read_attribute(:
#{
column
}
) || {}
end
define_method('full_
#{
column
}
=') do |val|
define_method('
#{
chimera
}
=') do |val|
raise Shotengai::WebError.new('
#{
chimera
}
必须是个 Hash', -1 , 401) unless val.nil? || Hash === val
write_attribute(:
#{
column
}
, val)
end
def
#{
column
}
_before_implant
#{
column
}
end
define_method('
#{
column
}
') do
full_
#{
column
}
['
#{
self_name
}
'] || {}
#{
chimera
}
['
#{
as
}
'] || {}
end
def
#{
column
}
_before_implant= val
#{
column
}
= val
end
define_method('
#{
column
}
=') do |val|
val =
super
(val)
self.
full_
#{
column
}
= full_
#{
column
}
.merge('snapshot
' => val)
val =
#{
column
}
_before_implant=
(val)
self.
#{
chimera
}
=
#{
chimera
}
.merge('
#{
as
}
' => val)
end
#{
children_names
}
.each do |child|
#{
Array
(
implants
)
}
.each do |child|
define_method(
\"\#
{child}_
#{
column
}
\"
) do
full_
#{
column
}
[child]
#{
chimera
}
[child]
end
# WARNING: TODO: 这里 val = 并没有继承
define_method("
\#
{child}_
#{
column
}
=") do |val|
self.
#{
chimera
}
=
#{
chimera
}
.merge(child => val)
end
end
}
end
# TODO:ORNOT:
def
hash_column
# like meta, detail these json using for code development
end
# def custom_hash_columns columns, options={}
# decode_or_not = options[:decode]
# columns.each do |column|
# # QUESTION: 这样可以避免 send("#{column}="), 合适?
# class_eval %Q{
# define_method('#{column}') do
# super() || {}
# end
# if #{decode_or_not}
# define_method("#{column}_input=") do |val|
# parsed_val = val && val.map{ |h| { (h[:key] || h['key']) => (h[:val] || h['val']) } }.reduce(&:merge)
# self.#{column} = parsed_val
# end
# define_method("#{column}_output") do
# self.#{column}.map {|key, val| { key: key, val: val } }
# end
# end
# }
# end
# end
# def generate_hash_template_column_for *names
# names.each do |name|
# class_eval %Q{
# def #{name}
# {
# template: self.#{name}_template.map { |x| x['key'] },
# value: self.#{name}_value,
# }
# end
# def #{name}_template
# Shotengai::Harray.new(super() || [])
# end
# redef #{name}_template= val
# raise Shotengai::WebError.new('#{name}_val 必须是个 Array', -1 , 401) unless val.nil? || Array === val
# old(val)
# end
# }
# end
# end
# def generate_hash_value_column_for *names, delegate_template_to: nil
# names.each do |name|
# class_eval %Q{
# delegate :#{name}_template, to: :#{delegate_template_to}
# def #{name}
# {
# template: self.#{name}_template.map { |x| x['key'] },
# value: self.#{name}_value,
# }
# end
# def #{name}_value= val
# raise Shotengai::WebError.new('#{name}_val 必须是个 Hash', -1 , 401) unless val.nil? || Hash === val
# old(val)
# end
# }
# end
# end
end
end
end
lib/shotengai/product.rb
View file @
162a7325
...
...
@@ -20,7 +20,6 @@ module Shotengai
# created_at :datetime not null
# updated_at :datetime not null
# remark_template :json
# info_template :json
#
# Indexes
#
...
...
@@ -32,10 +31,13 @@ module Shotengai
require
'acts-as-taggable-on'
self
.
table_name
=
'shotengai_products'
generate_hash_template_column_for
:spec
,
:info
,
:remark
# generate_hash_template_column_for :spec, :remark
harray_accessor
:spec_template
,
:remark_template
template_with_value_getters
:spec
,
:remark
,
value_in_template:
true
belongs_to
:manager
,
polymorphic:
true
,
optional:
true
#, touch: true
default_scope
{
order
(
created_at: :desc
)
}
scope
:alive
,
->
{
where
.
not
(
status:
'deleted'
)
}
scope
:recycle_bin
,
->
{
unscope
(
where: :status
).
deleted
.
where
(
'updated_at > ?'
,
Time
.
now
-
10
.
day
)}
...
...
lib/shotengai/series.rb
View file @
162a7325
...
...
@@ -15,7 +15,7 @@ module Shotengai
# updated_at :datetime not null
# aasm_state :string(255)
# remark_value :json
# info_
value
:json
# info_
template
:json
#
# Indexes
#
...
...
@@ -36,9 +36,19 @@ module Shotengai
# validate remark
validate
:check_remark_value
,
unless: :remark_template_empty?
harray_accessor
:info_template
,
:detail_info_template
harray_accessor
:spec_value
,
:remark_value
,
decode:
true
template_with_value_getters
:info
,
value_in_template:
true
template_with_value_getters
:spec
,
:remark
,
delegate_template_to: :product
# info_template
# generate_hash_template_column_for :info
# full_info_template: { optional: d, detail: detail_info_template }
column_has_implants
:info_template
,
implants:
[
'detail'
],
as:
'optional'
generate_hash_value_column_for
:spec
,
:info
,
:remark
,
delegate_template_to: :product
# generate_hash_value_column_for :spec
, :remark, delegate_template_to: :product
delegate
:title
,
:detail
,
:banners
,
:cover_image
,
:status
,
:status_zh
,
:manager
,
to: :product
scope
:alive
,
->
{
where
.
not
(
aasm_state:
'deleted'
)
}
...
...
@@ -48,7 +58,7 @@ module Shotengai
scope
:query_spec_value_with_product
,
->
(
val
,
product
)
{
if
val
.
keys
.
sort
==
product
.
spec_template
.
keys
.
sort
keys
=
[];
values
=
[]
val
.
map
{
|
k
,
v
|
keys
<<
"spec_value->'$.
\"
#{
k
}
\"
' = ? "
;
values
<<
v
}
val
.
hash_
map
{
|
k
,
v
|
keys
<<
"spec_value->'$.
\"
#{
k
}
\"
' = ? "
;
values
<<
v
}
where
(
product:
product
).
where
(
keys
.
join
(
' and '
),
*
values
)
else
self
.
none
...
...
@@ -109,15 +119,14 @@ module Shotengai
private
# spec 字段
def
spec_template_empty?
spec_template
.
empty?
&&
spec_value
.
nil
?
# 当且仅当二者都为空才跳过验证
spec_template
.
empty?
&&
spec_value
.
empty
?
# 当且仅当二者都为空才跳过验证
end
def
remark_template_empty?
remark_template
.
empty?
&&
remark_value
.
nil
?
# 当且仅当二者都为空才跳过验证
remark_template
.
empty?
&&
remark_value
.
empty
?
# 当且仅当二者都为空才跳过验证
end
def
check_spec_value
errors
.
add
(
:spec_value
,
'spec_value 必须是个 Hash'
)
unless
spec_value
.
is_a?
(
Hash
)
errors
.
add
(
:spec_value
,
'非法的关键字,或关键字缺失'
)
unless
(
product
.
spec_template
.
keys
-
spec_value
.
keys
).
empty?
illegal_values
=
{}
spec_value
.
each
{
|
key
,
value
|
illegal_values
[
key
]
=
value
unless
value
.
in?
(
product
.
spec_template
.
val_at
(
key
)
||
[])
}
...
...
@@ -135,7 +144,6 @@ module Shotengai
end
def
check_remark_value
errors
.
add
(
:remark_value
,
'remark_value 必须是个 Hash'
)
unless
remark_value
.
is_a?
(
Hash
)
# product.remark_value.keys 包含 remark_value.keys
illegal_key
=
(
remark_value
.
keys
-
product
.
remark_template
&
.
keys
)
errors
.
add
(
:remark_value
,
"非法的关键字,
#{
illegal_key
}
"
)
unless
illegal_key
.
empty?
...
...
lib/shotengai/snapshot.rb
View file @
162a7325
...
...
@@ -38,10 +38,11 @@ module Shotengai
validate
:check_remark_value
,
unless: :remark_template_empty?
validates
:count
,
numericality:
{
only_integer:
true
,
greater_than:
0
}
generate_hash_value_column_for
:spec
,
:info
,
:remark
,
delegate_template_to: :series
# generate_hash_value_column_for :spec, :info, :remark, delegate_template_to: :series
template_with_value_getters
:spec
,
:remark
,
:info
,
delegate_template_to: :series
column_has_
children
:meta
,
children
:
[
'product'
,
'series'
],
as: :snapshot
column_has_
children
:info_value
,
children:
[
'series
'
],
as: :snapshot
column_has_
implants
:meta
,
implants
:
[
'product'
,
'series'
],
as: :snapshot
column_has_
implants
:info_value
,
implants:
[
'detail
'
],
as: :snapshot
validate
:cannot_edit
,
if: :order_was_paid
before_destroy
:cannot_edit
,
if: :order_was_paid
...
...
@@ -112,15 +113,11 @@ module Shotengai
banners:
series
.
banners
,
cover_image:
series
.
cover_image
,
detail:
series
.
detail
,
full_meta:
{
product:
product
.
meta
,
series:
series
.
meta
,
snapshot:
meta
,
},
full_info_value:
{
series:
series
.
info_value
,
snapshot:
info_value
,
}
product_meta:
product
.
meta
,
series_meta:
series
.
meta
,
meta:
meta
,
detail_info_value:
series
.
detail_info_template
,
info_value:
info_value
,
)
end
...
...
@@ -159,7 +156,7 @@ module Shotengai
end
def
check_remark_value
nullable_keys
=
series
.
remark_value
.
select
{
|
k
,
v
|
v
}.
keys
nullable_keys
=
series
.
remark_value
.
decode
.
select
{
|
k
,
v
|
v
}.
keys
required_keys
=
product
.
remark_template
.
keys
-
nullable_keys
absent_keys
=
required_keys
-
remark
.
keys
# remark 可添加多余字段
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment