编程

Windows系统下C语言中使用自定义包的方法:

首先明确GOPATH的路径,执行go env | findstr GOPATH

1
2
3
4
C:\Users\CHORDER>go env | findstr GOPATH
set GOPATH=C:\Users\CHORDER\go

C:\Users\CHORDER>

接着在GOPATH目录中创建相应的自定义包,这里定义一个example包,并创建两个源码文件src1.gosrc2.go,源码内容如下:

C:\Users\CHORDER\go\src\chorder.net\example\src1.go

1
2
3
4
5
6
7
8
9
10
11
package example

import "fmt"

func init(){
fmt.Printf("\nchorder.net/example/src1.go init() has been called.")
}

func Src1(){
fmt.Printf("\nchorder.net/example/src1.go Src1() has been called.")
}

C:\Users\CHORDER\go\src\chorder.net\example\src2.go

1
2
3
4
5
6
7
8
9
10
11
package example

import "fmt"

func init(){
fmt.Printf("\nchorder.net/example/src2.go init() has been called.")
}

func Src2(){
fmt.Printf("\nchorder.net/example/src2.go Src1() has been called.")
}

编写代码调用这两个包中的方法:

packge_test.go

1
2
3
4
5
6
7
8
package main

import "chorder.net/example"

func main(){
trueexample.Src1()
trueexample.Src2()
}

执行结果:

1
2
3
4
5
6
>go run packge_test.go

chorder.net/example/src1.go init() has been called.
chorder.net/example/src2.go init() has been called.
chorder.net/example/src1.go Src1() has been called.
chorder.net/example/src2.go Src1() has been called.

最近的这几个VirtualBox版本(6.1.4、6.1.6、6.1.8)比以前多了一些变化,主要体现在Guest Additions上。

在6.1.4、6.1.6的版本里,曾经遇到过虚拟机和宿主机(Guest and Host)之间不能共享粘贴板(Clipboard)的bug,以及Windows 7、Debian10的Guest机器无法全屏的Bug。

之前的解决方法是,在 VirtualBox官网上下载Virtualbox 6.1.2版本的Guest Additions ISO,挂载并且安装ISO镜像中的VBoxLinuxAdditions.run文件后,即可解决这些问题。

但在今天的6.1.8版本的Release Changelog中,提到已经解决了多个这样的Bug,于是试试运气,结果遇到这样的问题:

1
VboxClient: The parent session seems to be non-X11. Exiting...

这里分享我在Windows 10 Host,Debian 10.0 Guest上的解决方法:

先注销当前用户:

再在登录的时候选择X11选项:

即可解决。

0x00 前言

Rails 6.0 发布已经有一段时间了,之前没有什么项目可以练手,最近总算遇到可以使用Rails 6开发的场景了。Rails 6中新增了一些功能和特性,有一些内容官方文档里并没有写的很具体,所以在摸索的过程中也遇到了一些坑点。这里以一个新工程从头到尾的构建,来简单记录在Rails6中使用jQuery和Bootstrap的过程。希望能够给新来的同学做个参考。

编程和码字的水平有限,如有错漏敬请指教,也请多包涵!下面就开始吧。

0x01 环境准备

  • 操作系统: Debian 10 ( 4.19.0-8-amd64 )
  • Ruby版本: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
  • Rails版本: Rails 6.0.2.1
1
2
3
4
5
6
test@debian:~$uname -a
Linux debian 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64 GNU/Linux
test@debian:~$ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
test@debian:~$rails -v
Rails 6.0.2.1

0x02 创建项目

这里新建一个项目“TestApp”,并在其中建立控制器“Test”和测试方法“test”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
test@debian:~$rails new TestApp
create
create README.md
create Rakefile
create .ruby-version
create config.ru
create .gitignore
create Gemfile
...
├─ [email protected]
├─ [email protected]
└─ [email protected]
Done in 59.74s.
Webpacker successfully installed 🎉 🍰
test@debian:~/TestApp$rails g controller Test test --no-stylesheets
Running via Spring preloader in process 22413
create app/controllers/test_controller.rb
route get 'test/test'
invoke erb
create app/views/test
create app/views/test/test.html.erb
invoke test_unit
create test/controllers/test_controller_test.rb
invoke helper
create app/helpers/test_helper.rb
invoke test_unit
invoke assets
invoke scss
test@debian:~$

