From 6b6ecc7e439989b0c40fc112c7fd0f6e57d2ff18 Mon Sep 17 00:00:00 2001 From: Absurdon Date: Sat, 25 Nov 2017 22:39:25 +0100 Subject: [PATCH] Some upgrade progress --- Gemfile | 4 + Gemfile.lock | 5 + app/controllers/articles_controller.rb | 14 ++- app/controllers/bans_controller.rb | 2 +- app/controllers/categories_controller.rb | 10 +- app/controllers/issues_controller.rb | 12 ++- app/controllers/users_controller.rb | 19 +++- app/models/article.rb | 42 ++++---- app/models/category.rb | 29 +++--- app/models/issue.rb | 3 +- app/models/user.rb | 118 ++++++++++++----------- config/routes.rb | 88 ++++++++--------- 12 files changed, 197 insertions(+), 149 deletions(-) diff --git a/Gemfile b/Gemfile index a5fecbb..89843a6 100644 --- a/Gemfile +++ b/Gemfile @@ -41,6 +41,10 @@ gem 'neat', '~> 1.6.0' gem 'haml', '~> 4.0.5' gem 'rails_autolink', '~> 1.1.5' +# acts as +gem 'acts_as_readable', '~> 2.1', '>= 2.1.1' +gem 'db_acts_as_versioned', '~> 3.5.0' + group :assets do gem 'uglifier', '~> 2.5.0' end diff --git a/Gemfile.lock b/Gemfile.lock index 28d2da5..2f221a1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -46,6 +46,8 @@ GEM minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) + acts_as_readable (2.1.1) + rails (~> 4.0) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) annotate (2.6.10) @@ -116,6 +118,7 @@ GEM crass (1.0.3) dalli (2.7.6) database_cleaner (1.2.0) + db_acts_as_versioned (3.5.0) debug_inspector (0.0.3) debugger-linecache (1.2.0) declarative (0.0.10) @@ -345,6 +348,7 @@ PLATFORMS DEPENDENCIES active_link_to (~> 1.0.2) + acts_as_readable (~> 2.1, >= 2.1.1) annotate (~> 2.6.2) bbcoder (~> 1.0.1) better_errors (~> 1.1.0) @@ -362,6 +366,7 @@ DEPENDENCIES country_select dalli (~> 2.7.0) database_cleaner (~> 1.2.0) + db_acts_as_versioned (~> 3.5.0) dotenv-rails (~> 0.10.0) dynamic_form (~> 1.1.4) exceptional (~> 2.0.33) diff --git a/app/controllers/articles_controller.rb b/app/controllers/articles_controller.rb index d0509e3..5b66be4 100644 --- a/app/controllers/articles_controller.rb +++ b/app/controllers/articles_controller.rb @@ -39,7 +39,7 @@ class ArticlesController < ApplicationController end def create - @article = Article.new params[:article] + @article = Article.new(article_create_params) @article.user = cuser raise AccessError unless @article.can_create? cuser @@ -52,8 +52,8 @@ class ArticlesController < ApplicationController end def update - raise AccessError unless @article.can_update? cuser, params[:article] - if @article.update_attributes(params[:article]) + raise AccessError unless @article.can_update?(cuser, params[:article]) + if @article.update_attributes(article_update_params) flash[:notice] = t(:articles_update) redirect_to @article else @@ -79,4 +79,12 @@ class ArticlesController < ApplicationController def get_article @article = Article.find params[:id] end + + def article_create_params + params.require(:article).permit(:title,:status, :category, :text, :text_parsed, :text_coding, :user) + end + + def article_update_params + params.require(:article).permit(:title,:status, :category, :text, :text_parsed, :text_coding) + end end diff --git a/app/controllers/bans_controller.rb b/app/controllers/bans_controller.rb index 0553b8e..d8fa03d 100644 --- a/app/controllers/bans_controller.rb +++ b/app/controllers/bans_controller.rb @@ -53,7 +53,7 @@ class BansController < ApplicationController end def ban_create_params - params.require(:ban).pemit(:steamid, :addr, :reason, :len, :user_name, :creator, :ban_type, :ip, :server, :len, :expiry) + params.require(:ban).permit(:steamid, :addr, :reason, :len, :user_name, :creator, :ban_type, :ip, :server, :len, :expiry) end def ban_update_params diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 0fc8be0..169002b 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -3,7 +3,7 @@ class CategoriesController < ApplicationController def show if [Category::DOMAIN_ARTICLES, Category::DOMAIN_NEWS].include? @category.domain - @articles = Article.with_comments.ordered.limited.nodrafts.category params[:id] + @articles = Article.with_comments.ordered.limited.nodrafts.of_category params[:id] Category.find(params[:id]).read_by! cuser if cuser render partial: 'articles/article', collection: @articles.to_a end @@ -23,7 +23,7 @@ class CategoriesController < ApplicationController end def create - @category = Category.new params[:category] + @category = Category.new category_params raise AccessError unless @category.can_create? cuser if @category.save @@ -37,7 +37,7 @@ class CategoriesController < ApplicationController def update raise AccessError unless @category.can_update? cuser - if @category.update_attributes params[:category] + if @category.update_attributes category_params flash[:notice] = t(:articles_category_update) redirect_to :categories end @@ -66,4 +66,8 @@ class CategoriesController < ApplicationController def get_category @category = Category.find params[:id] end + + def category_params + params.require(:category).permit(:name, :domain) + end end diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index c3563e9..cf5e49a 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -36,7 +36,7 @@ class IssuesController < ApplicationController end def create - @issue = Issue.new(params[:issue]) + @issue = Issue.new(issue_create_params) @issue.author = cuser if cuser raise AccessError unless @issue.can_create? cuser @@ -54,7 +54,7 @@ class IssuesController < ApplicationController def update raise AccessError unless @issue.can_update?(cuser, params[:issue]) - if @issue.update_attributes(params[:issue]) + if @issue.update_attributes(issue_update_params) flash[:notice] = t(:issues_update) redirect_to(@issue) else @@ -73,4 +73,12 @@ class IssuesController < ApplicationController def get_issue @issue = Issue.find params[:id] end + + def issue_create_params + params.require(:issue).permit(:title, :category, :text, :author) + end + + def issue_update_params + params.require(:issue).permit(:title, :category, :text, :assigned, :author, :solution, :status) + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 1174892..7d7c6d5 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -53,7 +53,7 @@ class UsersController < ApplicationController end def create - @user = User.new params[:user] + @user = User.new(user_create_params) @user.lastvisit = Date.today @user.lastip = request.env['REMOTE_ADDR'] @@ -73,7 +73,7 @@ class UsersController < ApplicationController def update raise AccessError unless @user.can_update? cuser params[:user].delete(:username) unless @user.can_change_name? cuser - if @user.update_attributes params[:user] + if @user.update_attributes user_update_params flash[:notice] = t(:users_update) redirect_to_back else @@ -117,7 +117,8 @@ class UsersController < ApplicationController def forgot if request.post? - if u = User.first(:conditions => {:username => params[:username], :email => params[:email]}) and u.send_new_password + user = User.where(username: params[:username], email: params[:email] ).first + if user and user.send_new_password flash[:notice] = t(:passwords_sent) else flash[:error] = t(:incorrect_information) @@ -137,4 +138,16 @@ class UsersController < ApplicationController user.lastvisit = DateTime.now user.save() end + + def user_create_params + params.require(:user).permit(:raw_password, :username, :email, :steamid, :birthdate) + end + + def user_update_params + params.require(:user).permit( + :raw_password, :username, :email, :steamid, :birthdate, + :firstname, :lastname, :country, :time_zone, :public_email, + params[:user][:profile_attributes].try(:keys) + ) + end end diff --git a/app/models/article.rb b/app/models/article.rb index 88664ab..7910c4b 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -36,23 +36,27 @@ class Article < ActiveRecord::Base G_RULES = 464 COMPMOD = 998 - attr_protected :id, :updated_at, :created_at, :user_id, :version + scope :recent, ->{ order(created_at: :desc).limit(8) } + scope :with_comments, lambda { + select("articles.*, COUNT(C.id) AS comment_num") + .joins("LEFT JOIN comments C ON C.commentable_type = 'Article' AND C.commentable_id = articles.id") + .group(:id) + } + scope :ordered, -> { order(created_at: :desc) } + scope :limited, -> { limit(5) } + scope :nodrafts, -> { where(status: STATUS_PUBLISHED) } + scope :drafts, -> { where(status: STATUS_DRAFT) } + scope :of_category, ->(cat){ where(category_id: cat) } - scope :recent, order: 'created_at DESC', limit: 8 - scope :with_comments, - select: "articles.*, COUNT(C.id) AS comment_num", - joins: "LEFT JOIN comments C ON C.commentable_type = 'Article' AND C.commentable_id = articles.id", - group: "articles.id" - scope :ordered, order: 'articles.created_at DESC' - scope :limited, limit: 5 - scope :nodrafts, conditions: { status: STATUS_PUBLISHED } - scope :drafts, conditions: { status: STATUS_DRAFT } - scope :articles, conditions: ["category_id IN (SELECT id FROM categories WHERE domain = ?)", Category::DOMAIN_ARTICLES] - scope :onlynews, conditions: ["category_id IN (SELECT id FROM categories WHERE domain = ?)", Category::DOMAIN_NEWS] - scope :category, lambda { |cat| { conditions: { category_id: cat } } } - scope :domain, lambda { |domain| { includes: 'category', conditions: { "categories.domain" => domain } } } - scope :nospecial, conditions: ["category_id != ?", Category::SPECIAL] - scope :interviews, conditions: ["category_id = ?", Category::INTERVIEWS] + scope :domain, lambda { |domain| + includes(:category) + .where(category_id: {category: { domain: domain}}) + } + scope :articles, -> { domain Category::DOMAIN_ARTICLES } + scope :onlynews, -> { domain Category::DOMAIN_NEWS } + + scope :nospecial, -> { where(category_id: Category::SPECIAL) } + scope :interviews, -> { where(category_id: Category::INTERVIEWS) } belongs_to :user belongs_to :category @@ -83,11 +87,11 @@ class Article < ActiveRecord::Base end def previous_article - category.articles.nodrafts.first(conditions: ["id < ?", self.id], order: "id DESC") + category.articles.nodrafts.where(["id < ?", self.id]).order(id: :desc).first end def next_article - category.articles.nodrafts.first(conditions: ["id > ?", self.id], order: "id ASC") + category.articles.nodrafts.where(["id > ?", self.id]).order(:id).first end def statuses @@ -95,7 +99,7 @@ class Article < ActiveRecord::Base end def validate_status - errors.add :status, I18n.t(:invalid_status) unless statuses.include? status + errors.add :status, 'Invalid status' unless statuses.include? status end def init_variables diff --git a/app/models/category.rb b/app/models/category.rb index 8f0097b..94c332a 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -28,21 +28,26 @@ class Category < ActiveRecord::Base PER_PAGE = 3 - attr_protected :id, :updated_at, :created_at, :sort - validates_length_of :name, :in => 1..30 validate :validate_domain - scope :ordered, :order => "sort ASC, created_at DESC" - scope :domain, lambda { |domain| {:conditions => {:domain => domain}} } - scope :nospecial, :conditions => ["name != 'Special'"] - scope :newest, :include => :articles, :order => "articles.created_at DESC" - scope :page, lambda { |page| {:limit => "#{(page-1)*PER_PAGE}, #{(page-1)*PER_PAGE+PER_PAGE}"} } - scope :of_user, lambda { |user| {:conditions => {"articles.user_id" => user.id}, :include => :articles} } + scope :ordered, ->{ order(:sort, created_at: :desc) } + scope :domain, ->(domain) { where(domain: domain) } + scope :nospecial,->{ where.not(name: 'Special') } + scope :newest, lambda{ + includes(:articles) + .order(articles: { created_at: :desc}) + } + scope :of_user, lambda { |user| + includes(:articles) + .where(articles: { + user_id: user.id + }) + } - has_many :articles, :order => "created_at DESC" - has_many :issues, :order => "created_at DESC" - has_many :forums, :order => "forums.position" + has_many :articles, ->{ order(created_at: :desc) } + has_many :issues, ->{ order(created_at: :desc) } + has_many :forums, ->{ order(:position) } has_many :movies has_many :maps has_many :gathers @@ -65,7 +70,7 @@ class Category < ActiveRecord::Base end def validate_domain - errors.add :domain, I18n.t(:invalid_domain) unless domains.include? domain + errors.add(:domain, 'Incalid Domain') unless domains.include? domain end def can_create? cuser diff --git a/app/models/issue.rb b/app/models/issue.rb index 0bf039b..0b3f088 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -30,7 +30,6 @@ class Issue < ActiveRecord::Base CATEGORY_GATHER = 54 attr_accessor :assigned_name - attr_protected :id, :created_at, :updated_at has_many :comments, :as => :commentable belongs_to :category @@ -81,7 +80,7 @@ class Issue < ActiveRecord::Base end def validate_status - errors.add :status, I18n.t(:invalid_status) unless statuses.include? status + errors.add :status, 'Invalid status' unless statuses.include? status end def parse_text diff --git a/app/models/user.rb b/app/models/user.rb index f7a08f9..556bed9 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -23,14 +23,12 @@ require 'digest/md5' -require File.join(Rails.root, 'vendor', 'plugins', 'acts_as_versioned', 'lib', 'acts_as_versioned.rb') class User < ActiveRecord::Base include Extra - + VERIFICATION_TIME = 604800 - attr_protected :id, :created_at, :updated_at, :lastvisit, :lastip, :password, :version attr_accessor :raw_password belongs_to :team @@ -47,60 +45,78 @@ class User < ActiveRecord::Base has_many :groups, :through => :groupers has_many :shoutmsgs, :dependent => :destroy has_many :issues, :foreign_key => "author_id", :dependent => :destroy - has_many :open_issues, :class_name => "Issue", :foreign_key => "assigned_id", - :conditions => ["issues.status = ?", Issue::STATUS_OPEN] + + has_many :open_issues, ->{ where(status: Issue::STATUS_OPEN) }, + :class_name => "Issue", :foreign_key => 'assigned_id' + has_many :posted_comments, :dependent => :destroy, :class_name => "Comment" - has_many :comments, :class_name => "Comment", :as => :commentable, :order => "created_at ASC", :dependent => :destroy + + has_many :comments, ->{ order(created_at: :asc) }, + :class_name => "Comment", :as => :commentable, :dependent => :destroy + has_many :teamers, :dependent => :destroy - has_many :active_teams, :through => :teamers, :source => "team", - :conditions => ["teamers.rank >= ? AND teams.active = ?", Teamer::RANK_MEMBER, true] - has_many :active_contesters, :through => :active_teams, :source => "contesters", - :conditions => {"contesters.active" => true} - has_many :active_contests, :through => :active_contesters, :source => "contest", - :conditions => ["contests.status != ?", Contest::STATUS_CLOSED] - has_many :past_teams, :through => :teamers, :source => "team", :group => "user_id, team_id" + + has_many :active_teams, ->{ where(["teamers.rank >= ? AND teams.active = ?", Teamer::RANK_MEMBER, true]) }, + :through => :teamers, :source => "team" + + has_many :active_contesters, ->{ where(active: true) }, + :through => :active_teams, :source => "contesters" + + has_many :active_contests,->{ where(status: Contest::STATUS_CLOSED) }, + :through => :active_contesters, :source => "contest" + + has_many :past_teams, ->{ group(:user_id, :team_id) }, + :through => :teamers, :source => "team" + has_many :matchers, :dependent => :destroy has_many :matches, :through => :matchers has_many :predictions, :dependent => :destroy has_many :challenges_received, :through => :active_contesters, :source => "challenges_received" has_many :challenges_sent, :through => :active_contesters, :source => "challenges_sent" - has_many :upcoming_team_matches, :through => :active_contesters, :source => "matches", - :conditions => "match_time > UTC_TIMESTAMP()" - has_many :upcoming_ref_matches, :class_name => "Match", :foreign_key => "referee_id", - :conditions => "match_time > UTC_TIMESTAMP()" - has_many :past_team_matches, :through => :active_contesters, :source => "matches", - :conditions => "match_time < UTC_TIMESTAMP()" - has_many :past_ref_matches, :class_name => "Match", :foreign_key => "referee_id", - :conditions => "match_time < UTC_TIMESTAMP()" + + has_many :upcoming_team_matches, ->{ where("match_time > UTC_TIMESTAMP()") }, + :through => :active_contesters, :source => "matches" + + has_many :upcoming_ref_matches, ->{ where("match_time > UTC_TIMESTAMP()") }, + :class_name => "Match", :foreign_key => "referee_id" + + has_many :past_team_matches, ->{ where("match_time < UTC_TIMESTAMP()") }, + :through => :active_contesters, :source => "matches" + + has_many :past_ref_matches,->{ where("match_time < UTC_TIMESTAMP()") }, + :class_name => "Match", :foreign_key => "referee_id" + has_many :received_personal_messages, :class_name => "Message", :as => "recipient", :dependent => :destroy has_many :received_team_messages, :through => :active_teams, :source => :received_messages has_many :sent_personal_messages, :class_name => "Message", :as => "sender", :dependent => :destroy has_many :sent_team_messages, :through => :active_teams, :source => :sent_messages - has_many :match_teams, :through => :matchers, :source => :teams, :uniq => true + has_many :match_teams, ->{ uniq }, :through => :matchers, :source => :teams - scope :active, :conditions => {:banned => false} - scope :with_age, - :select => "DATE_FORMAT(FROM_DAYS(TO_DAYS(NOW())-TO_DAYS(birthdate)), '%Y')+0 AS aged, COUNT(*) as num, username", - :group => "aged", - :having => "num > 8 AND aged > 0" - scope :country_stats, - :select => "country, COUNT(*) as num", - :conditions => "country is not null and country != '' and country != '--'", - :group => "country", - :having => "num > 15", - :order => "num DESC" - scope :posts_stats, - :select => "users.id, username, COUNT(posts.id) as num", - :joins => "LEFT JOIN posts ON posts.user_id = users.id", - :group => "users.id", - :order => "num DESC" - scope :banned, - :joins => "LEFT JOIN bans ON bans.user_id = users.id AND expiry > UTC_TIMESTAMP()", - :conditions => "bans.id IS NOT NULL" - scope :idle, - :conditions => ["lastvisit < ?", 30.minutes.ago.utc] - scope :lately, - :conditions => ["lastvisit > ?", 30.days.ago.utc] + scope :active,->{ where(banned: false) } + scope :with_age, lambda { + select("DATE_FORMAT(FROM_DAYS(TO_DAYS(NOW())-TO_DAYS(birthdate)), '%Y')+0 AS aged, COUNT(*) as num, username") + .having('num > 8 AND aged > 0') + .group('aged') + } + scope :country_stats, lambda { + select("country, COUNT(*) as num") + .where("country is not null and country != '' and country != '--'") + .having("num > 15") + .group("country") + .order("num DESC") + } + scope :posts_stats, lambda { + select("users.id, username, COUNT(posts.id) as num") + .joins("LEFT JOIN posts ON posts.user_id = users.id") + .group("users.id") + .order("num DESC") + } + scope :banned, lambda { + joins("LEFT JOIN bans ON bans.user_id = users.id AND expiry > UTC_TIMESTAMP()") + .where("bans.id IS NOT NULL") + } + scope :idle, ->{ where(["lastvisit < ?", 30.minutes.ago.utc]) } + scope :lately, ->{ where(["lastvisit > ?", 30.days.ago.utc]) } before_validation :update_password @@ -199,10 +215,6 @@ class User < ActiveRecord::Base groups.exists? id: Group::STAFF end - def staff? - groups.exists? :id => Group::STAFF - end - def caster? groups.exists? id: Group::CASTERS end @@ -220,14 +232,6 @@ class User < ActiveRecord::Base admin? or moderator? end - def gather_moderator? - groups.exists? id: Group::GATHER_MODERATORS - end - - def allowed_to_ban? - admin? or gather_moderator? - end - def verified? # created_at < DateTime.now.ago(VERIFICATION_TIME) true diff --git a/config/routes.rb b/config/routes.rb index c783a93..2c2e25a 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -19,9 +19,9 @@ Ensl::Application.routes.draw do resources :versions end - match "contests/del_map" - match "contests/scores" - match "contests/historical", to: "contests#historical" + get "contests/del_map" + get "contests/scores" + get "contests/historical", to: "contests#historical" resources :contests do get "current", on: :collection @@ -32,7 +32,7 @@ Ensl::Application.routes.draw do resources :options resources :polls - match "comments/quote" + get "comments/quote" resources :comments resources :shoutmsgs @@ -45,8 +45,8 @@ Ensl::Application.routes.draw do resources :forumers resources :topics - match "forums/up" - match "forums/down" + get "forums/up" + get "forums/down" resources :forums resources :users @@ -80,71 +80,65 @@ Ensl::Application.routes.draw do resources :tweets resources :issues - match "posts/quote" + get "posts/quote" resources :posts resources :brackets - match "about/action" - match "about/staff" - match "about/statistics" + get "about/action" + get "about/staff" + get "about/statistics" - match "refresh", to: "application#refresh" - match "search", to: "application#search" + # match "refresh", to: "application#refresh" + # match "search", to: "application#search" - match "news", to: "articles#news_index" - match "news/archive", to: "articles#news_archive" - match "news/admin", to: "articles#admin" - match "articles/cleanup" + get "news", to: "articles#news_index" + get "news/archive", to: "articles#news_archive" + get "news/admin", to: "articles#admin" + get "articles/cleanup" - match "data_files/admin" - match "data_files/addFile" - match "data_files/delFile" - match "data_files/trash" + get "data_files/admin" + match "data_files/addFile", via: [:get, :post] + match "data_files/delFile", via: [:get, :post] + match "data_files/trash", via: [:get, :post] - match "contesters/recalc" + match "contests/recalc", via: [:get, :post] - match "directories", to: "directories#show", id: 1 + get "directories", to: "directories#show", id: 1 - match "gathers/refresh" + match "gathers/refresh", via: [:get, :post] match "gathers/latest/:game", to: "gathers#latest", via: :get match "gather", to: "gathers#latest", game: "ns2", via: :get match "gatherers/:id/status", to: "gatherers#status", via: :post - match "groups/addUser" - match "groups/delUser" + post "groups/addUser" + post "groups/delUser" - match "movies/download" - match "movies/preview" - match "movies/snapshot" + get "movies/download" + get "movies/preview" + get "movies/snapshot" - match "plugin/user" + get "plugin/user" - match "users/forgot" - match "users/recover" - match "users/agenda" - match "users/logout" - match "users/login" + match "users/forgot", via: [:get, :post] + get "users/agenda" + match "users/logout", via: [:get, :post] + match "users/login", via: [:get, :post] + get "users/popup" - match "users/agenda" - match "users/login" - match "users/logout" - match "users/popup" - match "users/forgot", to: "users#forgot" - - match "votes/create" - match "polls/showvotes/:id", to: "polls#showvotes", as: "polls_showvotes" + post "votes/create" + get "polls/showvotes/:id", to: "polls#showvotes", as: "polls_showvotes" get "custom_urls", to: "custom_urls#administrate" resources :custom_urls, only: [:create, :update, :destroy] get ":name", to: "custom_urls#show", requirements: {name: /\A[a-z\-]{2,10}\Z/} - match ":controller/:action", requirements: { action: /A-Za-z/ } - match ":controller/:action/:id" - match ":controller/:action/:id.:format" - match ":controller/:action/:id/:id2" + match ":controller/:action", requirements: { action: /A-Za-z/ }, via: [:get, :post] + match ":controller/:action/:id", via: [:get, :post] + match ":controller/:action/:id.:format", via: [:get, :post] + match ":controller/:action/:id/:id2", via: [:get, :post] - match "teamers/replace", to: "teamers#replace", as: "teamers_replace" + # match "teamers/replace", to: "teamers#replace", as: "teamers_replace" end