README.md 4.5 KB
Newer Older
Ondřej Moravčík's avatar
Ondřej Moravčík committed
1 2 3 4
# Rys

Name is a big mistery. Do not bother to figure it out :-).

Ondřej Moravčík's avatar
Ondřej Moravčík committed
5
Library is similar to Railties but within Redmine environment.
Ondřej Moravčík's avatar
Ondřej Moravčík committed
6

Ondřej Moravčík's avatar
Ondřej Moravčík committed
7
- plugin generator
Ondřej Moravčík's avatar
Ondřej Moravčík committed
8 9 10 11 12 13 14
- feature toggler
- patcher manager
- interface to Redmine

All you need to do is insert `gem 'rys'` into your Gemfile. If you want develop this gem or its plugis locally you can set bundler:

`bundle config local.GEM_NAME GEM_PATH`
Ondřej Moravčík's avatar
Ondřej Moravčík committed
15

Ondřej Moravčík's avatar
Ondřej Moravčík committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
#### Dependecies

Install all dependecies are not so easy like with redmine plugins. For this purpose check gem `rys-bundler`.

## Rys plugins

Target directory can be set via option `--path` or via environment varible `RYS_PLUGINS_PATH`. Otherwise `RAILS_ROOT/rys_plugins` is chosen.

```
rails generate rys:plugin --help
rails generate rys:plugin NAME
```

Also gem is automatically appended into `Gemfile.local`.

Ondřej Moravčík's avatar
Ondřej Moravčík committed
31 32
## Features

Ondřej Moravčík's avatar
Ondřej Moravčík committed
33
You can toggle some code base on database state or by custom definiton. First you need to register features.
Ondřej Moravčík's avatar
Ondřej Moravčík committed
34 35 36 37 38 39 40

```ruby
# Basic definition
# This feature will be active if record on the DB will have active == true
Rys::Feature.add('issue.show')
```

Ondřej Moravčík's avatar
Ondřej Moravčík committed
41
All features have tree structure so if parent is disabled all children are disabled too. For example:
Ondřej Moravčík's avatar
Ondřej Moravčík committed
42 43 44 45 46 47 48 49 50 51 52 53

```ruby
Rys::Feature.add('issue.show')
Rys::Feature.add('issue.show.sidebar')

# issue
# `-- issue.show
#     `-- issue.show.sidebar
```

If `issue` is disabled -> all `issue.*` are disabled too regardless to theirs state.

Ondřej Moravčík's avatar
Ondřej Moravčík committed
54
You can check feature state via:
Ondřej Moravčík's avatar
Ondřej Moravčík committed
55 56 57 58 59 60 61 62 63 64 65

```ruby
Rys::Feature.on('issue.show') do
  # issue.show is active
end

if Rys::Feature.active?('issue.show')
  # issue.show is active
end
```

Ondřej Moravčík's avatar
Ondřej Moravčík committed
66
### In routes
Ondřej Moravčík's avatar
Ondřej Moravčík committed
67 68 69 70 71 72 73 74 75

```ruby
get 'path', rys_feature: 'issue.show'

rys_feature 'issue.show' do
  get 'path'
end
```

Ondřej Moravčík's avatar
Ondřej Moravčík committed
76
### In patches
Ondřej Moravčík's avatar
Ondřej Moravčík committed
77

Ondřej Moravčík's avatar
Ondřej Moravčík committed
78
More details can be found at Patch manager section.
Ondřej Moravčík's avatar
Ondřej Moravčík committed
79

Ondřej Moravčík's avatar
Ondřej Moravčík committed
80
```ruby
Ondřej Moravčík's avatar
Ondřej Moravčík committed
81 82
instance_methods(feature: 'issue.show') do
  def show
Ondřej Moravčík's avatar
Ondřej Moravčík committed
83
    # Something todo
Ondřej Moravčík's avatar
Ondřej Moravčík committed
84 85 86 87 88 89 90
    # if feature is active
    super
  end
end
```


Ondřej Moravčík's avatar
Ondřej Moravčík committed
91
### Custom condition
Ondřej Moravčík's avatar
Ondřej Moravčík committed
92

Ondřej Moravčík's avatar
Ondřej Moravčík committed
93
If you don't want to use DB record checking you can define custom condition.
Ondřej Moravčík's avatar
Ondřej Moravčík committed
94 95 96 97 98 99 100 101

```ruby
# Ruby block state
Rys::Feature.add('issue.show') do
  rand(0..10) == 1