创建好之后,修改test页面,添加一个表单和按钮,用于稍后测试Bootstrap。(在执行创建控制器和方法的命令后,Rails已经为我们自动添加了到Test控制器test方法的路由,所以不需要我们再新增路由。)

app/views/test/test.html.erb 代码:

1
2
3
4
5
6
7
<h1>Test#test</h1>
<p>Find me in app/views/test/test.html.erb</p>

<form>
<input id="test" type="text"/>
<button id="test_btn">点我</button>
</form>

启动Rails服务,访问http://localhost:3000/test/test:

1
2
3
4
5
6
7
8
9
10
11
test@debian:~/TestApp$rails s
=> Booting Puma
=> Rails 6.0.2.1 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.1 (ruby 2.6.5-p114), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop

此时应用已经创建成功。

0x03 添加jQuery和Bootstrap库

这里采用yarn作为Javascript包管理器。在TestApp目录中运行bin/yarn,如果出现以下内容,说明yarn没有安装:

1
2
3
test@debian:~/TestApp$bin/yarn
Yarn executable was not detected in the system.
Download Yarn at https://yarnpkg.com/en/docs/install

安装方法在这里, 以当前使用的Debian 10为例,安装的方法是:

1
2
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

安装好yarn之后,就可以用yarn添加jQuery包和Bootstrap包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
test@debian:~/TestApp$yarn add jquery 
yarn add v1.21.1
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > [email protected]" has unmet peer dependency "[email protected]^4.0.0 || ^5.0.0".
warning "webpack-dev-server > [email protected]" has unmet peer dependency "[email protected]^4.0.0".
[4/4] Building fresh packages...

success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ [email protected]
info All dependencies
└─ [email protected]
Done in 9.98s.
test@debian:~/TestApp$yarn add bootstrap
yarn add v1.21.1
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > [email protected]" has unmet peer dependency "[email protected]^4.0.0 || ^5.0.0".
warning "webpack-dev-server > [email protected]" has unmet peer dependency "[email protected]^4.0.0".
warning " > [email protected]" has unmet peer dependency "[email protected]^1.16.0".
[4/4] Building fresh packages...

success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ [email protected]
info All dependencies
└─ [email protected]
Done in 13.33s.

由于Bootstrap还需要基于popper.js,不装的话会报依赖错误,所以安装一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
test@debian:~/TestApp$yarn add popper.js
yarn add v1.21.1
[1/4] Resolving packages...
warning [email protected]: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > [email protected]" has unmet peer dependency "[email protected]^4.0.0 || ^5.0.0".
warning "webpack-dev-server > [email protected]" has unmet peer dependency "[email protected]^4.0.0".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ [email protected]
info All dependencies
└─ [email protected]
Done in 11.78s.

安装的执行结果:

因为众所周知的原因,网速慢的同学就尴尬了,这里可能要等很久,所以你需要选一个科学一点的方式。

此时查看TestApp/node_modules目录,所需的前端库已经添加好了:

1
2
3
4
5
6
7
test@debian:~/TestApp$ls node_modules/jquery/
AUTHORS.txt bower.json dist external LICENSE.txt package.json README.md src
test@debian:~/TestApp$ls node_modules/bootstrap/
dist js LICENSE package.json README.md scss
test@debian:~/TestApp$ls node_modules/popper.js/
dist index.d.ts index.js.flow package.json README.md src
test@debian:~/TestApp$

0x04 使用Bootstrap

跟Rails5有所不同的是,Rails6采用webpack打包的方式,把需要打包的资源统一放在一个文件里(Rails6之前是采用Gemfile的方式引入第三方库,再通过Asset Pipeline汇聚)。

于是在安装好所需的前端库之后,就需要在app/javascript/packs/application.js中先引用它:

以Bootstrap为例,在其中添加import 'bootstrap'引入语句:

与此同时还需要在application.scss中引入Bootstrap的CSS样式表:

app/assets/stylesheets/application.scss文件中添加@import "bootstrap/dist/css/bootstrap";


