Determining the status of associated models in a class
I have a Rails 2.3 app which tracks an organisation's members, and whether they have a paid membership. Some members may not have a paid membership, some may have a 1-year paid membership, and some may have a lifetime membership. We wish to record a member's membership history.
Currently I have the following (relevant) models and schema:
class Member < ActiveRecord::Base
has_many :memberships
end
class Membership < ActiveRecord::Base
belongs_to :member
end
create_table "members", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "memberships", :force => true do |t|
t.string "name"
t.integer "member_id"
t.datetime "end_date"
t.boolean "lifetime"
end
At the moment we determine whether a client is a current member in the view, which of course is not a best practice, so we want to move the logic to the model. The code in the view is:
<% if @memberships.count == 0 %>
This member has never had a paid membership
<% else %>
<% if @memberships.last.lifetime? %>
This member is a lifetime member
<% else %>
<% if @memberships.last.end_date < Time.now %>
This member's membership has expired
<% else %>
<% if @memberships.last.end_date > Time.now %>
This member is a current member
<% end %>
<% end %>
<% end %>
&开发者_如何学编程lt;% end %>
What I'd like is for a (for example) current_member method and a lifetime_member method in the Member class, which will return true or false. I've had a play at doing this, but I'm not sure which is the best way to do it.
Any suggestions?
General case:
class Member
def current_member?
if memberships.count > 0
memberships.each{ |m| return true if m.lifetime || m.end_date > Time.now }
end
return false
end
def lifetime_member?
if memberships.count > 0
memberships.each{ |m| return true if m.lifetime }
end
return false
end
end
If you're sure that you want to check only the last membership:
class Member
def lifetime_member?
return memberships.count > 0 && memberships.last.lifetime
end
def current_member?
return memberships.count > 0 && (memberships.last.lifetime || memberships.last.end_date > Time.now }
end
end
Here's is how I might go about moving the logic to the model.
class Member < ActiveRecord::Base
has_many :memberships
def current_membership
memberships.last
end
def has_membership?
memberships.any?
end
def active?
!expired?
end
def expired?
!lifetime? && (current_membership.active? if current_membership)
end
def lifetime?
current_membership.lifetime? if current_membership
end
end
class Membership < ActiveRecord::Base
belongs_to :member
def active?
!expired
end
def expired?
end_date < Time.now
end
end
Here's is what you might write in erb:
<% unless @member.has_membership? %>
This member has never had a paid membership
<% end %>
<% if @member.lifetime? %>
This member is a lifetime member
<% end %>
<% if @member.expired?%>
This member's membership has expired
<% end %>
<% if @member.active? %>
This member is a current member
<% end %>
And the same in HAML, which I recommend:
- unless @member.has_membership?
This member has never had a paid membership
- if @member.lifetime?
This member is a lifetime member
- if @member.expired?
This member's membership has expired
- if @member.active?
This member is a current member
精彩评论