end
```

Ondřej Moravčík's avatar
Ondřej Moravčík committed
102
Or you can use both approaches with:
Ondřej Moravčík's avatar
Ondřej Moravčík committed
103 104 105 106 107 108 109

```ruby
Rys::Feature.add('issue.show') do
  rand(0..10) == 1 && RysFeatureRecord.active?('issue.show')
end
```

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
## Translations

All features have title and description. You can set them via language file or via options.

```ruby
Rys::Feature.add('issue.show')
# => I18n.t 'rys_features.issue_show.title'
# => I18n.t 'rys_features.issue_show.description'

Rys::Feature.add('issue.show', title: :feature_title,
                               description: :feature_description)
# => I18n.t 'feature_title'
# => I18n.t 'feature_description'
```

Ondřej Moravčík's avatar
Ondřej Moravčík committed
125 126 127 128 129 130 131 132
# Patch manager

You can easily define patches for your Rails projects in just two steps.

First you need to register path to directory

```ruby
# extend your engine
Ondřej Moravčík's avatar
Ondřej Moravčík committed
133
include ::Rys::EngineExtensions
Ondřej Moravčík's avatar
Ondřej Moravčík committed
134 135 136 137 138

# or manually
Rys::Patcher.paths << PATH_TO_DIRECTORY
```

Ondřej Moravčík's avatar
Ondřej Moravčík committed
139
Now you can define a patch
Ondřej Moravčík's avatar
Ondřej Moravčík committed
140 141 142 143

```ruby
Rys::Patcher.add(CLASS_TO_PATCH) do

Ondřej Moravčík's avatar
Ondřej Moravčík committed
144 145
  where WHERE

Ondřej Moravčík's avatar
Ondřej Moravčík committed
146 147 148 149 150 151
  apply_only_once!

  apply_if do
    CONDITION
  end

Ondřej Moravčík's avatar
Ondřej Moravčík committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
  included do
    # This section is evaluated in CLASS_TO_PATCH
  end

  instance_methods do
    # Your instance methods
  end

  instance_methods(feature: FEATURE) do
    # Your conditional methods
  end

  class_methods do
    # Your class methods
  end

end

```

So your patch can look like this

```ruby
Rys::Patcher.add('IssuesController') do

  included do
    before_action :add_flash_notice, only: [:show]
  end

  instance_methods do

    def show
      flash.now[:notice] = 'Hello'
      super
    end

  end
end
```

Ondřej Moravčík's avatar
Ondřej Moravčík committed
192 193
#### Generating

Ondřej Moravčík's avatar
Ondřej Moravčík committed
194
Patches can be generated via command:
Ondřej Moravčík's avatar
Ondřej Moravčík committed
195 196 197 198 199 200 201 202 203

```
rails generate rys:patch TYPE PLUGIN NAME

rails generate rys:patch m RYS_PLUGIN_NAME Issue
rails generate rys:patch model RYS_PLUGIN_NAME Issue
rails generate rys:patch helper RYS_PLUGIN_NAME Issues
```

Ondřej Moravčík's avatar
Ondřej Moravčík committed
204 205 206 207 208 209
Or you can use interactive generator

```
rails generate rys:ipatch
```

Ondřej Moravčík's avatar
Ondřej Moravčík committed
210
### Rails generators
Ondřej Moravčík's avatar
Ondřej Moravčík committed
211

Ondřej Moravčík's avatar
Ondřej Moravčík committed
212
You can use the same generator like in any Rails plugin. Just add prefix `rys` and specify Rys plugin name.
Ondřej Moravčík's avatar
Ondřej Moravčík committed
213 214

```
Ondřej Moravčík's avatar
Ondřej Moravčík committed
215 216 217
rails generate rys:model RYS_PLUGIN_NAME ...normal arguments...
rails generate rys:scaffold RYS_PLUGIN_NAME ...normal arguments...
rails generate rys:controller RYS_PLUGIN_NAME ...normal arguments...
Ondřej Moravčík's avatar
Ondřej Moravčík committed
218
```
Lukáš Pokorný's avatar
Lukáš Pokorný committed
219

Lukáš Pokorný's avatar
Lukáš Pokorný committed
220
### TESTS
Lukáš Pokorný's avatar
Lukáš Pokorný committed
221 222 223 224 225 226 227 228 229 230

Tests requires gem `easy_core` !
TODO: link na easy_core repo ;)

  1. Setup dummy app (export DUMMY_PATH env OR test/dummy folder...)
  2. Make sure both (dummy and rys) have cleared `.bundle`, `Gemfile.lock`, `gems.locked`
  3. In RYS plugin run `rake app:db:migrate` follow by `rake app:db:test:prepare`
  4. Feel free tu run `rspec`