2020/05/28 Patch

纠个错,如果想要通过@import "bootstrap/dist/css/bootstrap";的方式引用bootstrap相关的CSS,需要把app/assets/stylesheets/application.css文件重命名为app/assets/stylesheets/application.scss
如果直接使用app/assets/stylesheets/application.css的话,那么采用如下方式来引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
* File: app/assets/stylesheets/application.css
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require bootstrap/dist/css/bootstrap
*= require_tree .
*= require_self
*/

Ending Patch


接着继续修改app/views/test/test.html.erb文件中的代码,添加相应的CSS类来测试Bootstrap是否已经引入成功:

1
2
3
4
5
6
7
8
9
<h1>Test#test</h1>
<p>Find me in app/views/test/test.html.erb</p>

<form>
<div class="form-group">
<input id="test" type="text" class="form-control"/>
<button id="test_btn" class="btn btn-success">点我</button>
</div>
</form>

启动应用,再次访问测试页面:

虽然界面有点丑,但是从渲染效果来看,Bootstrap已经成功引入了。

0x05 使用jQuery

继续修改app/javascript/packs/application.js,添加用于测试jQuery的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")


// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

import 'bootstrap'

$(document).on('turbolinks:load', function(){
$("#test_btn").click(function(){
alert($("#test").val());
});
});

保存并运行,刷新https://localhost:3000/test/test页面,发现添加的代码无法执行,控制台中有报错:

1
2
ReferenceError: $ is not defined 
application.js:21

这是因为jQuery库也需要引入一下,但是引入的方式有些不同,并不是在页面中直接引入,而是需要在config/webpack/environment.js中添加以下引入代码:

1
2
3
4
5
6
var webpack = require('webpack');
environment.plugins.append( 'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
})
)

通过声明一个全局的导出,就可以在全局的JS代码文件中使用”$”符号了。

刷新并再次访问,代码能够运行,控制台也没有再报错,说明jQuery已经成功集成:

另一种方法

还有一种方法是通过在JS文件按中使用import $ from 'jquery'来使”$”符生效,但是这样比较繁琐,需要在每个JS文件中出现,所以不再介绍了,当然,也提供一下详细的代码参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")


// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

import 'bootstrap'
import $ from 'jquery' // 在每个JS文件中加上这一行,也可以替代声明全局变量。

$(document).on('turbolinks:load', function(){
$("#test_btn").click(function(){
alert($("#test").val());
});
});

0x06 总结

在网上主要参考了这篇文章。Rails 6中的变化还是挺大的,不知道webpack会不会真的成为Rails的未来,感觉之前使用coffee script来写JS的同学不是很多,但是我倒是已经非常习惯于使用它来开发前端功能了。

但是想必Rails的先驱们有着他们更成熟的考虑吧,那就一起继续探索好了。

最近有不少好剧,有时候网速不好追剧太累了,而且有的有广告。看了一下几个主流的视频网站,有不少都还是用的标准的hls协议,没有在此基础上做修改(所以容易导致影视资源泄漏)。用标准hls协议的好处就是我们可以基于hls协议很方便地将影视资源多线程快速下载到本地,既可以流畅观看又可以去广告(部分)。

于是写了一个多线程的m3u8的文件下载器,基于python3纯原生库,安全放心:

代码链接:

https://github.com/Chorder/m3u8_downloader

顺便说一句,m3u8文件挺有意思的,结合ffmepg的缺陷,曾经爆出过播放器任意文件读取漏洞 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-1897 ,但是亲测在浏览器中m3u8文件其实还有更多妙用。感兴趣的童鞋可以进一步玩耍一下。

在PostgresSQL中如果尝试删除一个用户,可能会遇到这个报错:

1
2
ERROR:  role "XXX" cannot be dropped because some objects depend on it
DETAIL: privileges for table YYY

这是因为没有撤销该用户的权限所导致的。

具体以一个例子来说明。创建一张叫做“xxx”的表,再创建一个“test”用户,并将这张表的所有权限赋予“test”用户。

直接尝试删除这个用户,就会出现这个权限提示。

