24、Rails应用开发:前端样式、投票功能与逻辑抽象

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应用,为后续的开发和优化奠定了基础。在未来的开发中,我们可以根据用户需求和业务发展,不断完善和扩展应用的功能。

复杂几何的多球近似MATLAB类及多球模型的比较 MATLAB类Approxi提供了一个框架,用于使用具有迭代缩放的聚集球体模型来近似解剖体积模型,以适应目标体积和模型比较。专为骨科、生物力学和计算几何应用而开发。 MATLAB class for multi-sphere approximation of complex geometries and comparison of multi-sphere models 主要特点: 球体模型生成 1.多球体模型生成:Sihaeri的聚集球体算法的接口 2.音量缩放 基于体素的球体模型和参考几何体的交集。 迭代缩放球体模型以匹配目标体积。 3.模型比较:不同模型体素占用率的频率分析(多个评分指标) 4.几何分析:原始曲面模型和球体模型之间的顶点到最近邻距离映射(带颜色编码结果)。 如何使用: 1.代码结构:Approxi类可以集成到相应的主脚本中。代码的关键部分被提取到单独的函数中以供重用。 2.导入:将STL(或网格)导入MATLAB,并确保所需的函数,如DEM clusteredSphere(populateSpheres)和inpolyhedron,已添加到MATLAB路径中 3.生成多球体模型:使用DEM clusteredSphere方法从输入网格创建多球体模型 4.运行体积交点:计算多球体模型和参考几何体之间的基于体素的交点,并调整多球体模型以匹配目标体积 5.比较和可视化模型:比较多个多球体模型的体素频率,并计算多球体模型原始表面模型之间的距离,以进行2D/3D可视化 使用案例: 骨科和生物力学体积建模 复杂结构的多球模型形状近似 基于体素拟合度量的模型选择 基于距离的患者特定几何形状和近似值分析 优点: 复杂几何的多球体模型 可扩展模型(基于体素)-自动调整到目标体积 可视化就绪输出(距离图)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值