这就是我需要做的事情。我有Tournament
模型,它通过User
(N:N)连接到Signup
。
Signup
唯一添加的是注册状态。比赛有一个开始时间,用户只能在比赛开始前60分钟进行注册。之后,注册用户可以办理登机手续。所以基本上我有两个选择状态
简而言之,模型看起来像这样
class Signup < ActiveRecord::Base
REGISTERED = 0
CHECKED = 1
belongs_to :tournament
belongs_to :user
end
class Tournament < ActiveRecord::Base
has_many :signups
has_many :users, :through => :signups
end
class User < ActiveRecord::Base
has_many :signups
has_many :tournaments, :through => :signups
end
我跳过一些代码来保持这个简短。问题在于,因为我有很多条件要记住。这是我的实际代码(using Slim as a templating engine)
- if logged_in?
- if current_user.registered_for?(@tournament)
- if @tournament.starts_at < 60.minutes.from_now
p Signups are closed, only registered users can now check in
- if current_user.registered_for?(@tournament)
= button_to "Checkin!", { :controller => :signups, :action => :update, :id => @tournament.id }, :method => :put
- else
= button_to "Cancel your registration for the tournament", { :controller => :signups, :action => :destroy, :id => @tournament.id }, :method => :delete
- elsif current_user.checked_in?(@tournament)
p You have already checked in.
- elsif @tournament.starts_at > 60.minutes.from_now
= button_to "Sign up for the tournament", :controller => :signups, :action => :create, :method => :post, :id => @tournament.id
- else
p
| The tournament starts in less than 60 minutes, you can't sign in
- else
p
| You need to
|
= link_to "log in", login_path
| to play
问题是,我不知道如何使这个更清洁。我的意思是,我可以为按钮添加助手,但这对if if else else
丑陋无助,因为有许多不同的组合。这是一个简短的清单:
这只是冰山一角,因为管理员应该看到比普通用户更多的信息,但我不想让这个问题复杂化。
主要问题是,我应该如何处理这样的案件?在一个视图中这样做似乎太可怕了,但我没有看到任何其他更简单的方法。
答案 0 :(得分:5)
更简洁的方法是在模型上创建有意义的方法。例如,在锦标赛模型中,添加如下内容:
def can_register?( user )
!user.registered_for?(self) && self.starts_at > 60.minutes.from_now
end
然后在您看来,您可以在显示内容之前检查can_register?
。像你一样在视图中添加逻辑不是MVC应用程序的目的。
答案 1 :(得分:2)
您应该使用对象来封装逻辑。也许是这样的:
class UserSignup
def initialize(user, tournament)
@user, @tournament = user, tournament
end
def registered?
@user.registered_for?(@tournament)
end
def signups_closed?
@tournament.start_at < 1.hour.from_now
end
def checked_in?
@user.checked_in?(@tournament)
end
end
这使得视图更加简单,并且不需要太多工作。你会发现很多重复都会被这种方式删除,你可以独立于视图测试你的注册逻辑。
您还可以制作一位演示者,这需要更多参与,但更能清理您的观点。看看像draper这样的宝石来帮助你解决这个问题。
class SignupPresenter
def initialize(user_signup)
@user_signup = user_signup
end
def register_button
view.button_to("sign up") if @user_signup.registered?
end
# etc ...
end
另外,我会考虑为不同的用户使用不同的模板甚至控制器。因此,根本没有登录的用户甚至无法访问此页面,管理员也可以拥有不同的控制器(甚至命名空间)。
我不会只是将其拆分为部分,因为这只会隐藏逻辑。我也喜欢一个单独的对象,而不是把它放到一个模型中,因为这样一来,模型不会变得混乱,所有的逻辑都保持在一起,很好地集中在一起。