1
2
3
4
5
6
7
8
9
root=# CREATE TABLE xxx ( id SERIAL PRIMARY KEY , name CHAR(15) NOT NULL );
CREATE TABLE
root=# CREATE USER test PASSWORD 'test';
CREATE ROLE
root=# GRANT ALL ON xxx TO test;
GRANT
root=# DROP USER test;
ERROR: role "test" cannot be dropped because some objects depend on it
DETAIL: privileges for table xxx

可以通过下面这条语句查询PG中“test”用户的权限,并根据查询到的结果撤销之。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root=# SELECT * FROM information_schema.table_privileges WHERE grantee='test';
grantor | grantee | table_catalog | table_schema | table_name | privilege_type | is_grantable | with_hierarchy
---------+---------+---------------+--------------+------------+----------------+--------------+----------------
root | test | root | public | xxx | INSERT | NO | NO
root | test | root | public | xxx | SELECT | NO | YES
root | test | root | public | xxx | UPDATE | NO | NO
root | test | root | public | xxx | DELETE | NO | NO
root | test | root | public | xxx | TRUNCATE | NO | NO
root | test | root | public | xxx | REFERENCES | NO | NO
root | test | root | public | xxx | TRIGGER | NO | NO
(7 rows)

root=# REVOKE ALL ON xxx FROM test;
REVOKE
root=# DROP USER test;
DROP ROLE
root=#

批量撤销用户在数据库中所有表的权限:

1
2
revoke all on database XX from test;
revoke all on all tables in schema public from test;

PG权限的基本操作

赋予权限的语句是

1
GRANT *privilege ON *obj TO *user

撤销权限的语句从语法上与之对应:

1
REVOKE *privilege ON *obj FROM *user
  • privilege − SELECT,INSERT,UPDATE,DELETE, RULE,ALL
  • obj − 要授予访问权限的对象名称,可以是 table, view,sequence
  • user可以是以下情况
    • PUBLIC − 所有用户
    • GROUP group − 用户组
    • username − 用户名 (PUBLIC 是代表所有用户的简短形式)

删除用户:

查看用户权限:

先介绍一下:

XVA是Citrix XenServer导出的虚拟机格式镜像

OVA是Virtualbox常见的开放虚拟映像

RAW是纯粹的磁盘映像文件

在多个虚拟化平台之间进行镜像转换时,思路是先将特定平台镜像转换成中间映像(RAW),再转换成目标平台的虚拟化格式。

从Citrix XenServer XVA文件转Virtualbox格式时,先将xva转换成raw,运行:

1
qemu-img convert -O raw target.xva output.raw

qemu-img包含在Debian系的qemu-utils软件包中,如果没有,安装即可:

1
apt-get install qemu-utils

转换完成后,得到output.raw,再使用Virtualbox的VBoxManage将raw转换成VHD,就可以在Virtualbox使用了(似乎也可以在Vmware中使用)。

1
"c:Program Files\Oracle\VirtualBox\VBoxManage.exe" convertfromraw output.raw output.vhd --format VHD

参考自:

https://bart.jakubowski.in/2013/10/21/xva-to-vhd/

XenServer默认是没有ISO镜像目录的,如果需要创建自定义镜像的虚拟机,需要先创建ISO光盘映像目录,再导入镜像。方法如下:

首先登录XenServer,运行如下命令,在/var/目录下创建存放ISO的目录(也可自定义成其他目录),使用xe命令创建镜像分区。

1
2
3
mkdir -p /var/iso_import

xe sr-create name-label=ISO type=iso device-config:location=/var/iso_import/ device-config:legacy_mode=true content-type=iso

后面只需要将镜像iso文件导入/var/iso_import目录中,在XenServer可视化控制台中刷新(rescan)即可看到镜像。创建虚拟机时即可从自定义的镜像启动。

Windows10在升级到1903之后,菜单栏突然多出了一个“ms-resource:AppName/text”的空条目,逼死强迫症。
如何安全删除这个图标呢?
方法如下:

以Administrator身份运行powershell

在Powershell中运行:

1
Get-AppxPackage -all *HolographicFirstRun* | Remove-AppPackage -AllUsers

打开任务管理器,kill掉explorer.exe进程(保持Powershell在前台运行)。在Powershell中,进入这个目录:

