Description:
tag
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r681:bc0fcfe3abaa - - 23 files changed: 283 inserted, 3 deleted

@@ -0,0 +1,3
1 + # Place all the behaviors and hooks related to the matching controller here.
2 + # All this logic will automatically be available in application.js.
3 + # You can use CoffeeScript in this file: http://coffeescript.org/
@@ -0,0 +1,3
1 + // Place all the styles related to the tags controller here.
2 + // They will automatically be included in application.css.
3 + // You can use Sass (SCSS) here: http://sass-lang.com/
@@ -0,0 +1,58
1 + class TagsController < ApplicationController
2 + before_action :set_tag, only: [:show, :edit, :update, :destroy]
3 +
4 + # GET /tags
5 + def index
6 + @tags = Tag.all
7 + end
8 +
9 + # GET /tags/1
10 + def show
11 + end
12 +
13 + # GET /tags/new
14 + def new
15 + @tag = Tag.new
16 + end
17 +
18 + # GET /tags/1/edit
19 + def edit
20 + end
21 +
22 + # POST /tags
23 + def create
24 + @tag = Tag.new(tag_params)
25 +
26 + if @tag.save
27 + redirect_to @tag, notice: 'Tag was successfully created.'
28 + else
29 + render :new
30 + end
31 + end
32 +
33 + # PATCH/PUT /tags/1
34 + def update
35 + if @tag.update(tag_params)
36 + redirect_to @tag, notice: 'Tag was successfully updated.'
37 + else
38 + render :edit
39 + end
40 + end
41 +
42 + # DELETE /tags/1
43 + def destroy
44 + @tag.destroy
45 + redirect_to tags_url, notice: 'Tag was successfully destroyed.'
46 + end
47 +
48 + private
49 + # Use callbacks to share common setup or constraints between actions.
50 + def set_tag
51 + @tag = Tag.find(params[:id])
52 + end
53 +
54 + # Only allow a trusted parameter "white list" through.
55 + def tag_params
56 + params.require(:tag).permit(:name, :description, :public)
57 + end
58 + end
@@ -0,0 +1,2
1 + module TagsHelper
2 + end
@@ -0,0 +1,8
1 + class ProblemTag < ActiveRecord::Base
2 + self.table_name = 'problems_tags'
3 +
4 + belongs_to :problem
5 + belongs_to :tag
6 +
7 + validates_uniqueness_of :problem_id, scope: :tag_id, message: ->(object, data) { "'#{Problem.find(data[:value]).full_name}' is already has this tag" }
8 + end
@@ -0,0 +1,4
1 + class Tag < ActiveRecord::Base
2 + has_many :problems_tags, class_name: ProblemTag
3 + has_many :problems, through: :problems_tags
4 + end
@@ -0,0 +1,22
1 + = form_for @tag do |f|
2 + - if @tag.errors.any?
3 + #error_explanation
4 + %h2= "#{pluralize(@tag.errors.count, "error")} prohibited this tag from being saved:"
5 + %ul
6 + - @tag.errors.full_messages.each do |msg|
7 + %li= msg
8 +
9 + .row
10 + .col-md-6
11 + .form-group.field
12 + = f.label :name
13 + = f.text_field :name, class: 'form-control'
14 + .form-group.field
15 + = f.label :description
16 + = f.text_area :description, class: 'form-control'
17 + .form-group.field
18 + = f.label :public
19 + = f.text_field :public, class: 'form-control'
20 + .actions
21 + = f.submit 'Save', class: 'btn btn-primary'
22 + .col-md-6
@@ -0,0 +1,7
1 + %h1 Editing tag
2 +
3 + = render 'form'
4 +
5 + = link_to 'Show', @tag
6 + \|
7 + = link_to 'Back', tags_path
@@ -0,0 +1,26
1 + %h1 Tags
2 +
3 + = link_to 'New Tag', new_tag_path, class: 'btn btn-success'
4 +
5 + %table.table.table-hover
6 + %thead
7 + %tr
8 + %th Name
9 + %th Description
10 + %th Public
11 + %th
12 + %th
13 + %th
14 +
15 + %tbody
16 + - @tags.each do |tag|
17 + %tr
18 + %td= tag.name
19 + %td= tag.description
20 + %td= tag.public
21 + %td= link_to 'Show', tag
22 + %td= link_to 'Edit', edit_tag_path(tag)
23 + %td= link_to 'Destroy', tag, :method => :delete, :data => { :confirm => 'Are you sure?' }
24 +
25 + %br
26 +
@@ -0,0 +1,5
1 + %h1 New tag
2 +
3 + = render 'form'
4 +
5 + = link_to 'Back', tags_path
@@ -0,0 +1,15
1 + %p#notice= notice
2 +
3 + %p
4 + %b Name:
5 + = @tag.name
6 + %p
7 + %b Description:
8 + = @tag.description
9 + %p
10 + %b Public:
11 + = @tag.public
12 +
13 + = link_to 'Edit', edit_tag_path(@tag)
14 + \|
15 + = link_to 'Back', tags_path
@@ -0,0 +1,11
1 + class CreateTags < ActiveRecord::Migration
2 + def change
3 + create_table :tags do |t|
4 + t.string :name, null: false
5 + t.text :description
6 + t.boolean :public
7 +
8 + t.timestamps null: false
9 + end
10 + end
11 + end
@@ -0,0 +1,10
1 + class CreateProblemTags < ActiveRecord::Migration
2 + def change
3 + create_table :problems_tags do |t|
4 + t.references :problem, index: true, foreign_key: true
5 + t.references :tag, index: true, foreign_key: true
6 +
7 + t.index [:problem_id,:tag_id], unique: true
8 + end
9 + end
10 + end
@@ -0,0 +1,49
1 + require 'test_helper'
2 +
3 + class TagsControllerTest < ActionController::TestCase
4 + setup do
5 + @tag = tags(:one)
6 + end
7 +
8 + test "should get index" do
9 + get :index
10 + assert_response :success
11 + assert_not_nil assigns(:tags)
12 + end
13 +
14 + test "should get new" do
15 + get :new
16 + assert_response :success
17 + end
18 +
19 + test "should create tag" do
20 + assert_difference('Tag.count') do
21 + post :create, tag: { description: @tag.description, name: @tag.name, public: @tag.public }
22 + end
23 +
24 + assert_redirected_to tag_path(assigns(:tag))
25 + end
26 +
27 + test "should show tag" do
28 + get :show, id: @tag
29 + assert_response :success
30 + end
31 +
32 + test "should get edit" do
33 + get :edit, id: @tag
34 + assert_response :success
35 + end
36 +
37 + test "should update tag" do
38 + patch :update, id: @tag, tag: { description: @tag.description, name: @tag.name, public: @tag.public }
39 + assert_redirected_to tag_path(assigns(:tag))
40 + end
41 +
42 + test "should destroy tag" do
43 + assert_difference('Tag.count', -1) do
44 + delete :destroy, id: @tag
45 + end
46 +
47 + assert_redirected_to tags_path
48 + end
49 + end
@@ -0,0 +1,9
1 + # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2 +
3 + one:
4 + problem_id:
5 + tag_id:
6 +
7 + two:
8 + problem_id:
9 + tag_id:
@@ -0,0 +1,11
1 + # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2 +
3 + one:
4 + name: MyString
5 + description: MyString
6 + public:
7 +
8 + two:
9 + name: MyString
10 + description: MyString
11 + public:
@@ -0,0 +1,7
1 + require 'test_helper'
2 +
3 + class ProblemTagTest < ActiveSupport::TestCase
4 + # test "the truth" do
5 + # assert true
6 + # end
7 + end
@@ -0,0 +1,7
1 + require 'test_helper'
2 +
3 + class TagTest < ActiveSupport::TestCase
4 + # test "the truth" do
5 + # assert true
6 + # end
7 + end
@@ -1,7 +1,7
1 1 class GroupUser < ActiveRecord::Base
2 2 self.table_name = 'groups_users'
3 -
3 +
4 4 belongs_to :user
5 5 belongs_to :group
6 6 validates_uniqueness_of :user_id, scope: :group_id, message: ->(object, data) { "'#{User.find(data[:value]).full_name}' is already in the group" }
7 7 end
@@ -1,57 +1,60
1 1 class Problem < ActiveRecord::Base
2 2
3 3 belongs_to :description
4 4 has_and_belongs_to_many :contests, :uniq => true
5 5
6 6 #has_and_belongs_to_many :groups
7 7 has_many :groups_problems, class_name: GroupProblem
8 8 has_many :groups, :through => :groups_problems
9 9
10 + has_many :problems_tags, class_name: ProblemTag
11 + has_many :tags, through: :problems_tags
12 +
10 13 has_many :test_pairs, :dependent => :delete_all
11 14 has_many :testcases, :dependent => :destroy
12 15
13 16 validates_presence_of :name
14 17 validates_format_of :name, :with => /\A\w+\z/
15 18 validates_presence_of :full_name
16 19
17 20 scope :available, -> { where(available: true) }
18 21
19 22 DEFAULT_TIME_LIMIT = 1
20 23 DEFAULT_MEMORY_LIMIT = 32
21 24
22 25 def self.available_problems
23 26 available.order(date_added: :desc).order(:name)
24 27 #Problem.available.all(:order => "date_added DESC, name ASC")
25 28 end
26 29
27 30 def self.create_from_import_form_params(params, old_problem=nil)
28 31 org_problem = old_problem || Problem.new
29 32 import_params, problem = Problem.extract_params_and_check(params,
30 33 org_problem)
31 34
32 35 if !problem.errors.empty?
33 36 return problem, 'Error importing'
34 37 end
35 38
36 39 problem.full_score = 100
37 40 problem.date_added = Time.new
38 41 problem.test_allowed = true
39 42 problem.output_only = false
40 43 problem.available = false
41 44
42 45 if not problem.save
43 46 return problem, 'Error importing'
44 47 end
45 48
46 49 import_to_db = params.has_key? :import_to_db
47 50
48 51 importer = TestdataImporter.new(problem)
49 52
50 53 if not importer.import_from_file(import_params[:file],
51 54 import_params[:time_limit],
52 55 import_params[:memory_limit],
53 56 import_params[:checker_name],
54 57 import_to_db)
55 58 problem.errors.add(:base,'Import error.')
56 59 end
57 60
@@ -1,23 +1,23
1 1 # Be sure to restart your server when you modify this file.
2 2
3 3 # Version of your assets, change this if you want to expire all your assets.
4 4 Rails.application.config.assets.version = '1.0'
5 5
6 6 # Add additional assets to the asset load path.
7 7 # Rails.application.config.assets.paths << Emoji.images_path
8 8 # Add Yarn node_modules folder to the asset load path.
9 9 Rails.application.config.assets.paths << Rails.root.join('node_modules')
10 10 Rails.application.config.assets.paths << Rails.root.join('vendor/assets/fonts')
11 11
12 12 # Precompile additional assets.
13 13 # application.js, application.css, and all non-JS/CSS in the app/assets
14 14 # folder are already added.
15 15 # Rails.application.config.assets.precompile += %w( admin.js admin.css )
16 16
17 17 Rails.application.config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js']
18 18 Rails.application.config.assets.precompile += ['local_jquery.js','tablesorter-theme.cafe.css']
19 19 %w( announcements submissions configurations contests contest_management graders heartbeat
20 20 login main messages problems report site sites sources tasks groups
21 - test user_admin users ).each do |controller|
21 + test user_admin users tags).each do |controller|
22 22 Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
23 23 end
@@ -1,49 +1,50
1 1 CafeGrader::Application.routes.draw do
2 + resources :tags
2 3 get "sources/direct_edit"
3 4
4 5 root :to => 'main#login'
5 6
6 7 #logins
7 8 get 'login/login', to: 'login#login'
8 9
9 10 resources :contests
10 11
11 12 resources :sites
12 13
13 14 resources :announcements do
14 15 member do
15 16 get 'toggle','toggle_front'
16 17 end
17 18 end
18 19
19 20 resources :problems do
20 21 member do
21 22 get 'toggle'
22 23 get 'toggle_test'
23 24 get 'toggle_view_testcase'
24 25 get 'stat'
25 26 end
26 27 collection do
27 28 get 'turn_all_off'
28 29 get 'turn_all_on'
29 30 get 'import'
30 31 get 'manage'
31 32 end
32 33 end
33 34
34 35 resources :groups do
35 36 member do
36 37 post 'add_user', to: 'groups#add_user', as: 'add_user'
37 38 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
38 39 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
39 40 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
40 41 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
41 42 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
42 43 end
43 44 collection do
44 45
45 46 end
46 47 end
47 48
48 49 resources :testcases, only: [] do
49 50 member do
@@ -1,62 +1,62
1 1 # encoding: UTF-8
2 2 # This file is auto-generated from the current state of the database. Instead
3 3 # of editing this file, please use the migrations feature of Active Record to
4 4 # incrementally modify your database, and then regenerate this schema definition.
5 5 #
6 6 # Note that this schema.rb definition is the authoritative source for your
7 7 # database schema. If you need to create the application database on another
8 8 # system, you should be using db:schema:load, not running all the migrations
9 9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 10 # you'll amass, the slower it'll run and the greater likelihood for issues).
11 11 #
12 12 # It's strongly recommended that you check this file into your version control system.
13 13
14 - ActiveRecord::Schema.define(version: 20170911091143) do
14 + ActiveRecord::Schema.define(version: 20170914150742) do
15 15
16 16 create_table "announcements", force: :cascade do |t|
17 17 t.string "author", limit: 255
18 18 t.text "body", limit: 65535
19 19 t.boolean "published"
20 20 t.datetime "created_at", null: false
21 21 t.datetime "updated_at", null: false
22 22 t.boolean "frontpage", default: false
23 23 t.boolean "contest_only", default: false
24 24 t.string "title", limit: 255
25 25 t.string "notes", limit: 255
26 26 end
27 27
28 28 create_table "contests", force: :cascade do |t|
29 29 t.string "title", limit: 255
30 30 t.boolean "enabled"
31 31 t.datetime "created_at", null: false
32 32 t.datetime "updated_at", null: false
33 33 t.string "name", limit: 255
34 34 end
35 35
36 36 create_table "contests_problems", id: false, force: :cascade do |t|
37 37 t.integer "contest_id", limit: 4
38 38 t.integer "problem_id", limit: 4
39 39 end
40 40
41 41 create_table "contests_users", id: false, force: :cascade do |t|
42 42 t.integer "contest_id", limit: 4
43 43 t.integer "user_id", limit: 4
44 44 end
45 45
46 46 create_table "countries", force: :cascade do |t|
47 47 t.string "name", limit: 255
48 48 t.datetime "created_at", null: false
49 49 t.datetime "updated_at", null: false
50 50 end
51 51
52 52 create_table "descriptions", force: :cascade do |t|
53 53 t.text "body", limit: 65535
54 54 t.boolean "markdowned"
55 55 t.datetime "created_at", null: false
56 56 t.datetime "updated_at", null: false
57 57 end
58 58
59 59 create_table "grader_configurations", force: :cascade do |t|
60 60 t.string "key", limit: 255
61 61 t.string "value_type", limit: 255
62 62 t.string "value", limit: 255
@@ -101,202 +101,221
101 101 create_table "heart_beats", force: :cascade do |t|
102 102 t.integer "user_id", limit: 4
103 103 t.string "ip_address", limit: 255
104 104 t.datetime "created_at", null: false
105 105 t.datetime "updated_at", null: false
106 106 t.string "status", limit: 255
107 107 end
108 108
109 109 add_index "heart_beats", ["updated_at"], name: "index_heart_beats_on_updated_at", using: :btree
110 110
111 111 create_table "languages", force: :cascade do |t|
112 112 t.string "name", limit: 10
113 113 t.string "pretty_name", limit: 255
114 114 t.string "ext", limit: 10
115 115 t.string "common_ext", limit: 255
116 116 end
117 117
118 118 create_table "logins", force: :cascade do |t|
119 119 t.integer "user_id", limit: 4
120 120 t.string "ip_address", limit: 255
121 121 t.datetime "created_at", null: false
122 122 t.datetime "updated_at", null: false
123 123 end
124 124
125 125 create_table "messages", force: :cascade do |t|
126 126 t.integer "sender_id", limit: 4
127 127 t.integer "receiver_id", limit: 4
128 128 t.integer "replying_message_id", limit: 4
129 129 t.text "body", limit: 65535
130 130 t.boolean "replied"
131 131 t.datetime "created_at", null: false
132 132 t.datetime "updated_at", null: false
133 133 end
134 134
135 135 create_table "problems", force: :cascade do |t|
136 136 t.string "name", limit: 30
137 137 t.string "full_name", limit: 255
138 138 t.integer "full_score", limit: 4
139 139 t.date "date_added"
140 140 t.boolean "available"
141 141 t.string "url", limit: 255
142 142 t.integer "description_id", limit: 4
143 143 t.boolean "test_allowed"
144 144 t.boolean "output_only"
145 145 t.string "description_filename", limit: 255
146 146 t.boolean "view_testcase"
147 147 end
148 148
149 + create_table "problems_tags", force: :cascade do |t|
150 + t.integer "problem_id", limit: 4
151 + t.integer "tag_id", limit: 4
152 + end
153 +
154 + add_index "problems_tags", ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true, using: :btree
155 + add_index "problems_tags", ["problem_id"], name: "index_problems_tags_on_problem_id", using: :btree
156 + add_index "problems_tags", ["tag_id"], name: "index_problems_tags_on_tag_id", using: :btree
157 +
149 158 create_table "rights", force: :cascade do |t|
150 159 t.string "name", limit: 255
151 160 t.string "controller", limit: 255
152 161 t.string "action", limit: 255
153 162 end
154 163
155 164 create_table "rights_roles", id: false, force: :cascade do |t|
156 165 t.integer "right_id", limit: 4
157 166 t.integer "role_id", limit: 4
158 167 end
159 168
160 169 add_index "rights_roles", ["role_id"], name: "index_rights_roles_on_role_id", using: :btree
161 170
162 171 create_table "roles", force: :cascade do |t|
163 172 t.string "name", limit: 255
164 173 end
165 174
166 175 create_table "roles_users", id: false, force: :cascade do |t|
167 176 t.integer "role_id", limit: 4
168 177 t.integer "user_id", limit: 4
169 178 end
170 179
171 180 add_index "roles_users", ["user_id"], name: "index_roles_users_on_user_id", using: :btree
172 181
173 182 create_table "sessions", force: :cascade do |t|
174 183 t.string "session_id", limit: 255
175 184 t.text "data", limit: 65535
176 185 t.datetime "updated_at"
177 186 end
178 187
179 188 add_index "sessions", ["session_id"], name: "index_sessions_on_session_id", using: :btree
180 189 add_index "sessions", ["updated_at"], name: "index_sessions_on_updated_at", using: :btree
181 190
182 191 create_table "sites", force: :cascade do |t|
183 192 t.string "name", limit: 255
184 193 t.boolean "started"
185 194 t.datetime "start_time"
186 195 t.datetime "created_at", null: false
187 196 t.datetime "updated_at", null: false
188 197 t.integer "country_id", limit: 4
189 198 t.string "password", limit: 255
190 199 end
191 200
192 201 create_table "submission_view_logs", force: :cascade do |t|
193 202 t.integer "user_id", limit: 4
194 203 t.integer "submission_id", limit: 4
195 204 t.datetime "created_at", null: false
196 205 t.datetime "updated_at", null: false
197 206 end
198 207
199 208 create_table "submissions", force: :cascade do |t|
200 209 t.integer "user_id", limit: 4
201 210 t.integer "problem_id", limit: 4
202 211 t.integer "language_id", limit: 4
203 212 t.text "source", limit: 65535
204 213 t.binary "binary", limit: 65535
205 214 t.datetime "submitted_at"
206 215 t.datetime "compiled_at"
207 216 t.text "compiler_message", limit: 65535
208 217 t.datetime "graded_at"
209 218 t.integer "points", limit: 4
210 219 t.text "grader_comment", limit: 65535
211 220 t.integer "number", limit: 4
212 221 t.string "source_filename", limit: 255
213 222 t.float "max_runtime", limit: 24
214 223 t.integer "peak_memory", limit: 4
215 224 t.integer "effective_code_length", limit: 4
216 225 t.string "ip_address", limit: 255
217 226 end
218 227
219 228 add_index "submissions", ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true, using: :btree
220 229 add_index "submissions", ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id", using: :btree
221 230
231 + create_table "tags", force: :cascade do |t|
232 + t.string "name", limit: 255, null: false
233 + t.text "description", limit: 65535
234 + t.boolean "public"
235 + t.datetime "created_at", null: false
236 + t.datetime "updated_at", null: false
237 + end
238 +
222 239 create_table "tasks", force: :cascade do |t|
223 240 t.integer "submission_id", limit: 4
224 241 t.datetime "created_at"
225 242 t.integer "status", limit: 4
226 243 t.datetime "updated_at"
227 244 end
228 245
229 246 add_index "tasks", ["submission_id"], name: "index_tasks_on_submission_id", using: :btree
230 247
231 248 create_table "test_pairs", force: :cascade do |t|
232 249 t.integer "problem_id", limit: 4
233 250 t.text "input", limit: 16777215
234 251 t.text "solution", limit: 16777215
235 252 t.datetime "created_at", null: false
236 253 t.datetime "updated_at", null: false
237 254 end
238 255
239 256 create_table "test_requests", force: :cascade do |t|
240 257 t.integer "user_id", limit: 4
241 258 t.integer "problem_id", limit: 4
242 259 t.integer "submission_id", limit: 4
243 260 t.string "input_file_name", limit: 255
244 261 t.string "output_file_name", limit: 255
245 262 t.string "running_stat", limit: 255
246 263 t.integer "status", limit: 4
247 264 t.datetime "updated_at", null: false
248 265 t.datetime "submitted_at"
249 266 t.datetime "compiled_at"
250 267 t.text "compiler_message", limit: 65535
251 268 t.datetime "graded_at"
252 269 t.string "grader_comment", limit: 255
253 270 t.datetime "created_at", null: false
254 271 t.float "running_time", limit: 24
255 272 t.string "exit_status", limit: 255
256 273 t.integer "memory_usage", limit: 4
257 274 end
258 275
259 276 add_index "test_requests", ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id", using: :btree
260 277
261 278 create_table "testcases", force: :cascade do |t|
262 279 t.integer "problem_id", limit: 4
263 280 t.integer "num", limit: 4
264 281 t.integer "group", limit: 4
265 282 t.integer "score", limit: 4
266 283 t.text "input", limit: 4294967295
267 284 t.text "sol", limit: 4294967295
268 285 t.datetime "created_at"
269 286 t.datetime "updated_at"
270 287 end
271 288
272 289 add_index "testcases", ["problem_id"], name: "index_testcases_on_problem_id", using: :btree
273 290
274 291 create_table "user_contest_stats", force: :cascade do |t|
275 292 t.integer "user_id", limit: 4
276 293 t.datetime "started_at"
277 294 t.datetime "created_at", null: false
278 295 t.datetime "updated_at", null: false
279 296 t.boolean "forced_logout"
280 297 end
281 298
282 299 create_table "users", force: :cascade do |t|
283 300 t.string "login", limit: 50
284 301 t.string "full_name", limit: 255
285 302 t.string "hashed_password", limit: 255
286 303 t.string "salt", limit: 5
287 304 t.string "alias", limit: 255
288 305 t.string "email", limit: 255
289 306 t.integer "site_id", limit: 4
290 307 t.integer "country_id", limit: 4
291 308 t.boolean "activated", default: false
292 309 t.datetime "created_at"
293 310 t.datetime "updated_at"
294 311 t.boolean "enabled", default: true
295 312 t.string "remark", limit: 255
296 313 t.string "last_ip", limit: 255
297 314 t.string "section", limit: 255
298 315 end
299 316
300 317 add_index "users", ["login"], name: "index_users_on_login", unique: true, using: :btree
301 318
319 + add_foreign_key "problems_tags", "problems"
320 + add_foreign_key "problems_tags", "tags"
302 321 end
You need to be logged in to leave comments. Login now