Reputation: 437
Rails.cache.fetch(plan_list_cache_key(project), expires_in: EXPIRES_TIME) do
plans = Plan.all.where(is_active: true)
project_plan = project.project_plan
hash_array = []
plans.each do |plan|
plan = plan.attributes
expired = if (plan["id"] == project.plan.id)
(project_plan.end_date.to_date - Date.current).to_i.positive? ? false : true
else
false
end
subscribed = plan["id"] == project.plan.id
hash_array << plan.merge!({is_expired: expired , subscribed: subscribed})
end
hash_array
end
Models:
class Plan < MysqlBase
has_many :project_plans
end
class ProjectPlan < MysqlBase
belongs_to :plan
belongs_to :project
end
class Project < MysqlBase
has_one :project_plan
has_one :plan, :through => :project_plan
end
Schema:
create_table "plans", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "name"
t.text "description"
t.integer "email_limit"
t.integer "validity"
t.float "unit_price", limit: 24
t.string "currency"
t.integer "base_user_count"
t.boolean "is_renewable"
t.boolean "is_active"
t.boolean "is_free"
t.string "terms"
t.integer "trial_days"
t.boolean "default"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "project_plans", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.integer "plan_id"
t.integer "project_id"
t.datetime "start_date"
t.datetime "end_date"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Response
{
"status": "OK",
"status_code": 200,
"message": "ok",
"data": {
"plans": [
{
"id": 1,
"name": "Free",
"description": "30 days free trial",
"email_limit": 10000,
"validity": 30,
"unit_price": 0.0,
"currency": "USD",
"base_user_count": 0,
"trial_days": 30,
"is_free": true,
"subscribed": false,
"is_expired": false
},
{
"id": 2,
"name": "Standard",
"description": "$3 for 100 users",
"email_limit": 0,
"validity": 30,
"unit_price": 0.03,
"currency": "USD",
"base_user_count": 100,
"trial_days": 0,
"is_free": false,
"subscribed": true,
"is_expired": false
}
]
}
}
Each project has a separate project_plan. Plans are the same for all users. But what I have to do is to add two additional fields is_expired & subscribed with the API response
I am caching my response here using fetch. But is it the right way to doing cache as there are some DB & logical operations
If that isn't the right way what type of error can be happened here?
What will be the best approach to do this kind of caching?
Upvotes: 0
Views: 251
Reputation: 102368
One solution here is to join the project plans table and select aggregates:
SELECT
plans.*,
-- you will get integers since MySQL is a peasant database and does not have real boolean types
COUNT(pp.id) > 0 AS subscribed,
COALESCE(MAX(pp.ends_at) < NOW(), FALSE) AS is_expired
FROM plans
LEFT OUTER JOIN project_plans pp
ON pp.plan_id = plans.id
AND pp.project_id = ?
GROUP BY plans.id
class Plan
def with_statuses_for_project(project)
pp = ProjectPlan.arel_table
j = pp.join(arel_table).on(
pp[:plan_id].eq(arel_table[:id])
.and(
pp[:project_id].eq(project.id)
)
)
.select(
arel_table[Arel.star],
"COUNT(pp.id) > 0 AS subscribed",
"COALESCE(MAX(pp.ends_at) < NOW(), FALSE) AS is_expired"
)
.joins(j.join_sources)
.group(:id)
end
end
Upvotes: 1