1
cd $Env:localappdata\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy`

如果能进入,运行以下删除目录语句:

Remove-Item -Recurse -Force .\TempState\

在任务管理器中重新打开Explorer.exe。此时查看菜单,ms-resource:AppName/text图标应该已经删除了。

参考自:

https://answers.microsoft.com/en-us/windows/forum/all/ms-resourceappnametext-appeared-on-start-menu-all/e6c5d10b-bad9-4eae-835f-99f438f3bd91

原文:

1
2
3
4
5
6
7
8
9
10
11
12
Run Powershell with Admin privilege
On the prompt, run this command:

Get-AppxPackage -all *HolographicFirstRun* | Remove-AppPackage -AllUsers

Open Task manager, kill explorer.exe (keep the powershell console open)
Back on the prompt, type:
cd $Env:localappdata\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy
If the previous command succesfully put you on AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy directory inside your profile dir, then run:
Remove-Item -Recurse -Force .\TempState\
Start explorer.exe back up from task manager (File -> New Task)
The rogue start menu item should be gone.

在CentOS 6 机器中安装sassc Gem,报如下的错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
[[email protected] ~ ]# gem install sassc
Building native extensions. This could take a while...
ERROR: Error installing sassc:
trueERROR: Failed to build gem native extension.

current directory: /usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/ext
/usr/local/rvm/rubies/ruby-2.6.2/bin/ruby -rrubygems /usr/local/rvm/rubies/ruby-2.6.2/lib/ruby/gems/2.6.0/gems/rake-12.3.2/exe/rake RUBYARCHDIR\=/usr/local/rvm/gems/ruby-2.6.2/extensions/x86_64-linux/2.6.0/sassc-2.0.1 RUBYLIBDIR\=/usr/local/rvm/gems/ruby-2.6.2/extensions/x86_64-linux/2.6.0/sassc-2.0.1
cd libsass
make lib/libsass.so
mkdir lib
cc -Wall -O2 -I /usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/ext/libsass/include -fPIC -fPIC -c -o src/cencode.o src/cencode.c
src/cencode.c: In function ‘base64_encode_block’:
src/cencode.c:50: warning: empty declaration
src/cencode.c:64: warning: empty declaration
g++ -Wall -O2 -std=c++0x -I /usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/ext/libsass/include -fPIC -fPIC -c -o src/ast.o src/ast.cpp
In file included from src/ast.cpp:2:
src/ast.hpp: In member function ‘virtual size_t Sass::Vectorized<T>::hash()’:
src/ast.hpp:336: error: expected initializer before ‘:’ token
src/ast.hpp:339: error: expected primary-expression before ‘}’ token
src/ast.hpp:339: error: expected ‘;’ before ‘}’ token
src/ast.hpp:339: error: expected primary-expression before ‘}’ token
src/ast.hpp:339: error: expected ‘)’ before ‘}’ token
src/ast.hpp:339: error: expected primary-expression before ‘}’ token
src/ast.hpp:339: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In constructor ‘Sass::Hashed::Hashed(size_t)’:
src/ast.hpp:373: error: ‘class Sass::ExpressionMap’ has no member named ‘reserve’
src/ast.hpp: In member function ‘Sass::Hashed& Sass::Hashed::operator+=(Sass::Hashed*)’:
src/ast.hpp:402: error: expected initializer before ‘:’ token
src/ast.hpp:406: error: could not convert ‘Sass::Hashed::reset_duplicate_key()’ to ‘bool’
src/ast.hpp:407: error: expected primary-expression before ‘return’
src/ast.hpp:407: error: expected ‘)’ before ‘return’
In file included from src/ast.cpp:2:
src/ast.hpp: In member function ‘virtual size_t Sass::Map::hash()’:
src/ast.hpp:1153: error: expected initializer before ‘:’ token
src/ast.hpp:1157: error: expected primary-expression before ‘}’ token
src/ast.hpp:1157: error: expected ‘;’ before ‘}’ token
src/ast.hpp:1157: error: expected primary-expression before ‘}’ token
src/ast.hpp:1157: error: expected ‘)’ before ‘}’ token
src/ast.hpp:1157: error: expected primary-expression before ‘}’ token
src/ast.hpp:1157: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In member function ‘virtual size_t Sass::Function_Call::hash()’:
src/ast.hpp:1522: error: expected initializer before ‘:’ token
src/ast.hpp:1524: error: expected primary-expression before ‘}’ token
src/ast.hpp:1524: error: expected ‘;’ before ‘}’ token
src/ast.hpp:1524: error: expected primary-expression before ‘}’ token
src/ast.hpp:1524: error: expected ‘)’ before ‘}’ token
src/ast.hpp:1524: error: expected primary-expression before ‘}’ token
src/ast.hpp:1524: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In member function ‘virtual size_t Sass::Number::hash()’:
src/ast.hpp:1614: error: expected initializer before ‘:’ token
src/ast.hpp:1616: error: expected primary-expression before ‘for’
src/ast.hpp:1616: error: expected ‘;’ before ‘for’
src/ast.hpp:1616: error: expected primary-expression before ‘for’
src/ast.hpp:1616: error: expected ‘)’ before ‘for’
src/ast.hpp:1616: error: expected initializer before ‘:’ token
src/ast.hpp:1618: error: expected primary-expression before ‘}’ token
src/ast.hpp:1618: error: expected ‘;’ before ‘}’ token
src/ast.hpp:1618: error: expected primary-expression before ‘}’ token
src/ast.hpp:1618: error: expected ‘)’ before ‘}’ token
src/ast.hpp:1618: error: expected primary-expression before ‘}’ token
src/ast.hpp:1618: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In member function ‘bool Sass::String_Schema::has_interpolants()’:
src/ast.hpp:1791: error: expected initializer before ‘:’ token
src/ast.hpp:1794: error: expected primary-expression before ‘return’
src/ast.hpp:1794: error: expected ‘;’ before ‘return’
src/ast.hpp:1794: error: expected primary-expression before ‘return’
src/ast.hpp:1794: error: expected ‘)’ before ‘return’
src/ast.hpp: In member function ‘virtual size_t Sass::String_Schema::hash()’:
src/ast.hpp:1801: error: expected initializer before ‘:’ token
src/ast.hpp:1803: error: expected primary-expression before ‘}’ token
src/ast.hpp:1803: error: expected ‘;’ before ‘}’ token
src/ast.hpp:1803: error: expected primary-expression before ‘}’ token
src/ast.hpp:1803: error: expected ‘)’ before ‘}’ token
src/ast.hpp:1803: error: expected primary-expression before ‘}’ token
src/ast.hpp:1803: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In member function ‘virtual size_t Sass::Compound_Selector::hash()’:
src/ast.hpp:2750: error: ‘template<class T> class Sass::Vectorized’ used without template parameters
src/ast.hpp: In member function ‘virtual size_t Sass::Selector_List::hash()’:
src/ast.hpp:2997: error: ‘template<class T> class Sass::Vectorized’ used without template parameters
src/ast.hpp: In member function ‘virtual void Sass::Selector_List::set_media_block(Sass::Media_Block*)’:
src/ast.hpp:3014: error: expected initializer before ‘:’ token
src/ast.hpp:3017: error: expected primary-expression before ‘}’ token
src/ast.hpp:3017: error: expected ‘;’ before ‘}’ token
src/ast.hpp:3017: error: expected primary-expression before ‘}’ token
src/ast.hpp:3017: error: expected ‘)’ before ‘}’ token
src/ast.hpp:3017: error: expected primary-expression before ‘}’ token
src/ast.hpp:3017: error: expected ‘;’ before ‘}’ token
src/ast.hpp: In member function ‘virtual bool Sass::Selector_List::has_placeholder()’:
src/ast.hpp:3019: error: expected initializer before ‘:’ token
src/ast.hpp:3022: error: expected primary-expression before ‘return’
src/ast.hpp:3022: error: expected ‘;’ before ‘return’
src/ast.hpp:3022: error: expected primary-expression before ‘return’
src/ast.hpp:3022: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘virtual bool Sass::Selector_List::find(bool (*)(Sass::AST_Node_Obj))’:
src/ast.cpp:35: error: expected initializer before ‘:’ token
src/ast.cpp:39: error: expected primary-expression before ‘return’
src/ast.cpp:39: error: expected ‘;’ before ‘return’
src/ast.cpp:39: error: expected primary-expression before ‘return’
src/ast.cpp:39: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘virtual bool Sass::Compound_Selector::find(bool (*)(Sass::AST_Node_Obj))’:
src/ast.cpp:45: error: expected initializer before ‘:’ token
src/ast.cpp:49: error: expected primary-expression before ‘return’
src/ast.cpp:49: error: expected ‘;’ before ‘return’
src/ast.cpp:49: error: expected primary-expression before ‘return’
src/ast.cpp:49: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘virtual void Sass::Arguments::set_delayed(bool)’:
src/ast.cpp:98: error: expected initializer before ‘:’ token
src/ast.cpp:102: error: expected primary-expression before ‘}’ token
src/ast.cpp:102: error: expected ‘)’ before ‘}’ token
src/ast.cpp:102: error: expected primary-expression before ‘}’ token
src/ast.cpp:102: error: expected ‘;’ before ‘}’ token
src/ast.cpp: In member function ‘virtual bool Sass::Compound_Selector::has_parent_ref() const’:
src/ast.cpp:171: error: expected initializer before ‘:’ token
src/ast.cpp:174: error: expected primary-expression before ‘return’
src/ast.cpp:174: error: expected ‘;’ before ‘return’
src/ast.cpp:174: error: expected primary-expression before ‘return’
src/ast.cpp:174: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘virtual bool Sass::Compound_Selector::has_real_parent_ref() const’:
src/ast.cpp:179: error: expected initializer before ‘:’ token
src/ast.cpp:182: error: expected primary-expression before ‘return’
src/ast.cpp:182: error: expected ‘;’ before ‘return’
src/ast.cpp:182: error: expected primary-expression before ‘return’
src/ast.cpp:182: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘virtual bool Sass::Compound_Selector::is_superselector_of(Sass::Selector_List_Obj, std::string)’:
src/ast.cpp:846: error: expected initializer before ‘:’ token
src/ast.cpp:849: error: expected primary-expression before ‘return’
src/ast.cpp:849: error: expected ‘;’ before ‘return’
src/ast.cpp:849: error: expected primary-expression before ‘return’
src/ast.cpp:849: error: expected ‘)’ before ‘return’
src/ast.cpp: In member function ‘Sass::Selector_List* Sass::Complex_Selector::resolve_parent_refs(std::vector<Sass::SharedImpl<Sass::Selector_List>, std::allocator<Sass::SharedImpl<Sass::Selector_List> > >&, Sass::Backtraces&, bool)’:
src/ast.cpp:1408: error: expected initializer before ‘:’ token
src/ast.cpp:2226: error: expected primary-expression at end of input
src/ast.cpp:2226: error: expected ‘;’ at end of input
src/ast.cpp:2226: error: expected primary-expression at end of input
src/ast.cpp:2226: error: expected ‘)’ at end of input
src/ast.cpp:2226: error: expected statement at end of input
src/ast.cpp:2226: error: expected ‘}’ at end of input
src/ast.cpp:2226: error: expected ‘}’ at end of input
src/ast.cpp: At global scope:
src/ast.cpp:2226: error: expected ‘}’ at end of input
src/units.hpp:11: warning: ‘Sass::PI’ defined but not used
make: *** [src/ast.o] Error 1
rake aborted!
Command failed with status (2): [make lib/libsass.so...]
/usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/lib/tasks/libsass.rb:31:in `block (2 levels) in <top (required)>'
/usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/lib/tasks/libsass.rb:13:in `block (3 levels) in <top (required)>'
/usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1/lib/tasks/libsass.rb:12:in `block (2 levels) in <top (required)>'
Tasks: TOP => lib/libsass.so
(See full trace by running task with --trace)

