[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7900":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":15,"stars30d":15,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":16,"rankGlobal":10,"rankLanguage":10,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":18,"hasPages":18,"topics":20,"createdAt":10,"pushedAt":10,"updatedAt":25,"readmeContent":26,"aiSummary":27,"trendingCount":15,"starSnapshotCount":15,"syncStatus":28,"lastSyncTime":29,"discoverSource":30},7900,"rollout","fetlife\u002Frollout","fetlife","Feature flippers.","",null,"Ruby",2904,215,61,0,29,"MIT License",false,"master",[21,22,23,5,24],"feature-flags","percentage","redis","ruby","2026-06-12 02:01:46","# rollout\n\nFast feature flags based on Redis.\n\n[![Gem Version](https:\u002F\u002Fbadge.fury.io\u002Frb\u002Frollout.svg)](https:\u002F\u002Fbadge.fury.io\u002Frb\u002Frollout)\n[![CI](https:\u002F\u002Fgithub.com\u002Ffetlife\u002Frollout\u002Factions\u002Fworkflows\u002Ftest.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Ffetlife\u002Frollout\u002Factions\u002Fworkflows\u002Ftest.yml)\n[![Code Climate](https:\u002F\u002Fcodeclimate.com\u002Fgithub\u002FFetLife\u002Frollout\u002Fbadges\u002Fgpa.svg)](https:\u002F\u002Fcodeclimate.com\u002Fgithub\u002FFetLife\u002Frollout)\n[![Test Coverage](https:\u002F\u002Fcodeclimate.com\u002Fgithub\u002FFetLife\u002Frollout\u002Fbadges\u002Fcoverage.svg)](https:\u002F\u002Fcodeclimate.com\u002Fgithub\u002FFetLife\u002Frollout\u002Fcoverage)\n\n## Install it\n\n```bash\ngem install rollout\n```\n\n## How it works\n\nInitialize a rollout object. I assign it to a global var.\n\n```ruby\nrequire 'redis'\n\n$redis = Redis.new\n$rollout = Rollout.new($redis)\n```\n\nor even simpler\n\n```ruby\nrequire 'redis'\n$rollout = Rollout.new($redis) # Will use REDIS_URL env var or default redis url\n```\n\n\nUpdate data specific to a feature:\n\n```ruby\n$rollout.set_feature_data(:chat, description: 'foo', release_date: 'bar', whatever: 'baz')\n```\n\nCheck whether a feature is active for a particular user:\n\n```ruby\n$rollout.active?(:chat, User.first) # => true\u002Ffalse\n```\n\nCheck whether a feature is active globally:\n\n```ruby\n$rollout.active?(:chat)\n```\n\nYou can activate features using a number of different mechanisms.\n\n## Groups\n\nRollout ships with one group by default: \"all\", which does exactly what it\nsounds like.\n\nYou can activate the all group for the chat feature like this:\n\n```ruby\n$rollout.activate_group(:chat, :all)\n```\n\nYou might also want to define your own groups. We have one for our caretakers:\n\n```ruby\n$rollout.define_group(:caretakers) do |user|\n  user.caretaker?\nend\n```\n\nYou can activate multiple groups per feature.\n\nDeactivate groups like this:\n\n```ruby\n$rollout.deactivate_group(:chat, :all)\n```\n\nGroups need to be defined every time your app starts. The logic is not persisted\nanywhere.\n\n## Specific Users\n\nYou might want to let a specific user into a beta test or something. If that\nuser isn't part of an existing group, you can let them in specifically:\n\n```ruby\n$rollout.activate_user(:chat, @user)\n```\n\nDeactivate them like this:\n\n```ruby\n$rollout.deactivate_user(:chat, @user)\n```\n\n## User Percentages\n\nIf you're rolling out a new feature, you might want to test the waters by\nslowly enabling it for a percentage of your users.\n\n```ruby\n$rollout.activate_percentage(:chat, 20)\n```\n\nThe algorithm for determining which users get let in is this:\n\n```ruby\nCRC32(user.id) \u003C (2**32 - 1) \u002F 100.0 * percentage\n```\n\nSo, for 20%, users 0, 1, 10, 11, 20, 21, etc would be allowed in. Those users\nwould remain in as the percentage increases.\n\nDeactivate all percentages like this:\n\n```ruby\n$rollout.deactivate_percentage(:chat)\n```\n\n_Note that activating a feature for 100% of users will also make it active\n\"globally\". That is when calling Rollout#active? without a user object._\n\nIn some cases you might want to have a feature activated for a random set of\nusers. It can come specially handy when using Rollout for split tests.\n\n```ruby\n$rollout = Rollout.new($redis, randomize_percentage: true)\n```\n\nWhen on `randomize_percentage` will make sure that 50% of users for feature A\nare selected independently from users for feature B.\n\n## Global actions\n\nWhile groups can come in handy, the actual global setter for a feature does not require a group to be passed.\n\n```ruby\n$rollout.activate(:chat)\n```\n\nIn that case you can check the global availability of a feature using the following\n\n```ruby\n$rollout.active?(:chat)\n```\n\nAnd if something is wrong you can set a feature off for everybody using\n\nDeactivate everybody at once:\n\n```ruby\n$rollout.deactivate(:chat)\n```\n\nFor many of our features, we keep track of error rates using redis, and\ndeactivate them automatically when a threshold is reached to prevent service\nfailures from cascading. See https:\u002F\u002Fgithub.com\u002Fjamesgolick\u002Fdegrade for the\nfailure detection code.\n\n## Check Rollout Feature\n\nYou can inspect the state of your feature using:\n\n```ruby\n>> $rollout.get(:chat)\n=> #\u003CRollout::Feature:0x00007f99fa4ec528 @data={}, @groups=[:caretakers], @name=:chat, @options={}, @percentage=0.05, @users=[\"1\"]>\n```\n\n## Namespacing\n\nRollout separates its keys from other keys in the data store using the\n\"feature\" keyspace.\n\nIf you're using redis, you can namespace keys further to support multiple\nenvironments by using the\n[redis-namespace](https:\u002F\u002Fgithub.com\u002Fresque\u002Fredis-namespace) gem.\n\n```ruby\n$ns = Redis::Namespace.new(Rails.env, redis: $redis)\n$rollout = Rollout.new($ns)\n$rollout.activate_group(:chat, :all)\n```\n\nThis example would use the \"development:feature:chat:groups\" key.\n\n## Frontend \u002F UI\n\n* [rollout-ui](https:\u002F\u002Fgithub.com\u002Ffetlife\u002Frollout-ui)\n* [Rollout-Dashboard](https:\u002F\u002Fgithub.com\u002Ffiverr\u002Frollout_dashboard\u002F)\n\n## Implementations in other languages\n\n*   Python: https:\u002F\u002Fgithub.com\u002Fasenchi\u002Fproclaim\n*   PHP: https:\u002F\u002Fgithub.com\u002Fopensoft\u002Frollout\n*   Clojure: https:\u002F\u002Fgithub.com\u002Fyeller\u002Fshoutout\n*   Perl: https:\u002F\u002Fmetacpan.org\u002Fpod\u002FToggle\n*   Golang: https:\u002F\u002Fgithub.com\u002FSalesLoft\u002Fgorollout\n\n\n## Contributors\n\n*   James Golick - Creator - https:\u002F\u002Fgithub.com\u002Fjamesgolick\n*   Eric Rafaloff - Maintainer - https:\u002F\u002Fgithub.com\u002FEricR\n\n\n## Releasing\n\n1. Bump version: `rake version:patch` (or `minor`\u002F`major`)\n2. Commit and tag: `git commit -am \"Bump version\" && git tag v0.7.3`\n3. Push: `git push origin master --tags`\n\nThe GitHub Actions workflow will automatically publish to RubyGems when tags are pushed.\n\n## Copyright\n\nCopyright (c) 2010-InfinityAndBeyond BitLove, Inc. See LICENSE for details.\n","rollout 是一个基于 Redis 的快速特性开关工具。它允许开发者通过定义用户组、特定用户或百分比等方式灵活地控制特性的启用状态，支持按需逐步向用户开放新功能或进行A\u002FB测试。项目采用Ruby语言编写，具有高性能和易用性特点，并且提供了丰富的API来管理特性标志及其元数据。适用于需要精细化管理软件发布过程、实施灰度发布策略或进行功能实验的场景。",2,"2026-06-11 03:14:59","top_language"]