# Developing with feature flags

> 原文：[https://docs.gitlab.com/ee/development/feature_flags/development.html](https://docs.gitlab.com/ee/development/feature_flags/development.html)

*   [Feature groups](#feature-groups)
    *   [Frontend](#frontend)
    *   [Specs](#specs)
    *   [`stub_feature_flags: true` (default and preferred)](#stub_feature_flags-true-default-and-preferred)
    *   [`stub_feature_flags: false`](#stub_feature_flags-false)
    *   [Enabling a feature flag (in development)](#enabling-a-feature-flag-in-development)

# Developing with feature flags[](#developing-with-feature-flags "Permalink")

通常，最好有一个基于组或基于用户的门，并且您应该比使用百分比门更好. 这将使调试更加容易，因为您也可以根据参与者过滤示例日志和错误. 此外，这允许首先启用`gitlab-org`或`gitlab-com`组，而其余用户则`gitlab-com` .

```
# Good
Feature.enabled?(:feature_flag, project)

# Avoid, if possible
Feature.enabled?(:feature_flag) 
```

要使用基于角色的特征门，模型需要响应`flipper_id` . 例如，要启用 Foo 模型：

```
class Foo < ActiveRecord::Base
  include FeatureGate
end 
```

只有`include FeatureGate`或公开的`flipper_id`方法的模型才能用作`Feature.enabled?` `flipper_id` `Feature.enabled?` .

已开发并打算在功能标记后合并的功能不应包含变更日志条目. 该条目应添加到删除功能部件标记的合并请求中，或在功能部件标记的默认值设置为 true 的合并请求中添加. 如果功能包含任何数据库迁移，则该功能应包括数据库更改的更改日志条目.

如果您需要功能标记自动打开，请在检查以下内容时使用`default_enabled: true` ：

```
Feature.enabled?(:feature_flag, project, default_enabled: true) 
```

[`Project#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/app/models/project_feature.rb#L63-68) ， [`Namespace#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/ee/namespace.rb#L71-85) （EE）和[`License.feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/license.rb#L293-300) （EE）方法都隐式检查默认情况下启用的功能标志，该标志与提供的参数同名.

例如，如果某个功能是许可门控的，则无需添加其他显式功能标志检查，因为该标志将作为`License.feature_available?`一部分进行检查`License.feature_available?` 呼叫. 同样，功能达到通用状态后，也无需"清理"功能标志.

您是否仍想使用显式`Feature.enabled?` 检查您的新功能是否不受许可或计划的限制.

**上面提到的隐式功能标志的一个重要副作用是，除非功能被明确禁用或限制为一定比例的用户，否则功能标志检查将默认为`true` .**

当使用[几个较小的合并请求](https://about.gitlab.com/handbook/values/#make-small-merge-requests)开发功能时，或者当该功能被视为[alpha 或 beta 时](https://about.gitlab.com/handbook/product/#alpha-beta-ga) ，这是相关的，并且默认情况下不可用.

例如，如果要交付功能的前端一半而没有后端，则希望完全禁用该功能，直到也可以交付后端一半. 要确保 GitLab.com 和自我管理实例均禁用此功能，应使用[`Namespace#alpha_feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/458749872f4a8f27abe8add930dbb958044cb926/ee/app/models/ee/namespace.rb#L113) 或[`Namespace#beta_feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/458749872f4a8f27abe8add930dbb958044cb926/ee/app/models/ee/namespace.rb#L100-112) 方法，根据我们的[定义](https://about.gitlab.com/handbook/product/#alpha-beta-ga) . 这样可以确保禁用功能，除非*明确*启用了功能标志.

## Feature groups[](#feature-groups "Permalink")

从 GitLab 9.4 开始，我们通过[Flipper 组](https://github.com/jnunemaker/flipper/blob/v0.10.2/docs/Gates.md#2-group)支持功能[组](https://github.com/jnunemaker/flipper/blob/v0.10.2/docs/Gates.md#2-group) .

功能组必须在`lib/feature.rb` （在`.register_feature_groups`方法中）静态定义，但是它们的实现显然可以是动态的（查询数据库等）.

在`lib/feature.rb`定义后，您将能够通过[features API](../../api/features.html#set-or-create-a-feature)的[`feature_group`参数](../../api/features.html#set-or-create-a-feature)激活给定功能组[的功能](../../api/features.html#set-or-create-a-feature)

### Frontend[](#frontend "Permalink")

对于前端代码，可以使用方法`push_frontend_feature_flag` ，该方法适用于所有从`ApplicationController`继承的控制器. 使用此方法，可以按如下所示公开功能部件标志的状态：

```
before_action do
  # Prefer to scope it per project or user e.g.
  push_frontend_feature_flag(:vim_bindings, project)

  # Avoid, if possible
  push_frontend_feature_flag(:vim_bindings)
end

def index
  # ...
end

def edit
  # ...
end 
```

然后，您可以按照以下步骤检查 JavaScript 中功能部件标志的状态：

```
if ( gon.features.vimBindings ) {
  // ...
} 
```

JavaScript 中的功能标志的名称将始终为 camelCased，这意味着检查`gon.features.vim_bindings`将不起作用.

有关如何访问 Vue 组件中的功能标志的详细信息，请参见[Vue 指南](../fe_guide/vue.html#accessing-feature-flags) .

### Specs[](#specs "Permalink")

我们在测试环境中的 Flipper 引擎以`Flipper::Adapters::Memory`的内存模式工作. `production`和`development`模式使用`Flipper::Adapters::ActiveRecord` .

### `stub_feature_flags: true` (default and preferred)[](#stub_feature_flags-true-default-and-preferred "Permalink")

在此模式下，将 Flipper 配置为使用`Flipper::Adapters::Memory`并将所有功能标志标记为默认状态，并在首次使用时保持不变. 这将覆盖`Feature.enabled?`的`default_enabled:` `Feature.enabled?` 和`Feature.disabled?` 除非功能标记持续存在，否则始终返回`true` .

Make sure behavior under feature flag doesn’t go untested in some non-specific contexts.

有关如何在测试中添加功能标志的信息和示例，请参见[测试指南](../testing_guide/best_practices.html#feature-flags-in-tests) .

### `stub_feature_flags: false`[](#stub_feature_flags-false "Permalink")

这将禁用存储在内存中的鳍状肢，并使用`Flipper::Adapters::ActiveRecord`一种`production`和`development`所使用的模式.

仅当您确实想测试 Flipper 的各个方面及其与`ActiveRecord`交互方式时，才应使用此模式.

### Enabling a feature flag (in development)[](#enabling-a-feature-flag-in-development "Permalink")

在 rails 控制台（ `rails c` ）中，输入以下命令以启用功能部件标志

```
Feature.enable(:feature_flag_name) 
```

同样，以下命令将禁用功能部件标志：

```
Feature.disable(:feature_flag_name) 
```

您也可以为给定的门启用功能标志：

```
Feature.enable(:feature_flag_name, Project.find_by_full_path("root/my-project")) 
```