rake failed, exit code 1

Gem files will remain installed in /usr/local/rvm/gems/ruby-2.6.2/gems/sassc-2.0.1 for inspection.
Results logged to /usr/local/rvm/gems/ruby-2.6.2/extensions/x86_64-linux/2.6.0/sassc-2.0.1/gem_make.out

经排查,是因为GCC的版本过低导致的。

按照这个步骤,检查下GCC版本,如果是同样的版本和报错,那么可以参考以下的解决方法:

1
2
[[email protected] ~]# gcc --version | head -n1
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23)

如果GCC是这个版本,那就安装新版本的的GCC:

1
2
yum install centos-release-scl-rh
yum install devtoolset-7-gcc devtoolset-7-gcc-c++ devtoolset-7-binutils

安装好以后,再次配置GCC环境并检查版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
[[email protected] ~]# cat << _EOF_ > /etc/profile.d/devtoolset.sh
> #!/bin/bash
> source scl_source enable devtoolset-7
> _EOF_
[[email protected] ~]#
[[email protected] ~]# gcc --version | head -n1
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23)
[[email protected] ~]# cat /etc/profile.d/devtoolset.sh
#!/bin/bash
source scl_source enable devtoolset-7
[[email protected] ~]# source /etc/profile.d/devtoolset.sh
[[email protected] ~]# gcc --version | head -n1
gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)

