是的,puts 会判断参数是否为数组,如果是的话 puts a 相当于 puts *a
安装 pry-doc, 然后
show-method $stdout.puts
可以看到其 C 实现
各数据库的组装方式不同,代码在它们的 driver 中
挖到一个坟... https://ruby-china.org/topics/9333
不用急,学点基础课再做东西,不然做了几年发现基础不好又多花时间回去补
数据库 pg/mysql/mongodb 都可自己生成 , pg/mongodb 有专门的 uuid 类型,占用存储空间少一半
但数据库其实往往用的 uuid-ossp, ruby 也有这个 gem, 不需要和数据库通信生成速度自然快很多
如果要保证全局唯一性,得自己来制定生成规则
存储或检查密码的瓶颈在 bcrypt, 因为 bcrypt 的 feature 就是慢,快就不安全了... 非密码请求的一大瓶颈在 session 的验证和签名,慢在 OpenSSL 和 Rack 里
devise 管得太宽 (last_login_at 这些东西其实让专门的用户行为追踪去做更好) 从前到后入侵太严重 (为啥要做一套模板?还要载入我不需要的模板引擎,和我不需要的 i18n 数据) 处理过程太黑箱,调用栈过深,定制只能通读 devise 源码并且复制修改 devise 源码,你还得熟悉 warden, 定制完了要升级 devise 自然兼容很有问题
我觉得最适合 devise 和 warden 的场景是只有搭 demo
把接口 1 提出一个方法,接口 2 直接调用这个方法,不要自己通过网络请求自己
你对自己说三遍好了为什么要对别人说多余的那两遍...
"abcd123".unpack('B*').first.scan /(.{4})(.{4})/ do |a,b|
print "#{a} #{b} "
end
正确的做法是漏水桶模型 https://en.wikipedia.org/wiki/Leaky_bucket
nginx 的 http_limit_req 模块就是这么做的 http://nginx.org/en/docs/http/ngx_http_limit_req_module.html 但是不好配置成针对单用户 id 的
简单的做法可以用 https://github.com/bendiken/rack-throttle 然后设置 client_identifier 不过就不是 leaky bucket 了
自己实现可以更灵活更核心一点
每个用户保存两个字段
bucket:float
bucket_updated_at:time
每次请求的时候
user.bucket = user.bucket - (Time.now - user.bucket_updated_at) * leaking_rate + 1
user.bucket = 0 if user.bucket < 0
user.bucket_updated_at = Time.now
如果 bucket 满 (大于一个设定值) 就拒绝请求
如果只是不管时间间隔,三次就锁定,在用户表中加个连续失败计数字段就可以,并且在成功登录时清空
这个是生成的你不用管它,你写的 bin 文件直接用 require_relative
引用 lib 的文件就可以了
修改 load path 就可以,不用 install 一次
例如
$:.unshift "./lib"
require 'yourgem'
至于可执行文件的情况,你说的是 extension?
#5 楼 @blacktulip false
和 nil
都是 false-y, 其他都是 true-y
#3 楼 @blacktulip 他的逻辑没检查 nil 就照抄了...
不能再简单了吧... 最多挤成一行但逻辑并没有简化
另外,可以用 nested select 减少一个查询?
Circle.in id: (status ? memberships.where(status: status) : memberships).select(:circle_id)
#5 楼 @deathking 是好是坏得看使用者... 如果重载的各个函数定义在了不同的地方会不会坑?
class A
def foo x
x
end
end
module B
def foo x, y=nil
y
end
end
class C < A
include B
def foo x
x
end
end
Crystal 应该是限制最宽松的静态语言了... 但要成功,得把 method name resolution 的规则做好,和加上 pattern match
可是 Ruby 代码一般不是右边那么写的...
def sum x, y=nil
x.to_i + y.to_i
end
其实 Ruby 的 bignum 实现用到的一个 bitset 的函数 nlz 可以调用 GCC 的 __builtin_clz, 而 __builtin_clz 会转换成处理器的 bsr/clz 指令,用 bitset 做这个运算,就可以少用很多内存,降低程序的 memory bandwidth. 而且 128 bit 的 clz 指令可以把第二次遍历的最后一次运算降低到 1/128
不过 bignum 并没有暴露 "set nth bit" 的 interface... 就做不到 C 的程度了
bitset + __builtin_clz:
#include <stdlib.h>
#include <memory.h>
typedef unsigned long l;
int firstMissingPositive(int* nums, int numsSize) {
if (!numsSize) {
return 1;
}
int llen = ((numsSize + sizeof(l) - 1) / sizeof(l));
int lbits = sizeof(l) * 8;
l* arr = malloc((llen + 1) * sizeof(l));
// unset first bit
memset(arr, 0xFF, (llen + 1) * sizeof(l));
arr[0] &= ~(1UL << (lbits - 1));
for (int i = 0; i < numsSize; i++) {
if (nums[i] > 0) {
int j = nums[i] / lbits;
int k = nums[i] % lbits;
arr[j] &= ~(1UL << ((lbits - 1) - k));
}
}
int res = 0;
for (int i = 0; i < llen; i++) {
if (arr[i]) {
res += __builtin_clzl(arr[i]);
break;
} else {
res += lbits;
}
}
free(arr);
return res;
}
3.2 这样比较简单
def first_missing_positive(nums)
b = Array.new nums.size + 1
b[0] = true
nums.each do |n|
b[n] = true if n > 0
end
b.index nil or b.size
end
循环体内尽量少做运算就可以
变量名用 snake case 更好些...
#10 楼 @killernova [s].pack('H*')
#8 楼 @killernova 写错了... 是 unpack
#6 楼 @killernova 这个不是 base64, 是 hex 表示,两个十六进制字符表示一个字节 (16*16=256)
"5\xD564\xCC\rf\xC4\xEE\x9A\xDB\x03".pack('h*')[0]
不是乱码,程序没问题,想好看点就 base64 呗
def encrypt64 s
Base64.encode64 encrypt s
end
def decrypt64 s
encrypt Base64.decode64 s
end