Rails应用开发:前端样式、投票功能与逻辑抽象
1. 前端样式调整
在前端页面添加新元素后,需要为这些元素添加样式规则。在
app/assets/stylesheets/stories.scss
文件中添加如下代码:
.story {
float: left;
width: 50%;
}
.story h3 { margin-bottom: 0; }
.story p { color: #666; }
同时,将默认的Rails欢迎页面替换为新的前端页面。需要修改
config/routes.rb
文件中的路由配置:
# 修改前
# root 'welcome#index'
# 修改后
root "stories#index"
注意,若
config/routes.rb
中未定义根路由,默认的Rails欢迎页面将显示。
2. 故事评分与投票箱实现
若前端页面故事较少,可通过投票功能让故事达到展示标准。实现投票箱功能,需在
/app/controllers/stories_controller.rb
文件中创建新方法
bin
:
class StoriesController < ApplicationController
⋮ controller code…
def bin
@stories = Story.where("votes_count < 5").order("id DESC")
render action: "index"
end
end
为了代码复用,将
index
和
bin
方法中的公共代码提取到
fetch_stories
方法中:
class StoriesController < ApplicationController
⋮ controller code…
def index
@stories = fetch_stories "votes_count >= 5"
end
def bin
@stories = fetch_stories "votes_count < 5"
render action: "index"
end
⋮ controller code…
protected
def fetch_stories(conditions)
@stories = Story.where(conditions).order("id DESC")
end
end
另一种常见方法是使用ActiveRecord作用域。在
app/models/story.rb
文件中添加作用域:
class Story < ApplicationRecord
...associations...
scope :upcoming, -> { where("votes_count < 5").order("id DESC") }
scope :popular, -> { where("votes_count >= 5").order("id DESC") }
...methods...
end
修改
StoriesController
中的
index
和
bin
方法:
class StoriesController < ApplicationController
⋮ controller code…
def index
@stories = Story.popular
end
def bin
@stories = Story.upcoming
render action: "index"
end
⋮ controller code…
protected
...removed fetch_stories...
end
选择使用哪种方法取决于个人偏好。若后续开发会多次使用
upcoming
和
popular
作用域,使用作用域更合适;若仅在控制器中使用,小的控制器方法也可接受。
3. 自定义RESTful路由
由于
bin
方法是新的控制器动作,不在默认的RESTful路由集合中,需要在
config/routes.rb
文件中添加自定义路由:
resources :stories do
collection do
get "bin"
end
resources :votes
end
这样会生成一个新的辅助方法
bin_stories_path
,用于在导航菜单中添加投票箱页面的链接。
4. 抽象展示逻辑
为避免视图模板中出现过多的Ruby代码,可使用ActionView辅助方法。以展示故事列表标题为例,若直接在
app/views/stories/index.html.erb
模板中添加逻辑,代码会显得混乱:
<h2>
<% if controller.action_name == 'index' %>
<%= "Showing #{ pluralize(@stories.size, 'front page story') }"%>
<% else %>
<%= "Showing #{ pluralize(@stories.size, 'upcoming story') }" %>
<% end %>
</h2>
可以在
app/helpers/stories_helper.rb
文件中创建辅助方法:
module StoriesHelper
def story_list_heading
story_type = case controller.action_name
when "index" then "frontpage story"
when "bin" then "upcoming story"
end
"Showing #{ pluralize(@stories.size, story_type) }"
end
end
在视图模板中使用该辅助方法:
<h2><%= story_list_heading %></h2>
<%= render partial: @stories %>
5. 扩展导航菜单
在
app/views/layouts/application.html.erb
文件的导航菜单中添加投票箱页面的链接:
<ul id="navigation">
<li><%= link_to 'Front page stories', stories_path %></li>
<li><%= link_to 'Upcoming stories', bin_stories_path %></li>
<li><%= link_to 'Submit a new story!', new_story_path %></li>
</ul>
以下是相关操作的流程图:
graph TD
A[前端页面添加新元素] --> B[添加样式规则到stories.scss]
B --> C[修改路由配置显示新前端页面]
C --> D[实现投票箱功能]
D --> E[代码复用或使用作用域]
E --> F[添加自定义RESTful路由]
F --> G[抽象展示逻辑使用ActionView辅助方法]
G --> H[扩展导航菜单]
6. 投票登录限制
为了记录用户投票历史,需要用户登录后才能投票。首先,在
app/controllers/votes_controller.rb
文件中添加
before_action
方法:
class VotesController < ApplicationController
before_action :ensure_login
⋮ controller code…
end
然后,在
app/views/stories/show.html.erb
文件中根据用户登录状态显示投票表单或登录提示:
><% if logged_in? %>
<div id="vote_form">
<%= form_for [@story, Vote.new], remote: true do %>
<%= submit_tag 'vote' %>
<% end %>
</div>
<% else %>
<p>
<em>
You would be able to vote for this story if you were
<%= link_to 'logged in', new_session_path %>!
</em>
</p>
<% end %>
最后,修改
VotesController
的
create
方法,将当前用户信息存储到投票记录中:
class VotesController < ApplicationController
⋮ controller code…
def create
@story = Story.find(params[:story_id])
if @vote = @story.votes.create(user: @current_user)
respond_to do |format|
format.html { redirect_to @story, notice: 'Vote was successfully crea' }
format.js {}
end
end
end
end
7. 自动投票功能
为了帮助新故事更快展示到首页,可实现自动投票功能。使用Rails模型的回调功能,在
app/models/story.rb
文件中添加回调方法:
class Story < ApplicationRecord
after_create :create_initial_vote
⋮ model code…
protected
模型回调可以在模型创建、更新或销毁等操作前后执行代码,与控制器中的过滤器类似。常见的回调方法有
before_create
、
before_save
、
before_destroy
等。
以下是投票功能的操作步骤列表:
1. 用户登录系统。
2. 访问投票箱页面,选择故事。
3. 点击投票按钮,系统记录投票信息。
4. 故事达到5票以上,显示在首页。
以下是投票功能的流程图:
graph TD
A[用户访问故事页面] --> B{用户是否登录}
B -- 是 --> C[显示投票表单]
B -- 否 --> D[显示登录提示]
C --> E[用户点击投票按钮]
E --> F[系统记录投票信息]
F --> G{故事票数是否达到5票}
G -- 是 --> H[故事显示在首页]
G -- 否 --> I[故事仍在投票箱]
通过以上步骤,我们完成了前端样式调整、投票功能实现、逻辑抽象等功能,让应用更完善。
Rails应用开发:前端样式、投票功能与逻辑抽象
8. 总结与功能回顾
在前面的开发过程中,我们逐步完成了多个重要功能,下面对这些功能进行总结回顾:
| 功能模块 | 实现步骤 | 关键代码文件 |
| — | — | — |
| 前端样式调整 | 为新元素添加样式规则,修改路由配置替换默认欢迎页 |
app/assets/stylesheets/stories.scss
、
config/routes.rb
|
| 故事评分与投票箱实现 | 创建
bin
方法,提取公共代码或使用作用域 |
/app/controllers/stories_controller.rb
、
app/models/story.rb
|
| 自定义RESTful路由 | 在路由配置文件中添加自定义路由 |
config/routes.rb
|
| 抽象展示逻辑 | 使用ActionView辅助方法避免视图模板代码混乱 |
app/helpers/stories_helper.rb
、
app/views/stories/index.html.erb
|
| 扩展导航菜单 | 在导航菜单中添加投票箱页面链接 |
app/views/layouts/application.html.erb
|
| 投票登录限制 | 添加
before_action
方法,根据登录状态显示投票表单或提示,存储用户信息 |
app/controllers/votes_controller.rb
、
app/views/stories/show.html.erb
|
| 自动投票功能 | 使用模型回调实现新故事自动投票 |
app/models/story.rb
|
9. 测试与验证
在完成上述功能开发后,需要对应用进行测试与验证,确保各个功能正常工作。
-
前端样式测试
:打开浏览器,访问前端页面,检查新元素的样式是否正确显示,页面布局是否符合预期。
-
投票功能测试
:
1. 未登录状态下,访问故事页面,检查是否显示登录提示。
2. 登录系统后,访问故事页面,点击投票按钮,检查投票信息是否正确记录,故事票数是否更新。
3. 当故事票数达到5票以上,检查故事是否显示在首页。
-
导航菜单测试
:点击导航菜单中的各个链接,检查是否能够正确跳转至相应页面。
10. 未来优化方向
虽然当前应用已经实现了基本功能,但仍有一些可以优化的方向:
-
用户体验优化
:可以添加更多的提示信息,如投票成功提示、登录过期提示等,提高用户体验。
-
性能优化
:对数据库查询进行优化,减少不必要的查询,提高应用的响应速度。
-
功能扩展
:可以添加更多的故事管理功能,如故事编辑、删除等,以及用户管理功能,如用户信息修改、权限管理等。
11. 开发经验总结
在本次开发过程中,我们积累了一些宝贵的经验:
-
代码复用
:通过提取公共代码和使用作用域,提高了代码的复用性和可维护性。
-
逻辑抽象
:使用ActionView辅助方法将展示逻辑从视图模板中抽象出来,使视图模板更加简洁。
-
遵循RESTful原则
:在路由设计中遵循RESTful原则,使应用的路由更加规范和易于理解。
12. 最终效果展示
经过一系列的开发和测试,应用已经具备了完整的功能。用户可以登录系统,访问投票箱页面,为故事投票,当故事票数达到5票以上,故事将显示在首页。以下是应用的最终操作流程图:
graph TD
A[用户打开应用] --> B{用户是否登录}
B -- 否 --> C[用户登录系统]
B -- 是 --> D[用户访问导航菜单]
C --> D
D --> E{选择页面}
E -- 首页 --> F[查看首页故事]
E -- 投票箱页面 --> G[选择故事投票]
G --> H{故事票数是否达到5票}
H -- 是 --> F
H -- 否 --> G
通过本次开发,我们成功实现了一个具备前端样式调整、投票功能、逻辑抽象等功能的Rails应用,为后续的开发和优化奠定了基础。在未来的开发中,我们可以根据用户需求和业务发展,不断完善和扩展应用的功能。
超级会员免费看
11

被折叠的 条评论
为什么被折叠?