确认GCC配置好以后,再次执行bundle或者执行gem install sassc来安装即可。

随着现代浏览器性能的提升,前端工程师设计出的交互方式也多种多样。其中瀑布流方式滚动更新加载已经是一种常见的Web前端交互方式了。

然而在Rails中如何实现这样一种随着用户滚动页面就能自动追加内容到页面的方式呢?

有一些现成的Gem可以推荐,例如jquery-infinite-pageswill_paginate_infinite等。不过我觉得它们使用比较复杂,不如自己去实现一个。

本文既然提到最方便,自然是需要用一种最小化改动的方式来实现这样的功能。

具体如何实现,请往下看。

首先假设我们要实现瀑布流式动态更新的对象是Post(或者是Article、News或者其他),第一步我们需要在Gemfile中加入以下两个Gem:

1
2
gem 'will_paginate'
gem 'bootstrap-will_paginate'

然后执行bundle,接着去修改posts_controller.rb,修改其中的index方法:

1
2
3
4
5
6
7
8
def index
@posts = Post.all.paginate(:page => params[:page], :per_page => 10)

respond_to do |format|
format.html
format.js
end
end

这里由于我们增加了js的渲染格式,所以要去views/posts中添加一个index.js.erb模板文件,内容如下:

1
2
3
4
5
6
7
$('#posts_list').append('<%= j render @posts %>');
<% if @posts.next_page %>
$('.pagination').replaceWith('<%= j will_paginate @posts %>');
<% else %>
$(window).off('scroll');
$('.pagination').remove();
<% end %>

上面的代码通过js定位页面中的posts_list作为要追加元素的目标,所以我们稍微修改一下views/posts/index.html.erb,在其中加入posts_list元素:

1
2
3
4
5
6
7
8

<div id="posts_list">
<%= render @posts %>
</div>

<div id="infinite-scrolling">
<%= will_paginate %>
</div>

在这段代码中,我们将@posts集合交给其他模板去渲染了,而这里暂时还没有用来渲染@posts的模板,所以要在views/posts中创建一个_post.html.erb模板文件,内容如下:

1
2
3
4
5
<div>
<h3><%= post.title %></h3>
<p><%= post.content %></p>
<hr/>
</div>

就这么简单,用来输出标题和内容。

最后关键的一步,需要创建一个事件监听器来捕获页面的滚动变化,所以在assets/javascripts/posts.coffee中,加入以下代码:

1
2
3
4
5
6
7
8
9

$(document).on "turbolinks:load", ->
$(window).on 'scroll', ->
more_posts_url = $('.pagination .next_page a').attr('href')
if more_posts_url && $(window).scrollTop() > $(document).height() - $(window).height() - 60
$('.pagination').html('<img src="/assets/ajax-loader.gif" alt="Loading..." title="Loading..." />')
$.getScript more_posts_url
return
return

如此一来,就实现了通过ajax方式请求原来需要在下一页展现内容,并把内容追加到index.html的文章列表中,也就实现了瀑布流加载了。

一切修改好以后,重启Rails服务,在页面滚动一下试试吧。

本方法参考自https://www.sitepoint.com/infinite-scrolling-rails-basics/

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×