20180214

2018年02月14日

肖威工作总结

魏晓 家开发设计数据学习免费编码 转到Domantas G的个人资料 Domantas G跟随 sciencetone.com的创建者 2017年12月16日 终极中级Ruby on Rails教程:让我们创建一个完整的应用程序!

网上有很多教程展示了如何创建你的第一个应用程序。本教程将更进一步并逐行解释如何创建更复杂的Ruby On Rails应用程序。

在整个教程中,我将逐步介绍新技术和概念。这个想法是,每一个新的部分,你应该学习新的东西。

本指南将讨论以下主题:

Ruby On Rails基础知识 重构:助手,部分,关注点,设计模式 测试:TDD / BDD(RSpec&Capybara),工厂(工厂女孩) 行动电缆 活跃的工作 CSS,Bootstrap,JavaScript,jQuery 那么应用程序将会是什么? 这将成为一个平台,您可以搜索和认识志同道合的人。

应用程序将具有的主要功能:

认证(与设计) 能够发布帖子,并对它们进行搜索和分类 即时消息(弹出窗口和单独的信使),能够创建私人和群组对话。 能够将用户添加到联系人 实时通知 你可以看到完整的应用程序将如何看。

你可以在GitHub上找到完整的项目源代码。

目录 简介和安装 先决条件 安装 创建新应用程序 布局主页Bootstrap 导航栏样式表

帖子 验证 助手 测试 主要源 单一帖子 特定分支 服务对象 创建一个新帖子 即时消息私人对话联系人群组对话Messenger

通知联系请求对话

先决条件 我会尽力解释每一行代码,以及我如何提出解决方案。我认为完全有可能让初学者完成本指南。但请记住,本教程涵盖了一些超出基础的主题。

所以,如果你是一个初学者,这将会变得更加困难,因为你的学习曲线会非常陡峭。我将提供资源链接,您可以从中获得有关我们所接触的每个新概念的额外信息。

理想情况下,如果您了解以下基本知识,最好:

HTML,CSS,Bootstrap,JavaScript,jQuery Ruby,Ruby On Rails 混帐 建立 我假设你已经建立了基本的Ruby On Rails开发环境。如果没有,请检查RailsInstaller。

我一直在Windows 10上开发。起初没问题,但过了一段时间,我厌倦了克服由Windows引起的神秘障碍。我不得不继续弄清楚黑客的方式来让我的应用程序工作。我意识到,这是不值得我的时间。克服这些障碍并没有给我任何宝贵的技能或知识。我只是花了我的时间通过管道录制Windows 10安装程序。

所以我转而使用虚拟机。我选择使用Vagrant创建开发环境并使用PuTTY连接到虚拟机。如果你想使用流浪汉,这是我觉得有用的教程。

创建一个新应用程序 我们将使用PostgreSQL作为我们的数据库。它是Ruby On Rails社区的热门选择。如果您尚未使用PostgreSQL创建任何Rails应用程序,则可能需要查看本教程。

一旦熟悉PostgreSQL,请导航到保存项目的目录并打开命令行提示符。

要生成新的应用程序,请运行以下行:

rails new collabfield --database=postgresql Collabfield,这就是我们的应用程序将被调用的方式。默认情况下,Rails使用SQlite3,但由于我们想使用PostgreSQL作为我们的数据库,我们需要通过添加以下内容来指定它:

--database = PostgreSQL的 现在我们应该已经成功生成了一个新应用程序

通过运行以下命令导航到新创建的目录:

cd collabfield 现在我们可以输入以下内容运行我们的应用

铁轨 我们刚开始我们的应用程序 现在我们应该能够看到我们到目前为止得到了什么。打开浏览器并转至http:// localhost:3000。如果一切顺利,您应该看到Rails签名欢迎页面。

布局 有时间编码。我们应该从哪里开始?那么,我们可以在任何我们想要的地方开始。当我建立一个新的网站时,我喜欢从创建某种基本的视觉结构开始,然后围绕这一点构建其他所有环节。我们就这样做。

主页 当我们转到http:// localhost:3000时,我们看到了Rails欢迎页面。我们将用我们自己的主页切换这个默认页面。为了做到这一点,请生成一个名为的新控制器Pages。如果你不熟悉Rails控制器,你应该浏览一下Action Controller来了解Rails控制器是什么。在您的命令提示符下运行此行以生成新的控制器。

导轨g控制器页面 这个轨道发生器应该为我们创建了一些文件。命令提示符中的输出应该如下所示:

我们将使用它PagesController来管理我们的特殊页面和静态页面。现在在文本编辑器中打开Collabfield项目。我使用Sublime Text,但你可以使用任何你想要的。

打开一个文件 pages_controller.rb

应用程序/控制器/ pages_controller.rb 我们将在这里定义我们的主页。当然,我们可以用不同的方式在不同的控制器中定义主页。但通常我喜欢在里面定义主页PagesController。

当我们打开时pages_controller.rb,我们看到:

控制器/ pages_controller.rb 这是一个空的类,名为PagesController,从ApplicationController类继承。你可以在这里找到这个类的源代码app/controllers/application_controller.rb。

我们将创建的所有控制器都将从ApplicationController类继承。这意味着该类中定义的所有方法都将在所有控制器中可用。

我们将定义一个名为的公共方法index,因此它可以作为一个动作来调用:

控制器/ pages_controller.rb 正如您可能在操作控制器中读过的一样,路由决定了要调用哪个控制器及其公共方法(操作)。让我们定义一个路由,所以当我们打开网站的根页面时,Rails知道要调用哪个控制器及其动作。打开routes.rb文件app/config/routes.rb。

如果您不知道Rails路由是什么,那么现在是阅读Rails路由来熟悉的最佳时机。

插入这一行:

根到:'pages#index' 你的routes.rb文件应该是这样的:

配置/ routes.rb中

Ruby中的哈希符号代表一种方法。正如你所记得的,一个行动只是一个公共方法,所以pages#index说“称之为PagesController公共方法(行动)” index。

如果我们转到根路径http:// localhost:3000,则会调用索引操作。但我们还没有任何模板可供渲染。所以让我们为我们的index行动创建一个新模板。转到app/views/pages并index.html.erb在该目录中创建一个文件。在这个文件中,我们可以编写普通的HTML + 嵌入式Ruby代码。只需在文件内写入内容,即可在浏览器中看到呈现的模板。

主页</ h1> 现在,当我们转到http:// localhost:3000时,我们应该看到类似这样的内容,而不是默认的Rails信息页面。

现在我们有一个非常基本的起点。我们可以开始向我们的网站介绍新的东西。我认为是时候创建我们的第一个提交。

在你的命令提示符下运行:

git状态 你应该看到这样的东西:

如果您还不知道,那么当我们生成一个新的应用程序时,就会初始化一个新的本地git存储库。

通过运行添加所有当前更改:

git add -A 然后通过运行提交所有更改:

git commit -m“生成PagesController。初始化主页” 如果我们运行这个:

git状态 我们会看到没有什么可以提交的,因为我们只是成功提交了所有更改。

引导 对于导航栏和响应式网格系统,我们将使用Bootstrap库。为了使用这个库,我们必须安装
bootstrap-sass gem。Gemfile在你的编辑器中打开。

collabfield /的Gemfile 将bootstrap-sass宝石添加到Gemfile中。正如文件所说,你必须确保sass-rails宝石也存在。

... gem'bootstrap-sass','〜> 3.3.6'gem'sass-rails','> = 3.2' ... 保存文件并运行它来安装新添加的宝石:

捆绑安装 如果您仍在运行应用程序,请重新启动Rails服务器以确保新的宝石可用。要重新启动服务器,只需按下Ctrl + C并rails s再次运行命令来启动服务器即可关闭服务器。

转到assets打开application.css 文件:

app/assets/stylesheets/application.css

在所有评论文字下面添加:

... @import“bootstrap-sprockets”; @import“bootstrap”; 现在将application.css名称更改为application.scss。为了在Rails中使用Bootstrap库,这是必要的,它也允许我们使用Sass功能。

我们想要控制所有.scss文件的渲染顺序 ,因为将来我们可能需要创建一些Sass变量。我们希望确保在使用它们之前我们的变量将被定义。

要完成它,从application.scss文件中删除这两行:

  • = require_self
  • = require_tree。 我们几乎可以使用Bootstrap库。还有一件事我们必须做。正如bootstrap-sass文档所说,Bootstrap JavaScript依赖于jQuery库。要在Rails中使用jQuery,您必须添加jquery-rails gem。

    宝石'jquery-rails' 跑…

    捆绑安装 ...再次,并重新启动服务器。

    最后一步是在应用程序的JavaScript文件中要求Bootstrap和jQuery。去application.js

    应用程序/资产/ JavaScript的/ application.js中 然后在文件中添加以下行:

    // =需要jquery // =需要bootstrap-sprockets 提交更改:

    git add -A git commit -m“添加并配置bootstrap gem” 导航栏 对于导航栏,我们将使用Bootstrap的导航栏组件作为起点,然后对其进行彻底修改。我们会将导航栏存储在部分模板中。

    我们这样做是因为最好将应用程序的每个组件都保存在单独的文件中。它允许更容易地测试和管理应用程序的代码。此外,我们可以在应用程序的其他部分重复使用这些组件,而无需重复代码。

    导航:

    景色/布局 创建一个新文件:

    _navigation.html.erb 对于partials,我们使用下划线前缀,所以Rails框架可以将它区分为部分。现在从Bootstrap文档复制并粘贴导航栏组件并保存文件。要查看网站上的部分内容,我们必须将其呈现在某处。导航到views/layouts/application.html.erb 。这是一切呈现的默认文件。

    在文件内部,我们看到以下方法:

    <%= yield%> 它呈现请求的模板。要在HTML文件中使用ruby语法,我们必须将其包装<% %>(嵌入的ruby允许我们这样做)。要快速了解ERB语法之间的差异,请检查此StackOverflow答案。

    在主页部分,我们设置路径来识别根URL。所以,只要我们发送一个GET请求到一个根页面,PagesController‘sindex动作就会被调用。并且相应的动作(在这种情况下是index动作)响应一个模板,该模板通过该yield方法进行渲染。正如你记得,我们的主页模板位于app/views/pages/index.html.erb。

    由于我们希望在所有页面上都有导航栏,因此我们将在默认application.html.erb文件中呈现导航栏。要渲染部分文件,只需使用该render方法并将部分路径作为参数传递即可。在这样的yield方法之上做:

    ... <%= render'layouts / navigation'%> <%= yield%> ... 现在转到http:// localhost:3000,你应该能够看到导航栏。

如上所述,我们将修改此导航栏。首先,让我们删除所有

  • 元素。将来我们会在这里创建自己的元素。该_navigation.html.erb文件现在应该看起来像这样。
  • 布局/ _navigation.html.erb 我们现在有一个基本的快速导航栏。现在是创建新提交的好时机。在命令提示符下运行以下命令:

    git add -A git commit -m“添加基本导航栏” 我们应该将导航栏的名称从更改Brand为collabfield。既然Brand是链接元素,我们应该使用一种link_to方法来生成链接。为什么?因为这个方法允许我们轻松地生成URI路径。打开命令提示符并导航到项目的目录。运行以下命令:

    铁路线路 该命令输出由routes.rb文件生成的可用路由。正如我们看到的:

    目前,我们只有一条路线,即我们之前定义的路线。如果你看看给定的路线,你可以看到一Prefix列。我们可以使用这些前缀来生成想要的页面的路径。我们所要做的就是使用前缀名称并添加_path到它。如果我们写了root_path,那会生成一个根页面的路径。所以让我们使用link_to方法和路线的力量。

    替换这一行:

    品牌 有了这条线:

    <%= link_to'collabfield',root_path,class:'navbar-brand'%> 请记住,只要您不太明白特定方法的工作原理,只需Google即可,并且您可能会找到其解释文档。有时文档写得不好,所以你可能希望谷歌多一点,你可能会发现一个博客或StackOverflow的答案,这将有所帮助。

    在这种情况下,我们传递一个字符串作为第一个参数来添加元素的值,第二个参数是一个路径需要的,这是路径帮助我们生成它的地方。第三个参数是可选的,它是在选项散列内部累积的。在这种情况下,我们需要添加navbar-brand类以保持Bootstrap动力导航栏的正常运行。

    让我们为这个小小的改变做另一次提交。在即将开始的部分中,我们将从导航栏开始更改我们应用的设计。

    git add -A git commit -m“将导航栏的品牌名称从Brand更改为collabfield” 样式表 让我介绍一下如何构建我的样式表文件。从我所知道的没有任何有关如何在Rails中构造样式表的强大约定。每个人都有不同的做法。

    这是我通常构造文件的方式。

    基本目录  - 这是我保存在整个应用程序中使用的Sass变量和样式的地方。例如默认字体大小和默认元素的样式。 部分  - 我的风格大部分去那里。我在这个目录中保留单独组件和页面的所有样式。 响应  - 这里我为不同的屏幕尺寸定义不同的样式规则。例如,桌面屏幕,平板电脑屏幕,手机屏幕等的样式。 首先,让我们通过运行这个来创建一个新的版本库分支:

    git checkout -b“样式” 我们刚刚创建了一个新的git分支并自动切换到它。从现在开始,我们将如何实现对代码的新更改。

    这样做的原因是我们可以隔离我们当前的功能版本(主分支),并在项目副本中写入新代码,而不会害怕损坏任何东西。

    一旦我们完成了实现,我们可以将更改合并到master分支。

    首先创建几个目录:

    应用程序/资产/样式表/谐音/布局 在布局目录内创建一个文件navigation.scss并在文件内添加:

    应用程序/资产/样式表/谐音/布局/ navigation.scss 通过这些代码行,我们可以更改导航栏的背景和链接颜色。您可能已经注意到,a选择器嵌套在另一个声明块中。Sass允许我们使用这个功能。 !important用于严格覆盖默认的Bootstraps样式。您可能已经注意到的最后一件事是,我们使用Sass变量而不是颜色名称。原因是我们要在整个应用中多次使用这种颜色。我们来定义这个变量。

    首先创建一个新文件夹:

    应用程序/资产/样式表/碱 在基目录内创建一个新文件variables.scss。在文件内部定义一个变量:

    $ navbarColor:#323738; 如果您尝试访问http:// localhost:3000,则不会注意到任何样式更改。原因是在Bootstrap部分我们删除了这些行:

    • = require_self
    • = require_tree。 从application.scss,不自动导入所有样式文件。

      这意味着现在我们必须将我们新创建的文件导入到主application.scss文件中。该文件现在应该如下所示:

    应用程序/资产/样式表/ application.scss variables.scss在顶部导入文件的原因是为了确保在我们使用它们之前定义变量。

    在navigation.scss文件顶部添加更多CSS :

    应用程序/资产/样式表/谐音/布局/ navigation.scss 当然,如果你愿意,你可以把这段代码放在文件的底部。就我个人而言,我根据CSS选择器的特殊性对CSS代码进行了排序和分组。再一次,每个人都略有不同。我在下面放置了更少的特定选择器和更具体的选择器。因此,例如类型选择器高于类选择器和类选择器高于ID选择器。

    让我们进行修改:

    git add -A git commit -m“将CSS添加到导航栏” 我们希望确保导航栏始终可见,即使向下滚动也是如此。目前我们没有足够的内容向下滚动,但我们会在将来。为什么我们现在不把这个功能给导航栏?

    要做到这一点使用Bootstrap类navbar-fixed-top。将这个类添加到nav元素中,所以它看起来像这样:

    它应该是这样的:

    提交更改:

    git add -A git commit -m“

    • 在_navigation.html.erb中将navbar-fixed-top类添加到nav中
    • 用容器替换容器流体类” 如果转到http:// localhost:3000,您会看到Home page文本隐藏在导航栏下。那是因为这个navbar-fixed-top班。要解决此问题,请通过将以下内容添加到以下内容来推倒主体navigation.scss:

      body { margin-top:50px; } 在这个阶段,应用应该看起来像这样:

    提交更改:

    git add -A git commit -m“将margin-top 50px添加到正文” 正如你记得的,我们之前已经创建了一个新的分支并切换到它。现在是时候回到master分支机构了。

    运行命令:

    git分支 你可以看到我们分支机构的名单。目前我们在styles分支机构。

    要切换回master分支,请运行:

    git checkout master 要合并我们在styles分支中完成的所有更改,只需运行:

    git合并样式 该命令合并了这两个分支,现在我们可以看到我们所做更改的摘要。

    我们不再需要styles分支,所以我们可以删除它:

    git分支-D样式 帖子 现在几乎是开始实施帖子功能的正确时机。由于我们的应用目标是让用户遇到志趣相投的人,所以我们必须确保可以识别帖子的作者。为了实现这一点,需要认证系统。

    认证 对于认证系统,我们将使用设计宝石。我们可以创建自己的认证系统,但这需要付出很大的努力。我们会选择一条更简单的路线。它也是Rails社区中的热门选择。

    首先创建一个新的分支:

    git checkout -b认证 就像其他任何宝石一样,要设置它,我们将遵循其文档。幸运的是,这很容易设置。

    添加到你的 Gemfile

    宝石'设计' 然后运行命令:

    捆绑安装 导轨生成设计:安装 您可能会在命令提示符下看到一些说明。我们不会在本教程中使用邮件程序,因此不需要进一步的配置。

    此时,如果您对Rails模型一无所知,您应该通过浏览Active Record和Active Model文档来熟悉它们。

    现在让我们使用一个设计生成器来创建一个User模型。

    轨道生成设计用户 运行以下命令为应用程序初始化数据库:

    rails db:create 然后运行这个命令在数据库中创建新的表格:

    rails db:migrate 而已。从技术上讲,我们的认证系统已经建立。现在我们可以使用Devise给定的方法并创建新的用户。提交更改:

    git add -A git commit -m“添加并配置Devise gem” 通过安装Devise gem,我们不仅可以获得后端功能,还可以获得默认视图。如果您通过运行列出您的路线:

    铁路线路

    你可以看到,现在你有一堆新的路线。请记住,直到现在我们只有一条根路线。如果有些事情似乎令人困惑,你可以随时打开设计文档并获得答案。另外不要忘记,许多相同的问题也会引起别人的注意。你很有可能会通过谷歌搜索找到答案。

    尝试一些这些路线。转到localhost:3000 / users / sign_in,您应该看到一个登录页面。

    如果您转到localhost:3000 / users / sign_up,您也会看到一个注册页面。上帝该死!就像Noob Noob所说的那样。如果你看views目录,你会发现没有任何Devise目录,我们可以修改它。正如Devise文档所说,为了修改Devise视图,我们必须使用设计生成器来生成它。跑

    rails生成设计:视图 如果你检查views目录,你会在里面看到一个生成的设计目录。在这里,我们可以修改注册和登录页面的外观。让我们从登录页面开始,因为在我们的例子中,这将是一个更直接的实现。有了注册页面,由于我们想要的功能,需要额外的努力。

    登录页面

    导航到并打开app/views/devise/sessions/new.html.erb。

    这是存储登录页面视图的地方。文件内只有一个登录表单。您可能已经注意到,该form_for方法用于生成此表单。这是一个方便的Rails方法来生成表单。我们将用bootstrap修改这个表单的样式。将所有文件的内容替换为:

    意见/设计/会话/ new.html.erb 这里没有什么特别的。我们只是通过改变方法名称bootstrap_form_for并将form-control类添加到字段来修改此表单为引导表单。

    看看这些方法中的参数是如何设计的。每个参数都以新的行开始。我之所以这样做是为了避免长时间的代码行。通常代码行不应该超过80个字符,它会提高可读性。我们将在指南的其余部分为代码设计风格。

    如果我们访问localhost:3000 / users / sign_in,我们会看到它给我们一个错误:

    未定义的方法'bootstrap_form_for' 为了在Rails中使用引导形式,我们需要添加一个bootstrap_form gem。将此添加到Gemfile

    宝石'bootstrap_form' 然后运行:

    捆绑安装 此时登录页面应该如下所示:

    提交更改:

    git add -A git commit -m“生成设计视图,修改登录表单 并添加bootstrap_form gem。” 要将引导程序的网格系统提供给页面,请使用引导程序容器包装登录表单。

    意见/设计/会话/ new.html.erb 登录表单的宽度是12列中的6列,偏移量是3列。在较小的设备上,表单将采用全屏宽度。这就是引导网格的工作原理。

    让我们做另一个提交。很小的变化,是吧?但这就是我通常所做的承诺。我在一个领域实施了明确的改变,然后提交。我认为这样做有助于跟踪变化并理解代码是如何演变的。

    git add -A git commit -m“使用boostrap容器在登录页面中包装登录表单” 如果我们可以通过去/login取代登录页面,那会更好/users/sign_in。我们必须改变路线。要做到这一点,我们需要知道在进入登录页面时被调用的动作位于何处。设计控制器位于宝石本身内部。通过阅读设计文档,我们可以看到所有控制器都位于devise目录内。这个发现并不令人惊讶,说实话U_U。通过使用该devise_scope方法,我们可以简单地更改路线。转到routes.rb文件并添加

    devise_scope:用户 获得'登录',即:'设计/会话#新' 结束 提交更改:

    git add -A git commit -m“将路由从/ users / sign_in更改为/ login” 现在,让登录页面保持原样。

    注册页面

    如果我们导航到localhost:3000 / users / sign_up,我们会看到默认的设计注册页面。但如上所述,注册页面需要额外的努力。为什么?因为我们想:name在users表中添加一个新 列,所以User对象可以具有该 :name属性。

    我们即将对schema.rb文件进行一些更改。此时,如果您不太熟悉模式更改和迁移,我建议您阅读Active Record Migrations文档。

    首先,我们必须在users表中添加一个额外的列。我们可以创建一个新的迁移文件并使用一种change_table方法来添加一个额外的列。但我们只处于开发阶段,我们的应用程序尚未部署。我们可以直接在devise_create_users迁移文件中定义一个新列,然后重新创建数据库。导航到db/migrate并打开CREATION_DATE_devise_create_users.rb文件并添加t.string :name, null: false, default: ""到create_table方法中。

    现在运行命令删除并创建数据库,然后运行迁移。

    rails db:drop rails db:create rails db:migrate 我们在用户表中添加了一个新列并更改了schema.rb文件。

    为了能够发送额外的属性,所以Devise控制器会接受它,我们必须在控制器级别上进行一些更改。我们可以用几种不同的方式对Devise控制器进行更改。我们可以使用设计生成器并生成控制器。或者我们可以创建一个新文件,指定控制器和我们想要修改的方法。两种方式都很好。我们打算使用后者。

    导航到app/controllers并创建一个新文件registrations_controller.rb。将以下代码添加到文件中:

    控制器/ registrations_controller.rb 此代码覆盖接受该属性的方法sign_up_params和account_update_params方法 :name。如你所见,这些方法都在Devise中RegistrationsController,所以我们指定了它并改变了它的方法。现在在我们的路线中,我们必须指定这个控制器,所以这些方法可以被覆盖。内部routes.rb改变

    devise_for:用户 至

    devise_for:users,:controllers => {:registrations =>“registrations”} 提交更改。

    git add -A git commit -m“

    • 将名称列添加到用户表中
    • 将名称属性包含 在RegistrationsController中的sign_up_params和account_update_params 方法中” 打开new.html.erb文件:

      应用程序/视图/设计/注册/ new.html.erb 再次,删除除表格之外的所有内容。将表单转换为引导表单。这次我们添加一个额外的名称字段。

    意见/设计/注册/ new.html.erb 提交更改。

    git add -A git commit -m“ 从注册页面中删除除表格以外的所有内容 将表单转换为引导表单添加一个额外的名称字段” 用引导容器包装表单并添加一些文本。

    意见/设计/注册/ new.html.erb 提交更改。

    git add -A git commit -m“ 用引导容器包装注册表单,在容器 内添加信息文本” 就像登录页面一样,如果我们可以通过/signup转而打开注册页面,则会更好users/sign_up。在routes.rb文件内添加以下代码:

    devise_scope:用户 获得'注册',以:'设计/注册#新' 结束 提交更改。

    git add -A git commit -m“将注册页面的路由从/ users / sign_up更改为/注册” 在我们继续之前,我们先应用一些样式更改。导航到app/assets/sytlesheets/partials并创建一个新signup.scss文件。在文件中添加以下CSS:

    资产/样式表/谐音/ signup.scss 我们还没有从文件partials目录中导入application.scss文件。我们现在就做。导航到application.scss上方@import partials/layout/*,从partials目录导入所有文件。Application.scss应该看起来像这样

    资产/样式表/ application.scss 提交更改。

    git add -A git commit -m“

    • 创建一个signup.scss并将CSS添加到注册页面
    • 将所有文件从partials目录导入到application.scss” 添加一些其他风格的变化,整体网站的外观。导航到app/assets/stylesheets/base并创建一个新default.scss文件。在文件中添加以下CSS代码:

    资产/样式表/碱/ default.scss 在这里,我们为整个网站应用一些一般风格的变化。font-size被设置为62.5%,所以1 rem单位可以表示10px。如果您不知道rem单元是什么,您可能需要阅读本教程。我们不希望在引导表单上看到标签文本,这就是为什么我们要这样设置:

    .control-label { display:none; } 您可能已经注意到使用了该$backgroundColor变量。但是这个变量还没有设置。所以让我们通过打开variables.scss文件并添加这个来做到这一点:

    $ backgroundColor:#f0f0f0; 该default.scss文件不在内部导入application.scss。在变量下面导入它,该application.scss文件应该如下所示:

    资产/样式表/ application.scss 提交更改。

    git add -A git commit -m“ 在主文件中添加CSS并导入CSS文件

    • 创建一个default.scss文件并添加CSS
    • 定义$ backgroundColor变量
    • 在application.scss中导入default.scss文件“ 导航栏更新

      现在我们有三个不同的页面:家庭,登录和注册。将它们连接在一起是一个好主意,因此用户可以毫不费力地浏览网站。我们会在导航栏上放置注册和登录页面的链接。导航到并打开_navigation.html.erb文件。

      应用程序/视图/布局/ _navigation.html.erb 我们将在这里添加一些额外的代码。将来我们会在这里添加更多的代码。这将导致一个有很多代码的文件,这是很难管理和测试。为了更容易地处理长代码,我们将开始将更大的代码拆分成更小的代码块。为了实现这一点,我们将使用partials。在添加额外的代码之前,我们_navigation.html.erb先将当前代码拆分为部分代码。

      让我快速向您介绍我们的导航栏如何工作。我们将有两个主要部分。无论屏幕尺寸是多少,元素都会一直显示。在导航栏的另一部分,元素将仅在较大的屏幕上显示,并在较小的屏幕上显示。

      这就是.container元素内部结构的 外观:

    布局/ _navigation_html.erb 里面的layouts目录:

    应用/视图/布局 创建一个新navigation目录。在此目录内创建一个新的部分_header.html.erb文件。

    应用程序/视图/布局/导航/ _header.html.erb 从_navigation.html.erb文件中剪切整个 .navbar-header部分并将其粘贴到_header.html.erb文件中。在navigation目录中,创建另一个名为的部分文件_collapsible_elements.html.erb 。

    应用程序/视图/布局/导航/ _collapsible_elements.html.erb 从_navigation.html.erb文件剪下整个 .navbar-collapse部分并粘贴在内部_collapsible_elements.html.erb。现在让我们在_navigation.html.erb文件中渲染这两个部分。该文件现在应该看起来像这样。

    布局/ _navigation_html.erb 如果你现在去了http:// localhost:3000,你不会注意到任何区别。我们只是清理了一下我们的代码,并为进一步的开发做好了准备。

    我们准备添加一些链接到导航栏。_collapsible_elements.html.erb再次导航到并再次打开该文件:

    应用程序/视图/布局/ _collapsible_elements.html.erb 让我们用链接填充这个文件,用以下内容替换文件的内容:

    布局/导航/ _collapsible_elements.html.erb 让我简单地向你解释这里发生了什么。首先,在第二行我将元素id改为navbar-collapsible-content。为了使这个内容可以折叠,这是必需的。这是一个引导程序的功能。默认id是bs-example-navbar-collapse-1。为了触发这个功能,这个按钮data-target在_header.html文件中有属性。打开views/layouts/navigation/_header.html.erb并将data-target属性更改为data-target="#navbar-collapsible-content"。现在该按钮将触发可折叠的内容。

    接下来,在_collapsible_elements.html.erb文件内部,if else用user_signed_in?Devise方法看到一些逻辑。这将根据用户是否登录显示不同的链接。if else在视图内留下逻辑,如语句不是一个好习惯。观点应该是非常“愚蠢的”,只是吐出信息,根本不“思考”。稍后我们将用Helpers重构这个逻辑。

    需要注意的最后一件事情里面的文件pc-menu和mobile-menuCSS类。这些类的目的是控制链接在不同屏幕尺寸上的显示方式。我们为这些类添加一些CSS。导航到app/assets/stylesheets并创建一个新目录responsive。在目录内创建两个文件,desktop.scss并mobile.scss。这些文件的目的是针对不同的屏幕尺寸有不同的配置。在desktop.scss文件里添加:

    资产/ styleshseets /响应/ desktop.scss 在mobile.scss文件里添加:

    资产/ styleshseets /响应/ mobile.scss 如果你不熟悉CSS媒体查询,阅读此。从responsive文件内的目录导入application.scss文件。将它导入到文件的底部,所以application.scss应该如下所示:

    应用程序/资产/样式表/ application.scss 导航到并打开navigation.scss文件

    应用程序/资产/样式表/谐音/布局/ navigation.scss 并通过在nav元素的选择器中添加以下内容来对导航栏进行一些风格调整:

    资产/ styleshseets /谐音/布局/ navigation.scss 在nav元素外部,添加以下CSS代码:

    资产/ styleshseets /谐音/布局/ navigation.scss 此时,当用户未登录时,我们的应用程序应该如下所示:

    当用户登录时就像这样:

    当屏幕尺寸较小时,就像这样:

    提交更改。

    git add -A git commit -m“ 更新导航栏

    • 在导航栏上添加登录,注册,注销和编辑配置文件链接
    • 将_navigation.scss代码拆分为部分
    • 在样式表目录内创建响应目录并添加CSS。

      • 添加CSS来调整导航栏风格“ 现在我们有一个基本的认证功能。它满足我们的需求。所以让我们将authentication分支合并到master分支。

      git checkout master git merge认证 我们可以再次看到更改的摘要。认证分支不再需要,所以删除它。

      git分支-D认证 助手 当我们在处理_collapsible_elements.html.erb文件时,我提到Rails视图不适合逻辑。如果您查看app项目的目录,则会看到名为的目录helpers。我们将从Rails视图中提取逻辑并将其放入helpers目录中。

      应用程序/视图/页 让我们创建我们的第一个助手。首先,创建一个新的分支并切换到它。

      git checkout -B助手 导航到该helpers目录并创建一个新navigation_helper.rb文件

      应用程序/佣工/ navigation_helper.rb 在帮助程序文件中,帮助程序被定义为模块。在navigation_helper.rb定义模块内部。

    应用程序/佣工/ navigation_helper.rb 默认情况下,Rails将所有帮助文件加载到所有视图。就我个人而言,我不喜欢这样,因为来自不同助手文件的方法名称可能会发生冲突。要覆盖此默认行为,请打开该application.rb文件

    配置/ application.rb中 在Application课堂内部添加这个配置

    config.action_controller.include_all_helpers = false 现在,助手只能用于相应的控制器视图。因此,如果我们有PagesController,pages_helper.rb文件内的所有助手将可用于目录内的所有视图文件pages。

    我们没有NavigationController,所以NavigationHelper模块内定义的辅助方法在任何地方都不可用。导航栏在整个网站上都可用。我们可以在NavigationHelper里面包含模块ApplicationHelper。如果您不熟悉加载和包含文件,请阅读本文以了解将要发生的情况。

    在application_helper.rb文件内部,需要navigation_helper.rb文件。现在我们可以访问navigation_helper.rb文件的内容。所以让我们通过使用方法NavigationHelper在模块内注入模块。本应该是这样的:ApplicationHelperincludeapplication_helper.rb

    助手/ application_helper.rb 现在NavigationHelper,整个应用程序都可以使用助手方法。

    导航到并打开_collapsible_elements.html.erb文件

    应用程序/视图/布局/导航/_collapsible_elements.html.erb 我们将把if else语句内的内容拆分为部分内容。collapsible_elements在navigation目录中创建一个新目录。

    应用程序/视图/布局/导航/collapsible_elements 在目录内创建两个文件:_signed_in_links.html.erb和_non_signed_in_links.html.erb。现在从_collapsible_elements.html.erb文件的if else语句中剪切内容并将其粘贴到相应的部分。部分应该看起来像这样:

    布局/导航/ collapsible_elements / _signed_in_links.html.erb

    布局/导航/ collapsible_elements / _non_signed_in_links.html.erb 现在在_collapsible_elements.html.erb文件中,而不是if else语句,添加render方法与collapsible_links_partial_path辅助方法作为参数。该文件应该看起来像这样

    布局/导航/ _collapsible_elements.html.erb collapsible_links_partial_path是我们要在里面定义的方法NavigationHelper。打开navigation_helper.rb

    应用程序/佣工/ navigation_helper.rb 并定义模块内部的方法。该navigation_helper.rb文件应该看起来像这样:

    应用程序/佣工/ navigation_helper.rb 定义的方法非常简单。如果用户登录,则返回相应的部分路径。如果用户未登录,则返回另一个部分的路径。

    我们创建了我们的第一个帮助器方法,并将视图中的逻辑提取到辅助方法中。无论何时我们在视图文件中遇到逻辑,我们都会为指南的其余部分执行此操作。通过这样做,我们为自己做了一件好事,测试和管理应用程序变得更加容易。

    该应用程序应该看起来和功能相同。

    提交更改。

    git add -A git commit -m“配置并创建助手

    • 将include_all_helpers配置更改为false
    • 拆分_collapsible_elements.html.erb file's content into partials and extract logic from the file into partials" 将helpers分支合并到master

      git checkout master git merge helpers https://gist.github.com/domagude/419bba70cb97e27f4ea04fe37820194a#file-rails_helper-rb 测试 此时该应用程序具有一些功能。即使认为目前还没有很多功能,但是如果我们想确保一切正常,我们已经不得不花费一些时间手动测试应用程序。想象一下,如果应用程序的功能比现在多20倍以上。每次我们修改代码时,检查一切正常,这是多么令人沮丧的事情。为了避免这种沮丧和几个小时的手动测试,我们将实施自动化测试。

      在深入测试写作之前,请允许我向您介绍我如何以及测试什么。您也可以阅读“测试Rails应用程序指南”以熟悉默认的Rails测试技术。

      我用来测试的东西

      框架:RSpec 当我开始测试我的Rails应用程序时,我使用了默认的Minitest框架。现在我使用RSpec。我认为这里没有好的或不好的选择。这两个框架都很棒。我认为这取决于个人喜好,使用哪个框架。我听说RSpec是Rails社区中的热门选择,所以我决定试试看。现在我大部分时间都在使用它。 示例数据:factory_girl 同样,我首先尝试使用默认的Rails方式 -  fixtures来添加示例数据。我发现这与测试框架不同。选择哪种测试框架可能是个人偏好。在我看来,样本数据并非如此。起初固定装置很好。但我注意到,在应用程序变大后,用夹具控制样品数据变得困难。也许我用错了方式。但是,随着工厂,一切都很好,和平马上。无论应用程序是更小还是更大 - 设置样本数据的努力都是一样的。 验收测试: 水豚 默认情况下,Capybara使用rack_test驱动程序。很抱歉,此驱动程序不支持JavaScript。我没有选择默认的水豚的驱动程序,而是选择了使用poltergeist。它支持JavaScript,在我的情况下,它是最容易设置的驱动程序。 我测试的是什么

      我测试了我写的所有逻辑。它可能是:

      助手 楷模 工作 设计模式 我写的任何其他逻辑 除了逻辑之外,我还使用Capybara接受测试来包装我的应用程序,以确保所有应用程序的功能都可以通过模拟用户的交互来正常工作。同样为了帮助我进行模拟测试,我使用请求测试来确保所有请求都返回正确的响应。

      这就是我在我的个人应用程序中测试的结果,因为它完全满足了我的需求。显然,测试标准可能因人而异,从公司到公司不同。

      没有提到控制者,观点和宝石,为什么?正如许多Rails开发人员所说,控制器和视图不应包含任何逻辑。我同意他们。在这种情况下,没有太多的测试。在我看来,用户模拟测试对视图和控制器来说是足够高效的。宝石已经由他们的创造者进行过测试。所以我认为模拟测试足以确保宝石能够正常工作。

      我如何测试

      当然,只要有可能,我都会尝试使用TDD方法。先写一个测试然后执行代码。在这种情况下,开发流程变得更加平滑。但是有时候你不确定完成的功能将如何看起来以及期望的输出类型。您可能正在尝试代码或仅尝试不同的实施解决方案。所以在这些情况下,先测试然后再执行实际上并不奏效。

      之前(有时在上面讨论过之后)我写的每一段逻辑,我都写了一个单独的测试单元测试。为了确保应用程序的每个功能都能正常工作,我使用Capybara编写验收(用户模拟)测试。

      建立一个测试环境

      在我们编写第一次测试之前,我们必须配置测试环境。

      打开Gemfile并将这些宝石添加到测试组

      宝石“rspec的护栏”,“〜> 3.6” 宝石“factory_girl_rails” 宝石“轨控制器-测试” 宝石“无头” 宝石“水豚” 宝石“骚灵” 宝石“database_cleaner” 如上所述,rspecgem是一个测试框架,factory_girl用于添加示例数据,capybara用于模拟用户与应用poltergeist程序的交互,驱动程序为您的测试提供JavaScript支持。

      如果您更容易设置,您可以使用其他支持JavaScript的驱动程序。如果你决定使用poltergeist宝石,你需要安装PhantomJS。要安装PhantomJS阅读poltergeist文档。

      headless宝石需要支持无头驱动程序。poltergeist是一个无头的司机,这就是为什么我们需要这个宝石。rails-controller-testing当我们将测试请求和请求规格的响应时,gem将会被要求。稍后更多。

      database_cleaner需要在执行JavaScript的测试之后清理测试数据库。正常情况下,测试数据库在每次测试后自行清理,但是当您测试具有某些JavaScript的功能时,数据库不会自动进行自我清理。它可能会在未来发生变化,但在编写本教程时,在执行JavaScript测试后,测试数据库不会自动清理。这就是为什么我们必须在每次JavaScript测试之后手动配置我们的测试环境以清理测试数据库。我们将配置何时运行database_cleaner宝石。

      现在,当这些宝石的目的被覆盖时,让我们通过运行来安装它们:

      捆绑安装 要初始化specRSpec框架的目录,请运行以下命令:

      rails generate rspec:install 一般来说,spec是指RSpec框架中的单一测试。当我们运行我们的规格时,这意味着我们运行我们的测试。

      如果您查看app目录内部,您会注意到一个名为的新目录spec。这是我们要编写测试的地方。你也可能注意到一个叫做目录test。这是您使用默认测试配置时存储测试的地方。我们根本不会使用这个目录。您可以简单地从项目c(x_X)中删除它b。

      如上所述,我们必须设置database_cleaner包含JavaScript的测试。打开rails_helper.rb文件

      投机/ rails_helper.rb 改变这一行

      config.use_transactional_fixtures = true 至

      config.use_transactional_fixtures = false 并在下面添加以下代码:

    投机/ rails_helper.rb 我从本教程中获取了这段代码片段。

    我们要做的最后一件事是添加一些配置。在rails_helper.rb文件的配置中,添加以下行

    投机/ rails_helper.rb 让我们稍微分解一下代码。

    使用require方法我们从新添加的gem中加载文件,所以我们可以在下面使用它们的方法。

    config.include Devise :: Test :: IntegrationHelpers,输入::feature 这个配置允许我们devise在capybara测试中使用方法。我是怎么想到这一行的?它是在Devise文档中提供的。

    config.include FactoryGirl :: Syntax :: Methods 这种配置允许使用factory_girl宝石的方法。同样,我在gem的文档中找到了这个配置。

    Capybara.javascript_driver =:poltergeist Capybara.server =:美洲狮 为了能够测试JavaScript,需要这两个配置capybara。当你想要实现你不知道如何去做的事情时,总是先阅读文档。

    在我们遇到特定问题时,我一次性向大家介绍大部分测试宝石和配置,而不是逐渐向大家介绍测试宝石和配置的原因是为了让您清楚地了解我用于测试的内容。现在您可以随时回到本节,并在一个地方查看大部分配置。而不是从一个地方跳到另一个地方,把宝石像拼图一样放在一起。

    让我们进行修改,最后让我们的手与测试一起弄脏。

    git add -A git commit -m“ 设置测试环境

    • 删除测试目录
    • 添加和配置rspec-rails,factory_girl_rails, rails-controller-testing,headless,水豚,poltergeist, database_cleaner gems“ 帮手规格

      关于每种类型的规格(测试),您可以通过阅读rspec文档及其gem文档来找到一般信息。两者都非常相似,但你可以找到彼此之间的一些差异。

      创建并切换到新的分支:

      git checkout -b规格 到目前为止,我们只创建了一个辅助方法。我们来测试一下。

      导航到spec目录https://gist.github.com/domagude/3c42ba6ccf31bf1c50588c59277a9146#file-navigation_helper_spec-rb d创建一个名为的新目录helpers。

      投机/佣工 在目录中,创建一个新文件 navigation_helper_spec.rb

      规格/助理/ navigation_helper_spec.rb 在文件里面,写下面的代码:

    规格/助理/ navigation_helper_spec.rb require ‘rails_helper'使我们能够访问所有测试配置和方法。 :type => :helper将我们的测试视为辅助规格,并为我们提供特定的方法。

    这就是测试navigation_helper_spec.rb该collapsible_links_partial_path方法时文件的外观。

    规格/助理/ navigation_helper_spec.rb 要详细了解context和it,请阅读基本结构文档。在这里,我们测试两个案例-当用户在当未登录用户登录在各个方面。signed in user而non-signed in user我们有挂钩之前。在相应的上下文中,这些钩子(方法)在每个测试之前运行。在我们的例子中,在每次测试之前,我们运行存根方法,因此user_signed_in?返回我们告诉它返回的任何值。

    最后,通过期望方法,我们检查当我们调用collapsible_links_partial_path方法时,我们得到预期的返回值。

    要运行所有测试,只需运行:

    rspec规范 要专门运行该navigation_helper_spec.rb文件,请运行:

    rspec spec / helpers / navigation_helper_spec.rb 如果测试通过,输出应该看起来类似于:

    提交更改。

    git add -A git commit -m“将规范添加到NavigationHelper的collapsible_links_partial_path方法中” 工厂

    接下来,我们需要一些示例数据来执行我们的测试。factory_girl只要我们需要,gem就能够非常轻松地添加示例数据。它还提供了一个高质量的文档,所以它使整体体验非常愉快。我们可以用我们的应用程序创建的唯一对象是User。要定义用户工厂,请factories在该spec目录内创建一个目录。

    规格/工厂。 在factories目录内创建一个新文件users.rb并添加以下代码:

    规格/工厂/用户 现在,在我们的规范中,我们可以在测试数据库内轻松地创建新用户,只要我们需要它们,就可以使用factory_girlgem的方法。有关如何定义和使用工厂的综合指南,请查看factory_girlgem的文档。

    我们定义的工厂user非常简单。我们定义了user对象的值。我们也使用了这种sequence方法。通过阅读文档,您可以看到每增加一条User记录,n值就会增加一个。即第一个创建的用户名将会是test0第二个test1,等等。

    提交更改。

    git add -A git commit -m“添加用户工厂” 功能规格

    在功能规格中,我们编写了模拟用户与应用程序交互的代码。功能规格由capybara宝石驱动。

    好消息是,我们已经准备好编写我们的第一个功能规格了。我们将测试登录,注销和注册功能。

    在spec目录中,创建一个名为的新目录features。

    规格/功能 在features目录中,创建另一个名为user。

    规格/特征/用户 在user目录中,创建一个名为的新文件login_spec.rb

    规格/特征/用户/ login_spec.rb 这就是登录测试的样子:

    规格/特征/用户/ login_spec.rb 通过此代码,我们模拟从主页开始访问登录页面。然后填写表格并提交。最后,我们检查#user-settings导航栏上是否有元素,该元素仅适用于已登录的用户。

    feature并且scenario是Capybara语法的一部分。feature与context/ 相同,describe并且scenario与之相同it。更多信息你可以在Capybara的文档中找到,使用水豚与Rspec。

    let 方法允许我们编写记忆的方法,我们可以在上下文中的所有规范中使用,方法已定义。

    在这里我们也使用我们创建的users工厂和create方法,它与factory_girl宝石一起提供。

    js: true 参数允许测试涉及JavaScript的功能。

    与往常一样,要查看测试是否通过,请运行特定文件。在这种情况下,它是login_spec.rb文件:

    rspec spec / features / user / login_spec.rb 提交更改。

    git add -A git commit -m“添加登录功能规格” 现在我们可以测试注销功能。在user目录中,创建一个名为的新文件logout_spec.rb

    规格/特征/用户/ logout_spec.rb 实施的测试应该如下所示:

    规格/特征/用户/ logout_spec.rb 该代码模拟用户单击注销按钮,然后希望在导航栏上看到未登录的用户链接。

    sign_in方法是Devise帮助器方法之一。我们rails_helper.rb以前在文件中包含了这些辅助方法。

    运行该文件以查看测试是否通过。

    提交更改。

    git add -A git commit -m“添加注销功能规格” 我们拥有的最后一项功能是能够注册一个新帐户。我们来测试一下。在user目录内创建一个名为的新文件sign_up_spec.rb。这就是内部测试的文件应该如下所示:

    规格/特征/用户/ sign_up_spec.rb 我们模拟用户导航到注册页面,填写表单,提交表单,最后,我们希望看到#user-settings只能用于登录用户的元素。

    这里我们使用Devise的build方法来代替create。这样我们创建一个新的对象而不将它保存到数据库中。

    我们可以运行整个测试套件并查看是否所有测试都通过了。

    rspec规范

    提交更改。

    git add -A git commit -m“添加注册功能规格” 我们完成了我们的第一次测试。所以让我们把specs分支和master。

    git checkout master git合并规范 规格分支不再需要。将其删除q__o。

    git分支-D规格 主要饲料 在主页上,我们将创建一个帖子供稿。此Feed将以卡片格式显示所有类型的帖子。

    首先创建一个新的分支:

    git checkout -b main_feed 生成一个叫做的新模型Post。

    轨道g模型职位 然后,我们需要一个Category模型来对帖子进行分类:

    导轨g型号类别 现在,让我们创造出一些社团之间User,Category和Post模型。

    每篇文章将属于一个类别及其作者(用户)。打开模型文件并添加关联。

    class Post <ApplicationRecord belongs_to:user belongs_to:category end class User <ApplicationRecord ... has_many:posts,dependent::destroy
    end class Category <ApplicationRecord has_many:posts 结束 该dependent: :destroy说法称,当用户被删除,哪些用户已创建的所有职位也将被删除。

    现在我们必须在迁移文件中定义数据列和关联。

    分贝/迁移/ CREATION_DATE_create_posts.rb

    分贝/迁移/ CREATION_DATE_create_categories.rb 现在运行迁移文件:

    rails db:migrate 提交更改:

    git add -A git commit -m“

    • 生成Post和Category模型
    • 在User,Post和Category模型之间创建关联
    • 创建类别并发布数据库表格。” 眼镜

      我们可以测试新创建的模型。稍后我们需要测试的样本数据。由于帖子属于某个类别,因此我们还需要类别的样本数据来设置关联。

      category在factories目录中创建一个工厂。

      规格/工厂/ categories.rb

      规格/工厂/ categories.rb post在factories目录中创建一个工厂

      规格/工厂/ posts.rb

      规格/工厂/ posts.rb 如您所见,为工厂建立关联非常简单。我们只需要在工厂内写下工厂的名字就可以建立工厂user和category协会。postpost

      提交更改。

      git add -A git commit -m“添加帖子和类别工厂” 现在我们只测试关联,因为这是我们在模型中写的唯一的东西。

      打开 post_spec.rb

      规格/型号/ post_spec.rb 为关联添加规格,所以文件应该如下所示:

    规格/型号/ post_spec.rb 我们使用该described_class方法来获取当前上下文的类。这与写作Post案例基本相同。然后我们使用reflect_on_association方法来检查它是否返回正确的关联。

    对其他型号也一样。

    规格/型号/ category_spec.rb

    规格/型号/ user_spec.rb 提交更改。

    git add -A git commit -m“为用户,类别,发布模型的关联添加规格” 主页布局 目前主页内没有内容,只有虚拟文本“主页”。现在是时候用bootstrap创建它的布局了。打开主页的视图文件,views/pages/index.html.erb并用下面的代码替换文件的内容来创建页面的布局:

    视图/页/ index.html.erb 现在添加一些CSS来定义元素的样式和响应行为。

    在stylesheets/partials目录内创建一个新文件home_page.scss

    资产/样式表/谐音/ home_page.scss 在文件中添加以下CSS:

    资产/样式表/谐音/ home_page.scss 在mobile.scss文件的max-width: 767px媒体查询内添加:

    资产/样式表/响应/ mobile.scss 现在主页应该在更大的屏幕上看起来像这样

    在小屏幕上就像这样

    提交更改。

    git add -A git commit -m“

    • 将引导程序布局添加到主页
    • 添加CSS以使主页布局的文体和响应式设计更改” 种子

      要在主页上显示帖子,首先我们需要将它们放入数据库中。手动创建数据无聊且耗时。为了使这个过程自动化,我们将使用种子。打开seeds.rb文件。

      DB / seeds.rb 添加下面的代码:

    DB / seeds.rb 正如你看到的,我们创建seed_users,seed_categories和seed_posts方法来创建User,Category并Post在开发数据库中的记录。另外,骗子宝石是用来生成虚拟文本。添加faker宝石到你的Gemfile

    宝石'faker' 和

    捆绑安装 要使用该seeds.rb文件对数据进行种子处理,请运行命令

    导轨db:种子 提交更改。

    git add -A git commit -m“

    • 添加faker gem
    • 在seeds.rb文件中创建用于 在开发数据库中生成User,Category和Post记录的方法” 呈现帖子

      为了呈现帖子,我们需要posts在视图内部有一个目录。

      生成一个新的控制器Posts,所以它会自动posts在视图内创建一个目录。

      轨道g控制器职位 由于在我们的应用程序PagesController中负责主页,因此我们需要查询pages_controller.rb文件index操作中的数据。在index动作内部从posts表中检索一些记录。将检索到的记录分配给实例变量,以便检索到的对象在主页的视图内可用。

      如果您不熟悉ruby变量,请阅读本指南。 如果您不熟悉从Rails中的数据库检索记录,请阅读Active Record Query Interface指南。 现在的index行动应该看起来像这样:

    控制器/ pages_controller.rb 导航到主页的模板

    视图/页/ index.html.erb 并在 .main-content元素内添加

    %=呈现@posts% 这将呈现所有在index操作中检索到的帖子。由于post对象属于Post该类,因此Rails会自动尝试呈现所在的_post.html.erb部分模板

    意见/职位/ _post.html.erb 我们还没有创建这个部分文件,所以创建它并在里面添加下面的代码:

    意见/职位/ _post.html.erb 我在这里使用了一个引导卡组件来实现所需的风格。然后,我只是将内容及其路径存储在元素中。此外,我添加了一个链接,这将导致完整的职位。

    到目前为止,我们没有为帖子定义任何路线。我们现在需要他们,所以让我们宣布他们。打开routes.rb文件并在路由中添加以下代码:

    的routes.rb 在这里,我使用的资源的方法来申报路线index,show,new,edit,create,update和destroy行动。然后我宣布了一些自定义collection路由来访问具有多个Post实例的页面。这些页面将专门用于单独的分支,我们将在稍后创建它们。

    重新启动服务器并转到http:// localhost:3000。您应该在屏幕上看到呈现的帖子。应用程序应该看起来类似于:

    提交更改。

    git add -A git commit -m“在主页上显示帖子

    • 生成帖子控制器并创建索引操作。 在索引操作中检索Post记录

      • 为帖子声明路由
      • 在帖子目录中创建_post.html.erb部分内容
      • 在主页的主要内容中呈现帖子“ 要开始样式文章,请在partials目录中创建一个新的scss文件:

      资产/样式表/谐音/ posts.scss 并在文件中添加以下CSS:

    资产/样式表/谐音/ posts.scss 主页应该看起来类似于这个:

    提交更改。

    git add -A git commit -m“创建一个posts.scss文件并添加CSS” 使用JavaScript进行样式设计

    目前该网站的设计非常枯燥。为了创造对比,我们将着色这些帖子。但是,不要用CSS来着色,每当用户刷新网站时,我们都会用不同的颜色模式给它们着色。为此,我们将使用JavaScript。这可能是一个愚蠢的想法,但它很有趣c(o_u)?

    导航到javascripts您的目录assets并创建一个名为的新目录posts。在目录内创建一个名为的新文件style.js。另外如果你愿意,你可以删除默认生成 .coffee的javascripts目录中的文件。我们不会在本教程中使用CoffeeScript。

    资产/ Java脚本/职位/ style.js 在style.js文件中添加以下代码。

    资产/ Java脚本/职位/ style.js 使用这段代码,我们通过向帖子添加属性来在浏览器刷新时随机设置两种样式模式中的一种。一种风格只有彩色边框,另一种风格有纯色的帖子。随着每次页面更改和浏览器刷新,我们也会随机重新着色帖子。在randomColorSet()函数内部可以看到预定义的颜色方案。

    mouseenter并且mouseleave将来需要事件处理程序来处理特定页面中的帖子。在主页上有帖子的风格与帖子不同。当你将鼠标悬停在帖子上时,它会稍微改变底部边框的颜色。你会在稍后看到。

    提交更改。

    git add -A git commit -m“创建一个style.js文件并添加js来创建帖子的样式” 为了补充样式,添加一些CSS。打开posts.scss文件

    资产/样式表/谐音/ posts.scss 并添加以下CSS:

    资产/样式表/谐音/ posts.scss 在里面mobile.scss添加下面的代码来在较小的屏幕上修复太大的文本问题:

    资产/样式表/响应/ mobile.scss 主页现在看起来应该与此类似:

    提交更改

    git add -A git commit -m“将CSS添加到主页上的帖子

    • 将CSS添加到posts.scss文件中
    • 将CSS添加到mobile.scss以在较小的屏幕上修复太大的文本问题“ 模态窗口

      我希望能够点击帖子并查看其完整内容,而无需转到其他页面。为了实现这个功能,我将使用引导程序的模块组件。

      在posts目录中,创建一个新的部分文件_modal.html.erb

      意见/职位/ _modal.html.erb 并添加下面的代码:

    意见/职位/ _modal.html.erb 这只是稍微修改了引导程序的组件来完成此特定任务。

    在主页模板的顶部渲染这个部分。

    视图/页/ index.html.erb 为了使这个模式窗口起作用,我们必须添加一些JavaScript。在posts目录中,创建一个新文件modal.js

    资产/ Java脚本/职位/ modal.js 在文件内,添加以下代码:

    资产/ Java脚本/职位/ modal.js 有了这个js代码,我们只需将选定的帖子数据存储到变量中,然后用此数据填充模态窗口的元素。最后,通过最后一行代码,我们可以显示模态窗口。

    要增强模态窗口的外观,请添加一些CSS。但在添加CSS之前,让我们在stylesheets目录中执行一项快速管理任务。

    在partials目录内创建一个名为的新目录posts

    资产/样式表/谐音/职位 在posts目录内创建一个新文件home_page.scss。从posts.scss文件中剪下所有代码并将其粘贴到home_page.scss文件中。删除posts.scss文件。我们正在为此做出更好的CSS代码管理。更小的CSS文件具有明显的目的,而不是一个大文件,它将所有内容混合在一起。

    在posts目录中,创建一个新文件modal.scss并添加下面的CSS:

    资产/样式表/谐音/职位/ modal.scss 现在,当我们点击帖子时,应用程序应该如下所示:

    提交更改。

    git add -A git commit -m“添加一个弹出窗口来显示完整帖子的内容

    • 添加引导程序的模态组件以显示完整的帖子内容
    • 在主页的模板中渲染模态
    • 添加js以填充帖子内容的模态并显示它
    • 添加CSS以模拟模态“ 还将该main_feed分支与该分支合并master

      git checkout master git merge main_feed 摆脱main_feed分支

      git分支-D main_feed 单一职位 切换到新的分支

      git checkout -b single_post 显示一个帖子

      如果你尝试点击I'm interested按钮,你会得到一个错误。我们还没有创建show.html.erb模板,也没有创建相应的控制器操作。通过点击按钮,我想将其重定向到选定的帖子页面。

      在里面PostsController,创建一个show动作,然后在一个实例变量中查询和存储一个特定的post对象:

    控制器/ posts_controller.rb I'm interested按钮重定向到选定的帖子。它具有href通往帖子路径的属性。通过发送GET请求获取帖子,rails会调用该show操作。在show动作内部,我们可以访问id参数,因为通过发送GET获取特定帖子的请求,我们提供了它id。通过进入即/posts/1道路上,我们会发送一个请求得到一个职位,其id是1。

    show.html.erb在posts目录中创建一个模板

    意见/职位/ show.html.erb 在文件内添加以下代码:

    意见/职位/ show.html.erb show.scss在posts目录中创建一个文件并添加CSS来设置页面的外观:

    资产/样式表/谐音/职位/ show.scss 在这里我定义了页面的高度100vh-50px,因此页面的内容是完整的视口高度。它允许在整个浏览器的高度将容器着色为白色,而不管元素内是否有足够的内容。vh属性意味着视口的高度,所以100vh值意味着该元素拉伸视口高度的100%。100vh-50px需要减去导航栏的高度,否则容器会被拉得太大50px。

    如果你I'm interested现在点击按钮,你将被重定向到一个类似这样的页面:

    稍后我们会在show.html.erb模板中添加额外的功能。现在提交更改。

    git add -A git commit -m“为帖子创建展示模板

    • 添加一个显示操作并将一个帖子查询到一个实例变量
    • 创建一个show.scss文件并添加CSS“ 眼镜

      而不是手动检查模式窗口外观和重定向到选定帖子的这个功能的工作原理,而是用规范包装它。我们将使用水豚模拟用户与应用程序的交互。

      在features目录中,创建一个名为的新目录posts

      规格/功能/职位 在新目录中,创建一个新文件 visit_single_post_spec.rb

      规格/特征/职位/ visit_single_post_spec.rb 并在里面添加一个功能规格。该文件如下所示:

    规格/特征/职位/ visit_single_post_spec.rb 在这里我定义了手动执行的所有步骤。我首先进入主页,点击帖子,期望看到弹出的模式窗口,点击I'm interested按钮,最后,期望被重定向到帖子的页面并查看其内容。

    默认情况下have_selector,have_css如果某个元素对用户可见,则RSpec匹配器等将返回true。所以在点击帖子后,测试框架希望看到一个可见的模式窗口。如果您不关心用户是否看到某个元素,并且只关心DOM中的某个元素,请传递一个额外的visible: false参数。

    尝试运行测试

    rspec spec / features / posts / visit_single_post_spec.rb 提交更改。

    git add -A git commit -m“添加功能规格以测试用户是否可以 从主页转到单个帖子” 将single_post分支合并到master。

    git checkout master git merge single_post git branch -D single_post 具体分支 每篇文章都属于一个特定的分支。让我们为不同的分支创建特定的页面。

    切换到新的分支

    git checkout -b specific_branches 主页的侧面菜单

    首先更新主页的侧边菜单。添加链接到特定分支。打开index.html.erb文件:

    视图/页/ index.html.erb 我们将在#side-menu元素内部添加一些链接。将文件内容拆分为部分内容,否则会很快产生噪音。 剪切#side-menu和#main-content元素,并将它们粘贴到单独的部分文件中。在该pages目录内创建一个index目录,并在该目录内为该元素创建相应的部分文件。这些文件应该如下所示:

    视图/页/索引/ _side_menu.html.erb

    视图/页/索引/ _main_content.html.erb 渲染主页模板中的部分文件。该文件应该看起来像这样:

    视图/页/ index.html.erb 提交更改。

    git add -A git commit -m“将主页模板的内容分割成部分” 在_side_menu.html.erb部分内部添加一个链接列表,所以文件应该看起来像这样:

    视图/页/索引/ _side_menu.html.erb 一个无序的列表被添加。在列表中,我们渲染另一个带有链接的部分。这些链接将适用于所有用户,无论他们是否登录。创建这个部分文件并添加链接。

    在index目录内创建一个side_menu目录:

    视图/页/索引/ side_menu 在目录内_no_login_required_links.html.erb使用以下代码创建一个部分:

    视图/页/索引/ side_menu / _no_login_required_links.html.erb 在这里,我们只是添加链接到特定分支的职位。如果您想知道我们如何获得路径,例如hobby_posts_path等等,请查看该routes.rb文件。以前我们collection在resources :posts声明中添加了嵌套路由。

    如果你注意i元素的属性,你会注意到fa类。通过这些类我们宣布Font Awesome图标。我们还没有设立这个图书馆。幸运的是,这很容易设置。在主application.html.erb文件的head元素内,添加以下行

    侧面菜单应该现在出席。

    提交更改。

    git add -A git commit -m“添加链接到主页的侧面菜单” 在较小的屏幕,其中宽度之间767px和1000px,引导的集装箱看起来不愉快的,它看起来过分压缩。所以在这些宽度之间拉伸。在mobile.scss文件内,添加以下代码:

    资产/样式表/响应/ mobile.scss 提交更改。

    git add -A git commit -m“ 当视口宽度在767px和1000px之间时,将.container宽度设置为100%” 分支页面 如果您尝试点击其中一个侧面菜单链接,您会收到错误消息。我们还没有设置行动,PostsController也没有为它创建任何模板。

    里面的PostsController,定义hobby,study和team行动。

    控制器/ posts_controller.rb 在每个动作中,posts_for_branch都会调用方法。此方法将根据操作的名称返回特定页面的数据。定义private范围内的方法。

    contorllers / posts_controller.rb 在@categories实例变量中,我们检索特定分支的所有类别。也就是说,如果您进入爱好分支页面,则将检索属于爱好分支的所有分类。

    要获取和存储@posts实例变量中的文章,使用get_posts方法,然后用paginate方法链接。paginate方法来自will_paginate gem。我们先来定义get_posts方法。里面PostsController的private范围增加:

    控制器/ posts_controller.rb 现在,get_posts方法只是检索任何30个帖子,而不是任何具体的东西,所以我们可以继续前进,并专注于进一步的发展。我们会在不久的将来回到这个方法。

    添加will_paginate宝石可以使用分页。

    宝石'will_paginate','〜> 3.1.0' 跑

    捆绑安装 我们现在想念的只是模板。它们将与所有分支相似,因此不必重复代码,而是在每个分支内部为分支创建一个具有通用结构的部分。在posts目录内创建一个_branch.html.erb文件。

    文章/ _branch.html.erb 首先你会看到一个page_title变量被打印在页面上。当我们渲染_branch.html.erb部分时,我们会将这个变量作为参数传递。接下来,_create_new_post呈现一个部分显示一个链接,这将导致一个页面,用户可以创建一个新的帖子。在新branch目录中创建这个部分文件:

    文章/分公司/ _create_new_post.html.erb 这里我们将使用一个create_new_post_partial_path辅助方法来确定要渲染的部分文件。在posts_helper.rb文件内部,实现该方法:

    助手/ posts_helper.rb 还要在一个新create_new_post目录中创建这两个对应的部分:

    文章/分公司/ create_new_post / _signed_in.html.erb

    文章/分公司/ create_new_post / _not_signed_in.html.erb 接下来,在_branch.html.erb文件内部,我们呈现一个类别列表。创建一个_categories.html.erb部分文件:

    文章/分公司/ _categories.html.erb 在文件内部,我们有一个all_categories_button_partial_path辅助方法来确定要渲染的部分文件。在posts_helper.rb文件中定义这个方法:

    助手/ posts_helper.rb 所有类别都将被默认选中。如果params[:category]为空,则表示用户未选择任何类别,这意味着当前all选择了默认值。创建相应的部分文件:

    文章/分公司/分类/ _all_selected.html.erb

    文章/分公司/分类/ _all_not_selected.html.erb 该发送方法,用在这里使用字符串来调用一个方法,这样就可以灵活,动态调用方法。在我们的例子中,我们根据当前控制器的动作生成不同的路径。

    接下来,在_branch.html.erb文件内部,我们呈现帖子并调用no_posts_partial_path助手方法。如果找不到帖子,该方法将显示一条消息。

    在posts_helper.rb添加辅助方法的内部:

    助手/ posts_helper.rb 这里我使用三元运算符,所以代码看起来更清晰一些。如果有任何帖子,我不想显示任何消息。由于您无法将空字符串传递给该render方法,因此在我不想呈现任何内容的情况下,我会将路径传递给空白部分。

    shared在视图内创建一个目录,然后创建一个空的部分:

    视图/共享/ _empty_partial.html.erb 现在_no_posts.html.erb在branch目录中为消息创建一个部分。

    文章/分公司/ _no_posts.html.erb 最后,will_paginate如果有很多帖子,我们使用gem中的方法将帖子拆分成多个页面。

    创建模板hobby,study和team行动。在他们内部,我们将渲染_branch.html.erb部分文件并传递特定的局部变量。

    文章/ hobby.html.erb

    文章/ study.html.erb

    文章/ team.html.erb 如果你去任何一个分支页面,你会看到类似的东西

    另外如果你向下滚动,你会看到现在我们有一个分页

    我们已经完成了很多工作来创建这些分支页面。提交更改

    git add -A git commit -m“为特定帖子创建分支页面

    • 在PostsController中定义爱好,学习和团队行为。 定义posts_for_branch方法并在这些操作中调用它

      • 添加will_paginate gem
      • 创建_branch.html.erb部分文件
      • 创建_create_new_post.html.erb部分文件
      • 定义create_new_post_partial_path帮助器方法
      • 创建_signed_in.html.erb部分文件
      • 创建_not_signed_in.html.erb部分文件
      • 创建_categories.html.erb部分文件
      • 定义all_categories_button_partial_path帮助器方法
      • 创建_all_selected.html.erb部分文件
      • 创建_all_not_selected.html.erb部分文件
      • 定义no_posts_partial_path帮助器方法
      • 创建一个_no_posts.html.erb部分文件
      • 创建一个hobby.html.erb模板文件
      • 创建一个study.html.erb模板文件
      • 创建一个team.html.erb模板文件“ 眼镜

      使用规格覆盖帮助程序方法。该posts_helper_spec.rb文件应该看起来像这样:

    规格/助理/ posts_helper_spec.rb 同样,这里的规格非常简单。我用这个stub方法来定义方法的返回值。为了定义参数,我选择了控制器并简单地将它定义为这样controller.params[:param_name]。最后,我使用assign方法分配实例变量。

    提交更改

    git add -A git commit -m“为PostsHelper方法添加规格” 设计更改 在这些分支页面中,我们希望有不同的帖子设计。在主页上我们有卡片设计。在分支页面中,我们创建一个列表设计,这样用户可以看到更多的帖子并更有效地浏览它们。

    在posts目录中,创建post一个_home_page.html.erb部分内部的目录。

    岗位/职位/ _home_page.html.erb 剪下_post.html.erb部分内容并将其粘贴到_home_page.html.erb部分文件中。在_post.html.erb部分文件中添加以下代码行:

    文章/ _post.html.erb 在这里,我们调用post_format_partial_path辅助方法来决定渲染哪个后期设计,具体取决于当前路径。如果用户在主页上,则呈现主页的帖子设计。如果用户在分支页面上,则为分支页面渲染帖子设计。这就是为什么我们将_post.html.erb文件内容剪切成_home_page.html.erb文件的原因。

    在post目录中,创建一个新_branch_page.html.erb文件并粘贴此代码以定义分支页面的帖子设计。

    岗位/职位/ _branch_page.html.erb 要决定渲染哪个部分文件,请定义post_format_partial_path内部的helper方法posts_helper.rb

    助手/ posts_helper.rb 该post_format_partial_path辅助方法在主页中不可用,因为我们在属于不同控制器的主页模板内呈现帖子。有此方法的访问,主页的模板中,包括PostsHelper里面的ApplicationHelper

    包括PostsHelper 眼镜

    为post_format_partial_path辅助方法添加规格:

    助手/ posts_helper_spec.rb 提交更改

    git add -A git commit -m“为post_format_partial_path帮助器方法添加规格” CSS

    使用CSS描述分支页面中的帖子风格。在posts目录中,创建一个新的branch_page.scss样式表文件:

    样式表/谐音/职位/ branch_page.scss 里面的base/default.scss添加:

    资产/样式表/碱/ default.scss 要在更小的设备上解决样式问题,请在responsive/mobile.scssadd中添加:

    资产/样式表/响应/ mobile.scss 现在分支页面应该看起来像这样:

    提交更改。

    git add -A git commit -m“描述分支页面中的帖子风格

    • 创建一个branch_page.scss文件并添加CSS
    • 将CSS 添加到default.scss文件
    • 将CSS添加到mobile.scss文件“ 搜索栏 我们不仅要浏览帖子,还要搜索特定的帖子。在_branch.html.erb部分文件的上方categories,添加:

    文章/ _branch.html.erb _search_form.html.erb在branch目录中创建一个部分文件并在里面添加下面的代码:

    文章/分公司/ _search_form.html.erb 在此send方法中,我们PostsController根据当前分支动态生成特定行为的路径。如果选择了特定类别,我们还会为该类别发送额外的数据字段。如果用户选择了特定类别,则只会返回该类别的搜索结果。

    定义category_field_partial_path内部的助手方法posts_helper.rb

    助手/ posts_helper.rb 创建一个_category_field.html.erb部分文件并添加代码:

    文章/分公司/ search_form / _category_field.html.erb 为了给搜索表单一些样式,将CSS添加到branch_page.scss文件中:

    资产/样式表/谐音/职位/ branch_page.scss 分支页面中的搜索表单应该看起来像现在这样

    提交更改

    git add -A git commit -m“在分支页面添加搜索表单

    • 在_branch.html.erb中呈现搜索表单
    • 创建_search_form.html.erb部分文件
    • 在PostsHelper中定义category_field_partial_path帮助器方法
    • 创建_category_field.html.erb部分文件
    • 在branch_page.scss中为搜索表单添加CSS“ 目前我们的表格并非真正的功能。我们可以使用一些宝石来实现搜索功能,但我们的数据并不复杂,所以我们可以创建我们自己的简单搜索引擎。我们将在模型中使用范围Post来实现查询可链接和控制器内的一些条件逻辑(我们将在下一节中将其提取到服务对象中,以使代码更清晰)。

      首先在Post模型中定义范围。要预热,请定义文件default_scope内部post.rb。这个按创建日期降序排列帖子,最新的帖子在顶部。

    车型/ post.rb 提交更改

    git add -A git commit -m“为帖子定义default_scope” default_scope通过用规范包装来确保工作正确。在post_spec.rb文件中,添加:

    规格/型号/ post_spec.rb 提交更改:

    git add -A git commit -m“为Post模型的default_scope添加规范” 现在让我们使搜索栏功能。在内部posts_controller.rb用以下get_posts方法替换方法的内容:

    控制器/ posts_controller.rb 正如我刚才提到的那样,逻辑就像在视图中一样,在控制器中并不是一个好地方。我们想让他们干净。所以我们将在下一节中提取出这种方法的逻辑。

    如你所见,有一些条件逻辑正在进行。根据用户请求,使用范围以不同方式查询数据。

    在Post模型内部,定义这些范围:

    车型/ post.rb 该joins方法用于查询关联表中的记录。基本SQL语法也用于根据提供的字符串查找记录。

    现在,如果您重新启动服务器并返回任何分支页面,则搜索栏应该可以正常工作!此外,您现在可以通过点击类别按钮来过滤帖子。此外,当您选择特定类别时,只有使用搜索表单时才会查询该类别的帖子。

    提交更改

    git add -A git commit -m“使 分支页面中的搜索栏和类别过滤器正常工作

    • 在Post模型中添加by_category,by_branch和搜索范围
    • 修改PostsController中的get_posts方法“ 根据规格覆盖这些示波器。在post_spec.rb文件的Scopes上下文中添加:

    规格/型号/ post_spec.rb 提交更改

    git add -A git commit -m“为Post模型的 by_branch,by_category和搜索范围添加规范” 无限滚动 当你转到任何这些分支页面时,在页面的底部你会看到分页

    当你点击下一个链接时,它会将你重定向到另一个包含旧帖子的页面。我们可以制作一个无限的滚动功能,而不是重定向到另一个带有较旧帖子的页面,类似于Facebook和Twitter的Feed。您只需向下滚动并且不进行任何重定向和页面重新加载,旧的帖子将追加到列表的底部。令人惊讶的是,这很容易实现。我们所要做的就是编写一些JavaScript。无论用户何时到达页面底部,都会发送AJAX请求以从next页面获取数据,并将数据附加到列表底部。

    首先配置AJAX请求及其条件。当用户通过向下滚动传递某个阈值时,AJAX请求被触发。在javascripts/posts目录中,创建一个新infinite_scroll.js文件并添加代码:

    资产/ Java脚本/职位/ infinite_scroll.js 该isLoading变量确保一次只发送一个请求。如果当前有一个请求正在进行,其他请求将不会启动。

    首先检查是否存在分页,如果有更多的帖子要呈现。接下来,获取到下一页的链接,这是将从中检索数据的位置。然后设置何时调用AJAX请求的阈值,在这种情况下,阈值60px来自窗口底部。最后,如果所有条件都成功通过,则next使用该getScript()函数从页面加载数据。

    因为该getScript()函数加载JavaScript文件,所以我们必须指定要在其中呈现哪个文件PostsController。在该posts_for_branch方法内指定respond_to格式和要呈现的文件。

    控制器/ posts_controller.rb 当控制器试图回应该 .js文件时,该posts_pagination_page模板会被渲染。此部分文件将新检索的帖子附加到列表中。创建此文件以附加新帖子并更新分页元素。

    文章/ _posts_pagination_page.js.erb 在中创建一个update_pagination_partial_path辅助方法posts_helper.rb

    助手/ posts_helper.rb 这里使用gem中的next_page方法will_paginate来确定是否有更多的帖子可以在将来加载。

    创建相应的部分文件:

    文章/ posts_pagination_page / _update_pagination.js.erb

    文章/ posts_pagination_page / _remove_pagination.js.erb 如果您转到任何分支页面并向下滚动,旧帖子应自动添加到列表中。

    我们也不再需要看到分页菜单,所以用CSS隐藏它。在branch_page.scss文件里添加:

    样式表/谐音/职位/ branch_page.scss 提交更改

    git add -A git commit -m“将帖子分页转换为无限滚动

    • 创建一个infinite_scroll.js文件
    • 在PostController的posts_for_branch方法中添加respond_to格式
    • 定义一个update_pagination_partial_path
    • Create _update_pagination.js.erb and _remove_pagination.js.erb partials
    • hide the .infinite-scroll element with CSS" 眼镜

      update_pagination_partial_path使用规格覆盖辅助方法:

    规格/助理/ post_helper_spec.rb 在这里我使用了一个测试double来模拟posts实例变量及其链式方法next_page。你可以在这里了解更多关于RSpec Mocks的信息。

    提交更改:

    git add -A git commit -m“为update_pagination_partial_path 帮助器方法添加规范” 在向下滚动后,我们还可以编写功能规格以确保帖子成功追加。创建一个infinite_scroll_spec.rb文件:

    规格/特征/职位/ infinite_scroll_spec.rb 在spec文件中覆盖了所有分支页面。我们确保此功能在所有三个页面上都能正常工作。这per_page是will_paginate宝石的方法。此处Post选择模型并设置每页的默认文章数量。

    该check_posts_count方法被定义为减少文件的代码量。我们不是一次又一次地在不同的规格中重复使用相同的代码,而是将其提取到一个单一的方法中。一旦访问该页面,预计会看到15个帖子。然后,该execute_script方法用于运行JavaScript,它将滚动条滚动到浏览器的底部。最后,在滚动之后,预计会看到另外15个帖子。现在总共应该有30个帖子在页面上。

    提交更改:

    git add -A git commit -m“为帖子'无限滚动功能添加功能规格” 主页更新

    目前在主页上我们只能看到几个随机帖子。修改主页,以便我们可以看到所有分支机构的一些帖子。

    将_main_content.html.erb文件的内容替换为:

    页/索引/ _main_content.html.erb 我们为每个分支创建了帖子部分。

    定义中的实例变量PagesController的index作用。行动应该看起来像这样:

    控制器/ pages_controller.rb 我们有no_posts_partial_path从前的辅助方法,但我们应该稍微修改它,并使其更加可重用。目前它仅适用于分支页面。posts为该方法添加一个参数,所以它现在应该看起来像这样:

    助手/ posts_helper.rb 这里posts添加了参数,实例变量被改为一个简单的变量,并且部分的路径也被改变了。所以_no_posts.html.erb从中移动部分文件

    文章/分公司/ _no_posts.html.erb 至

    文章/共享/ _no_posts.html.erb 在_branch.html.erb文件内部也将@posts实例变量no_posts_partial_path作为参数传递给方法。

    添加一些样式更改。在default.scss文件里添加:

    资产/样式表/碱/ default.scss 并在里面home_page.scss添加:

    资产/样式表/谐音/ home_page.scss 主页现在应该看起来与此类似

    提交更改

    git add -A git commit -m“在主页中添加来自所有分支的帖子 -修改定义中的实例变量的作用-修改_main_content.html.erb file

    • PagesControllerindex no_posts_partial_path helper method to be more reusable
    • Add CSS to style the home page" 服务对象 正如我之前提到的,如果你把逻辑放在控制器中,它们会变得非常容易变得复杂并且很难测试。这就是为什么从其他地方提取逻辑的好主意。为此,我使用设计模式,服务对象(服务)更具体。

      现在在里面PostsController,我们有这个方法:

    控制器/ posts_controller.rb 它有很多我想通过使用服务删除的条件逻辑。服务对象(服务)设计模式只是一个基本的ruby类。这非常简单,我们只是传递我们想要处理的数据并调用一个定义的方法来获得所需的返回值。

    在ruby中,我们将数据传递给Class的initialize方法,在其他语言中称为constructor。然后在类内部,我们创建一个处理所有已定义逻辑的方法。让我们来创建它,看看它在代码中的外观。

    在app目录中,创建一个新services目录:

    应用程序/服务 在目录中,创建一个新posts_for_branch_service.rb文件:

    服务/ posts_for_branch_service.rb 在这里,如上所述,它只是一个普通的ruby类,带有一个initialize接受参数的call方法和一个处理逻辑的方法。我们从这个get_posts方法中拿出了这个逻辑。

    现在只需创建此类的新对象并调用call方法内的get_posts方法。该方法现在应该看起来像这样:

    控制器/ posts_controller.rb 提交更改:

    git add -A git commit -m“创建一个服务对象以 从get_posts方法中提取逻辑” 眼镜

    有关设计模式(比如服务)的幸运之处在于为它编写单元测试很容易。我们可以简单地为该call方法编写规格并测试其每个条件。

    在spec目录内创建一个新的services目录:

    投机/服务 在目录内创建一个新文件 posts_for_branch_service_spec.rb

    投机/服务/ posts_for_branch_service_spec.rb 在文件顶部,posts_for_branch_service.rb加载文件,然后测试每个call方法的条件。

    提交更改

    git add -A git commit -m“为PostsForBranchService添加规格” 创建一个新帖子 到现在为止,帖子是通过使用种子人为创建的。让我们为它添加一个用户界面,以便用户可以创建帖子。

    在posts_controller.rb文件内添加new和create操作。

    控制器/ posts_controller.rb 在new动作内部,我们为表单定义了一些实例变量来创建新帖子。在@categories实例变量内部,存储特定分支的类别。该@post实例变量存储一个新的职位的目的,这需要用于滑轨形式。

    在create动作的@post实例变量中,我们创建一个新Post对象并使用该post_params方法填充数据。在private范围内定义此方法:

    控制器/ posts_controller.rb 该permit方法用于将对象的属性列入白名单,因此只允许传递这些指定的属性。

    在顶部PostsController添加以下行:

    控制器/ posts_controller.rb 这before_action是Rails 过滤器之一。我们不希望允许未登录的用户访问他们可以创建新帖子的页面。所以在调用该new动作之前,该redirect_if_not_signed_in方法被调用。我们也需要在其他控制器上使用这种方法,所以在application_controller.rb文件中定义它。另外一种重定向登录用户的方法在未来也会有用。所以定义它们两个。

    控制器/ application_controller.rb 现在该new模板是必需的,因此用户可以创建新帖子。在posts目录中,创建一个new.html.erb文件:

    文章/ new.html.erb 在里面创建一个new目录和一个_post_form.html.erb部分文件:

    文章/新/ _post_form.html.erb 表单非常简单。字段的属性被定义,并且该collection_select方法被用来允许选择一个可用的类别。

    提交更改

    git add -A git commit -m“创建一个UI来创建新帖子

    • 在PostsController中: 定义新的和创建的动作 定义一个 post_params 方法定义一个before_action过滤器
    • 在ApplicationController中: 定义一个redirect_if_not_signed_in方法 定义一个redirect_if_signed_in方法
    • 为帖子创建一个新模板“ 我们可以通过编写规范来测试表单是否工作。首先编写请求规范,确保在发送特定请求后我们得到正确的响应。在spec目录内部创建一对目录。

      规格/请求/职位 new_spec.rb里面有一个文件:

    规格/请求/职位/ new_spec.rb 正如文档中提到的那样,请求规范提供了一个关于集成测试的简单包装。所以我们测试当我们发送某些请求时是否得到正确的回应。该include Warden::Test::Helpers行是必需的,以便使用login_as方法。该方法记录用户。

    提交更改。

    git add -A git commit -m“为新的发布模板添加请求规范” 我们甚至可以为我们之前创建的页面添加更多的请求规格。

    在同一目录内创建一个branches_spec.rb文件:

    规格/请求/职位/ branches_spec.rb 这样我们检查所有分支页面的模板是否成功呈现。也shared_examples用于减少重复代码。

    提交更改。

    git add -A git commit -m“添加帖子分支页面模板的请求规格” 我们也可以确保show模板成功呈现。在同一目录内创建一个show_spec.rb文件:

    规格/请求/职位/ show_spec.rb 提交更改。

    git add -A git commit -m“添加Posts展示模板的请求规格” 要确保用户能够创建新帖子,请编写功能规格以测试该表单。在features/posts目录内创建一个新文件create_new_post_spec.rb

    规格/特征/职位/ create_new_post_spec.rb 提交更改。

    git add -A git commit -m“创建一个带有功能规格的create_new_post_spec.rb文件” 将一些设计应用于new模板。

    在以下目录中:

    assets/stylesheets/partials/posts 创建一个new.scss文件:

    资产/样式表/谐音/职位/ new.scss 如果您现在在浏览器中转到模板,您应该看到一个基本表单

    提交更改

    git add -A git commit -m“将CSS添加到Posts new.html.erb模板” 最后,我们要确保所有字段都填写正确。在Post模型内部,我们将定义一些验证。将以下代码添加到Post模型中:

    车型/ post.rb 提交更改。

    git add -A git commit -m“将验证添加到Post模型” 按照规格覆盖这些验证。转到Post模型的规格文件:

    规格/型号/ post_spec.rb 然后加:

    规格/型号/ post_spec.rb 提交更改。

    git add -A git commit -m“为Post模型的验证添加规格” 将specific_branches分支合并到master

    git checkout -b master git merge specific_branches git branch -D specific_branches 即时通讯 用户可以发布帖子并阅读其他用户的帖子,但他们无法相互沟通。我们可以创建一个简单的邮箱系统,这将更容易,更快地开发。但这是与某人沟通的一种非常古老的方式。实时通信开发更加令人兴奋,使用起来更加舒适。

    幸运的是,Rails有Action Wires,使实时特性的实现相对简单。Action Cables的核心概念是它使用WebSockets协议而不是HTTP。WebSockets的核心概念是建立客户端 - 服务器连接并保持打开。这意味着不需要重新加载页面来发送和接收额外的数据。

    私人谈话 本节的目标是创建一个可以在两个用户之间进行私人对话的工作特性。

    切换到新的分支

    git结帐-B private_conversation 命名空间模型

    从定义必要的模型开始。现在我们需要两种不同的模型,一种用于私人对话,另一种用于私人消息。我们可以为它们命名PrivateConversation和PrivateMessage,但你可以很快遇到了一点问题。虽然一切都可以正常工作,但想象一下,models在我们创建了更多具有相似名称前缀的模型后,该目录将如何开始显示。该目录很快就变得难以管理。

    为了避免目录中出现混乱的结构,我们可以使用命名空间技术。

    让我们看看它会是什么样子。一个普通的私人对话模型将被调用PrivateConversation,它的文件将被调用private_conversation.rb,并存储在models目录中

    车型/ private_conversation.rb 同时,命名空间版本将被调用Private::Conversation。该文件将被调用conversation.rb并位于该private目录内

    车型/私营/ conversation.rb 你能看到它可能有用吗?所有带有private前缀的文件都将存储在private目录中,而不是在主models目录内部进行累积,使其难以阅读。

    通常,Rails使开发过程愉快。我们可以通过指定一个我们想要放置模型的目录来创建命名空间模型。

    要创建名称空间Private::Conversation模型,请运行以下命令:

    导轨克模型私人/谈话 还生成Private::Message模型:

    导轨克模型私人/消息 如果你看看models目录,你会看到一个private.rb文件。这是为数据库表名称添加前缀所需的,因此可以识别模型。就我个人而言,我不喜欢将这些文件保存在models目录中,我更愿意在模型本身内指定表名。要在模型中指定表名,必须使用self.table_name =并提供表名作为字符串。如果您选择像这样指定数据库表的名称,那么模型应该如下所示:

    车型/私营/ conversation.rb

    车型/私营/ message.rb 目录中的private.rb文件models不再需要,您可以将其删除。

    用户将能够进行许多私人对话并且对话将具有许多消息。在模型中定义这些关联:

    车型/私营/ conversation.rb

    车型/私营/ message.rb

    车型/ user.rb 这里该class_name方法用于定义关联模型的名称。这允许为我们的关联使用自定义名称,并确保命名空间模型得到识别。该class_name方法的另一个用例是创建一个与自身的关系,当你想通过创建某种层次结构或类似结构来区分同一模型的数据时,这很有用。

    将foreign_key用于在数据库表中,指定关联的列的名称。表中的数据列仅在belongs_to关联的一侧创建,但要使列可识别,我们必须foreign_key在两个模型上定义相同的值。

    私人对话将在两个用户之间进行,这两个用户是sender和recipient。我们可以将它们命名为user1和user2。但是知道是谁发起了一个对话很方便,所以sender这里是对话的创建者。

    在迁移文件中定义数据表:

    分贝/迁移/ CREATION_DATE_create_private_conversations.rb 该private_conversations表格将存储用户的ID,这是工作所需要的,belongs_to并且has_many协会可以工作,当然还可以在两个用户之间创建对话。

    分贝/迁移/ CREATION_DATE_create_private_messages.rb 在body数据列中,消息的内容将被存储。除了添加索引和id列以使两个模型之间的关联起作用外,我们在这里使用了references简化实现的方法。

    运行迁移文件以在开发数据库中创建表

    rails db:migrate 提交更改

    git add -A git commit -m“创建Private :: Conversation和Private :: Message模型

    • 定义User,Private :: Conversation 和Private :: Message模型之间的关联
    • 定义private_conversations和private_messages表“ 非实时私人对话窗口

      我们有一个地方可以存储私人对话的数据,但这是非常重要的。我们应该从哪里开始?正如前面部分提到的,我个人喜欢创建一个功能的基本视觉方面,然后编写一些逻辑来使其功能。我喜欢这种方法,因为当我有一个视觉元素时,我想要实现功能,这更明显是我想要实现的。拥有用户界面后,将问题分解为更小的步骤会更容易,因为您知道发生特定事件后会发生什么情况。编写一些尚不存在的东西很难。

      要开始构建私人对话的用户界面,请创建一个Private::Conversations控制器。一旦我在应用程序中命名空间,我想保持一致并命名空间所有其他相关的部分。这允许更直观地理解和浏览源代码。

      导轨g控制器私人/对话 Rails发生器非常甜美。它创建了一个命名空间模型和名称空间视图,一切都准备好了开发。

      创建一个新的对话

      我们需要一种启动新对话的方式。在我们的应用程序中,有意义的是,您想联系与您有相似兴趣的人。这个功能的便利之处在于单个帖子的页面。

      在posts/show.html.erb模板内部,创建一个表单以启动新对话。在该

      <%= @post.content="" %="">

      行下面添加:

    文章/ show.html.erb 定义内部的助手方法 posts_helper.rb

    助手/ posts_helper.rb 为辅助方法添加规格:

    规格/助理/ posts_helper_spec.rb 创建一个show目录和相应的部分文件:

    文章/显示/ _contact_user.html.erb

    文章/显示/ _login_required.html.erb 定义leave_message_partial_path内部的助手方法posts_helper.rb

    助手/ posts_helper.rb 为该方法添加规格

    规格/助理/ posts_helper_spec.rb 我们将在一段时间@message_has_been_sent内定义实例变量PostsController,它将确定是否已发送给用户的初始消息。

    leave_message_partial_path在新contact_user目录中创建对应于辅助方法的部分文件

    文章/显示/ contact_user / _already_in_touch.html.erb

    文章/显示/ contact_user / _message_form.html.erb 现在配置PostsController的show作用。在动作内添加

    控制器/ posts_controller.rb 在控制器的private范围内,定义conversation_exist?方法

    控制器/ posts_controller.rb 该between_users方法查询两个用户之间的私人对话。将其定义为Private::Conversation模型内的范围

    车型/私营/ conversation.rb 我们必须测试范围是否有效。在编写规范之前,先定义一个private_conversation工厂,因为我们需要测试数据库中的样本数据。

    规格/工厂/ private_conversations.rb 我们在这里看到一个嵌套的工厂,它允许用父级的配置创建一个工厂,然后对其进行修改。另外,因为我们会在private_conversation_with_messages工厂创建消息,所以我们也需要定义private_message工厂

    规格/工厂/ private_messages.rb 现在我们已经准备好测试between_users范围了。

    规格/型号/私营/ conversation_spec.rb 定义create为动作Private::Conversations控制器

    控制器/私营/ conversation_controller.rb 在这里,我们创建一个帖子的作者和当前用户之间的对话。如果一切顺利,应用程序将创建一条消息,由当前用户编写,并通过渲染相应的JavaScript部分来提供反馈。

    创建这些部分

    文章/显示/ contact_user / message_form / _success

    文章/显示/ contact_user / message_form / _fail 为Private::Conversations和Private::Messages控制器创建路由

    的routes.rb 现在我们只需要很少的操作,这就是only方法的用处。该namespace方法允许为名称空间控制器轻松创建路由。

    .contact-user使用功能规格测试整个 表单的性能

    规格/特征/职位/ contact_user_spec.rb 提交更改

    git add -A git commit -m“在帖子内添加一个表单来联系用户

    • 在PostsHelper中定义一个contact_user_partial_path帮助器方法。 为该方法添加规范
      • 创建_contact_user.html.erb和_login_required.html.erb部分
      • 在PostsHelper中定义leave_message_partial_path帮助程序方法。 为方法添加规范
      • 创建_already_in_touch.html.erb和_message_form.html.erb 部分文件
      • 在PostsController的show action中定义@message_has_been_sent
      • 在Private :: Conversation模型中定义between_users 作用域 为作用域添加规范
      • 定义private_conversation和private_message工厂
      • 定义Private :: Conversations和Private :: Messages的路由 - 在Private :: Conversations中 定义一个创建动作
      • 创建_success.js和_fail.js部分
      • 添加功能规格以测试整个.contact用户表单“ 将CSS添加到branch_page.scss文件中,稍微改变窗体的样式

    样式表/谐音/职位/ branch_page.scss 当您访问单个帖子时,表单应该看起来像这样

    当您向帖子的作者发送消息时,表单将消失

    这就是您在与用户保持联系时的样子

    提交更改

    git add -A git commit -m“添加CSS以设置.contact-user表单的样式” 呈现对话窗口

    我们发送了一条消息并创建了一个新对话。这是我们现在唯一的权力,我们不能做任何事情。到目前为止,这是多么无用的力量。我们需要一个对话窗口来读取和写入消息。

    在会话中存储已打开的对话ID。这允许保持应用程序中打开的对话,直到用户关闭它们或破坏会话。

    里面Private::ConversationsController的create动作调用一个add_to_conversations unless already_added?方法,如果对话被成功保存。然后在private范围内定义方法

    控制器/私营/ conversations_controller.rb 这会将对话的ID存储在会话中。而already_added?私有方法是要确保通话的ID不是会话中尚未加入。

    控制器/私营/ conversations_controller.rb 最后,我们需要访问视图内的对话,因此将该conversation变量转换为实例变量。

    现在我们可以开始为对话窗口创建一个模板。为该窗口创建一个部分文件

    民营/会话/ _conversation.html.erb 在这里,我们使用该private_conv_recipient方法获得对话的收件人。定义内部的助手方法Private::ConversationsHelper

    佣工/私营/ conversations_helper.rb 该opposed_user方法被使用。转到Private::Conversation模型并定义方法

    车型/私营/ conversation.rb 这将返回一个私人对话的反对用户。通过覆盖规格确保该方法正常工作

    规格/型号/私营/ conversation_spec.rb 接下来,为_conversation.html.erb文件创建丢失的部分文件

    民营/会话/会话/ _heading.html.erb

    民营/会话/会话/ _messages_list.html.erb 在里面Private::ConversationsHelper,定义load_private_messages辅助方法

    佣工/私营/ conversations_helper.rb 这将添加一个链接来加载以前的消息。在新messages_list目录中创建相应的部分文件

    民营/会话/会话/ messages_list / _link_to_previous_messages.html.erb 不要忘记确保一切都很好,并为其编写规范

    规格/助理/私营/ conversations_helper_spec.rb 因为会话的窗口将在整个应用中呈现,这意味着我们需要访问Private::ConversationsHelper辅助方法。在整个应用程序中ApplicationHelper添加所有这些方法的访问权限

    包括私人:: ConversationsHelper 然后为会话的新消息表单创建最后缺失的部分文件

    民营/会话/会话/ _new_message_form.html.erb 我们稍后会让这个表单起作用。

    现在让我们创建一个功能,在用户通过单个帖子发送消息后,会话窗口在应用程序上呈现。

    在_success.js.erb文件里面

    文章/显示/ contact_user / message_form / _success.js.erb 加

    <%=呈现'私人/对话/打开'%> 这部分文件的目的是向应用程序添加对话窗口。定义部分文件

    民营/会话/ _open.js.erb 这个回调部分文件将在多个场景中重用。为了避免多次渲染相同的窗口,在渲染窗口之前,我们检查它是否已经存在于应用程序中。然后我们展开窗口并自动聚焦消息窗体。在文件底部,positionChatWindows()调用该函数以确保所有会话的窗口位置良好。如果我们没有定位它们,它们只会在同一个地方渲染,这当然是不可用的。

    现在在assets目录中创建一个文件,该文件将负责对话窗口的可见性和定位

    资产/ Java脚本/交谈/ position_and_visibility.js 我们可以使用gon gem ,而不是创建自己的设置和获取cookie的函数或类似的方式来管理JavaScript之间的数据。这个gem的原始用法是将数据从服务器端发送到JavaScript。但是我也发现它可以在整个应用程序中跟踪JavaScript变量。阅读说明安装并设置宝石。

    我们使用事件侦听器跟踪视口的宽度。当对话靠近视口的左侧时,对话将隐藏起来。一旦隐藏的对话窗口有足够的可用空间,应用程序就会再次显示它。

    在页面访问中,我们称定位和可见性功能来确保所有对话的窗口位于正确的位置。

    我们使用引导程序的面板组件来轻松地展开和折叠对话窗口。默认情况下,它们将被折叠而不是交互式。要使它们可切换,请在javascripts目录内创建一个新文件toggle_window.js

    Java脚本/会话/ toggle_window.js 创建一个新conversation_window.scss文件

    资产/样式表/谐音/ conversation_window.scss 并添加CSS样式对话窗口

    资产/样式表/谐音/ conversation_window.scss 您可能会注意到,有些类尚未在任何HTML文件中定义。这是因为我们将在views目录中创建的未来文件将与已有的HTML元素共享CSS。在我们添加任何次要的HTML元素之后,我没有多次来回跳转到CSS文件,而是在现在包含了一些在将来的HTML元素中定义的类。请记住,您可以随时访问样式表并分析特定样式的工作方式。

    以前我们已经在会话中保存了一个新创建的对话的ID。是时候利用它,并保持对话窗口打开,直到用户关闭它或破坏会话。在ApplicationController定义一个过滤器

    before_action:opened_conversations_windows 然后定义该opened_conversations_windows方法

    控制器/ application_controller.rb 该includes方法用于包含来自关联数据库表的数据。在不久的将来,我们会加载来自对话的消息。如果我们没有使用这个includes方法,我们就不会用这个查询加载对话的消息记录。这将导致N + 1查询问题。如果我们没有在查询中加载消息,则会为每条消息触发额外的查询。这会显着影响应用程序的性能。现在,对于100条消息而不是100条查询,对于任何数量的消息,我们只有一条初始查询。

    在application.html.erb文件内部,在yield方法下方,添加

    布局/ application.html.erb 创建一个新application目录并在里面创建_private_conversations_windows.html.erb部分文件

    布局/应用/ _private_conversations_windows.html.erb 现在,当我们浏览应用程序时,无论我们处于什么页面,我们始终都会看到已打开的对话。

    提交更改

    git add -A git commit -m“在应用上呈现私人对话窗口 -打开对话添加到会话 -私人/对话中创建一个_conversation.html.erb文件 -在定义private_conv_recipient辅助方法, 私有/ conversations_helper.rb -在私人::会话模型定义的opposed_user方法 和添加规格为它 - 在private / conversations / conversation中创建_heading.html.erb和_messages_list.html.erb文件

    • 在private / conversations_helper.rb中定义load_private_messages 并为其添加规范
    • 在 private / conversations / conversation中创建一个_new_message_form.html.erb
    • 创建一个_open.js.erbinside私人/会话
    • 在里面创建一个position_and_visibility.js assets / javascripts / conversations
    • 在 assets / stylesheets / partials中创建一个conversation_window.scss
    • 在 ApplicationController中定义一个opened_conversations_windows辅助方法
    • 在 layouts / application中创建一个_private_conversations_windows.html.erb 关闭对话

      会话的关闭按钮不起作用。但是我们已经准备好了一切。在里面Private::ConversationsController,定义一个close动作

    控制器/私营/ conversations_controller.rb 当关闭按钮被点击时,这个动作将被调用。该操作会将会话的ID从会话中删除,然后用与操作名称相同的js部分文件进行响应。创建部分文件

    民营/会话/ close.js.erb 它从DOM中删除对话窗口并重新定位对话窗口的其余部分。

    提交更改

    git add -A git commit -m“使关闭对话按钮有效

    • 在私人/对话内定义一个关闭动作“Private::ConversationsController
    • Create a close.js.erb inside the 呈现消息

      目前在消息列表中,我们看到一个没有任何消息的加载图标。这是因为我们还没有为消息创建任何模板。在views/private目录中,创建一个messages目录。在目录中,创建一个新文件

    私人/消息/ _message.html.erb 该private_message_date_check帮助方法检查该消息是否与前一条消息在同一天被写入。如果不是,则会渲染一个带有新日期的额外行。定义内部的助手方法Private::MessagesHelper

    佣工/私营/ messages_helper.rb 在里面ApplicationHelper,包括Private::MessagesHelper,所以我们可以通过应用程序访问它

    包括Private :: MessagesHelper 编写该方法的规格。创建一个新messages_helper_spec.rb文件

    规格/助理/私营/ messages_helper_spec.rb 在新message目录中创建一个_new_date.html.erb文件

    私人/消息/消息/ _new_date.html.erb 然后里面_message.html.erb的文件,我们有sent_or_received和seen_or_unseen辅助方法。他们在不同情况下返回不同的课程。在里面定义它们Private::MessagesHelper

    佣工/私营/ messages_helper.rb 为他们写规格:

    规格/助理/私营/ messages_helper_spec.rb 现在我们需要一个组件将消息加载到消息列表中。此外,该组件将在列表顶部添加先前的消息,当用户向上滚动时,直到没有消息留在对话中。我们将有一个无限的消息滚动机制,类似于我们在帖子页面中的滚动机制。

    在views/private/messages目录内创建一个_load_more_messages.js.erb文件:

    私人/消息/ _load_more_messages.js.erb 该@id_type实例变量确定类型的谈话。在未来,我们将不仅能够创建私人对话,还能创建团队。这导致两种类型之间的通用帮助方法和部分文件。

    在helpers目录中,创建一个shared目录。创建一个messages_helper.rb文件并定义一个辅助方法

    助手/共享/ messages_helper.rb 到目前为止,这个方法非常愚蠢。它只是返回一个部分的路径。稍后我们将为其提供一些智能,当时我们将为我们的消息传递系统构建额外的功能。现在,我们将无法访问此文件中定义的任何其他文件中的助手方法。我们必须将它们包含在其他帮助程序文件中。在里面 Private::MessagesHelper,包含来自的方法Shared::MessagesHelper

    要求'shared / messages_helper' 包含Shared :: MessagesHelper 在shared目录中,创建几个新目录:

    共享/ load_more_messages /窗 然后创建一个_append_messages.js.erb文件:

    共享/ load_more_messages /窗/ _append_messages.js.erb 此代码注意先前的消息会附加到消息列表的顶部。然后再定义另一个,而不是那个迷人的辅助方法Private::MessagesHelper

    佣工/私营/ messages_helper.rb 在目录内创建相应的private/messages目录并创建一个_add_link_to_messages.js.erb文件

    私人/消息/ load_more_messages /窗/ _add_link_to_messages.js.erb 该文件将更新加载先前消息的链接。之前的消息被追加后,链接将被替换为更新的链接以加载旧的旧消息。

    现在我们拥有了所有这个系统,以前的消息如何被附加到消息列表的顶部。但是,如果我们试图去应用程序并打开一个对话窗口,我们将看不到任何呈现的消息。为什么?因为没有东西会触发链接加载之前的消息。当我们第一次打开对话窗口时,我们希望看到最近的消息。我们可以用一种扩展的方式编程对话窗口,加载更多的消息链接被触发,以加载最近的消息。它启动了第一个附加前一个消息的循环,并用更新的消息替换了加载更多的消息链接。

    在toggle_window.js文件里面更新toggle函数来完成上面描述的内容

    Java脚本/会话/ toggle_window.js 创建一个事件处理程序,因此无论用户何时滚动并几乎到达消息列表的顶部,都会触发加载更多消息链接。

    资产/ Java脚本/交谈/ messages_infinite_scroll.js 当被点击更多信息链接会负载,一个Private::MessagesController的index动作被调用。这是路径,我们定义了加载之前的消息链接。创建控制器及其index操作

    控制器/私营/ messages_controller.rb 这里我们包含Messages模块中的方法。该模块存储在concerns目录中。ActiveSupport :: Concern是其中一个地方,您可以在其中存储稍后可以在课程中使用的模块。在我们的例子中,我们从模块向控制器添加了额外的方法。该get_messages方法来自Messages模块。它存储在模块内部的原因是我们稍后会在另一个控制器中使用完全相同的方法。为了避免代码重复,我们使该方法更加可重用。

    我看到一些人抱怨ActiveSupport::Concern并建议不要使用它。我挑战那些在八角形里打我的人。我在开玩笑:D。这是一个独立的应用程序,我们可以创建我们的应用程序,但我们喜欢它 如果你不喜欢concerns,还有其他一些方法来创建可重用的方法。

    创建模块

    控制器/关切/ messages.rb 在这里,我们需要active_support/concern然后扩展我们的模块ActiveSupport::Concern,所以Rails知道这是一个问题。

    通过该constantize方法,我们通过输入一个字符串值来动态创建一个常量名称。我们动态地调用模型。同样的方法将被用于Private::Conversation和Group::Conversation模型。

    在该get_messages方法设置了所有必需的实例变量之后,该index操作将以_load_more_messages.js.erb部分文件进行响应。

    最后,在消息附加到消息列表的顶部后,我们想要从对话窗口中删除加载图标。在_load_more_messages.js.erb文件的底部添加

    <%=呈现remove_link_to_messages%> 现在在remove_link_to_messages里面定义helper方法Shared::MessagesHelper

    助手/共享/ messages_helper.rb 尝试自行编写该方法的规范。

    创建_remove_more_messages_link.js.erb部分文件

    共享/ load_more_messages /窗/ _remove_more_messages_link.js.erb 现在,在这种情况下,以前的消息还没有离开,先前消息的链接和加载图标将被删除。

    如果您现在尝试联系用户,会话窗口将显示一条内部发送的消息。我们能够通过AJAX请求呈现消息。

    提交更改。

    git add -A git commit -m“使用AJAX呈现消息

    • 在private / messages中创建一个_message.html.erb
    • 在 Private :: MessagesHelper中定义一个private_message_date_check帮助器方法并为其编写规范
    • 在private / messages / message中创建一个_new_date.html.erb
    • 定义sent_or_received和seen_or_unseen帮助器方法 Private :: MessagesHelper并为它们编写规范
    • 在private / messages中创建_load_more_messages.js.erb
    • 在 Shared :: MessagesHelper中定义append_previous_messages_partial_path帮助器方法
    • 在 shared / load_more_messages / window中创建_append_messages.js.erb
    • 定义replace_link_to_private_messages_partial_path在_add_link_to_messages.js.erb里面 Private::MessagesHelper
    • Create a private / messages / load_more_messages / window
    • 在javascripts / conversations中创建toggle_window.js
    • 在 assets / javascripts / conversations中创建messages_infinite_scroll.js - 在Private :: MessagesController中定义一个索引操作
    • 在controllers / concerns中创建messages.rb
    • 在helpers / shared中定义remove_link_to_messages
    • 在 shared / load_more_messages / window中创建一个_remove_more_messages_link.js.erb “ 使用Action Cable的实时功能 对话的窗户看起来很整齐。他们也有一些甜蜜的功能。但是,他们缺乏最重要的功能 - 实时发送和接收消息的能力。

      如前所述,Action Cable将使我们能够实现对话所需的实时功能。您应该浏览文档以了解它是如何工作的。

      我们应该做的第一件事是创建一个WebSocket连接并订阅特定的频道。幸运的是,WebSocket连接已经被默认的Rails配置所覆盖。在app/channels/application_cable你看到的目录channel.rb和connection.rb文件中。的Connection类需要认证的关心和Channel类是存储所有信道之间共享的逻辑父类。

      连接默认设置。现在我们需要一个私人对话频道来订阅。生成名称空间频道

      导轨g通道私人/对话 在生成的内部Private::ConversationChannel,我们看到subscribed和unsubscribed方法。通过该subscribed方法,用户创建到该频道的连接。unsubscribed显然,使用该方法的用户会破坏连接。

      更新这些方法:

    渠道/私营/ conversation_channel.rb 在这里,我们希望用户拥有自己的独特频道。用户将从频道接收和发送数据。由于用户的ID是唯一的,因此我们通过添加用户的ID来使通道唯一。

    这是一个服务器端连接。现在我们需要在客户端创建一个连接。

    要在客户端创建连接的实例,我们必须编写一些JavaScript。实际上,Rails已经使用通道生成器创建了它。导航到assets/javascripts/channels/private默认情况下,Rails生成CoffeeScript文件。我要在这里使用JavaScript。因此,将文件重命名为conversation.js并替换其内容:

    资产/ Java脚本/渠道/私营/ conversation.js 重新启动服务器,转到应用程序,登录并检查服务器日志。

    我们得到了连接。实时通信的核心已经确定。我们有一个不断开放的客户端 - 服务器连接。这意味着我们可以从服务器发送和接收数据,而无需重新启动连接或刷新浏览器,man!一个真正强大的东西,当你想到它。从现在开始,我们将围绕此连接构建消息传递系统。

    提交更改。

    git add -A git commit -m“创建一个唯一的私人对话频道并订阅它” 让我们使对话窗口的新消息功能。在assets/javascripts/channels/private/conversations.js文件的底部添加这个功能:

    资产/ Java脚本/渠道/私营/ conversation.js 该函数将从新的消息表单中获取值并将它们传递给send_message函数。该send_message函数将send_message在服务器端调用一个方法,该方法将负责创建一条新消息。

    另外请注意,事件处理程序位于提交按钮上,但在对话窗口中我们没有任何可见的提交按钮。这是一个设计选择。我们必须按照在键盘上单击Enter键时触发提交按钮的方式编程对话窗口。这个功能将来会被其他功能使用,因此conversation.js在assets/javascripts/conversations目录中创建一个文件

    assets/javascripts/conversations/conversation.js 在文件中,我们描述了会话窗口的一些常规行为。第一种行为是让滚动条远离顶部,因此以前的消息在不需要时不会被加载。第二个函数确保在输入键单击时触发提交按钮,然后将输入的值清除回空字符串。

    首先send_message在private_conversation对象内部创建函数。将其添加到received回调函数下面

    资产/ Java脚本/渠道/私营/ conversation.js 这将调用send_message服务器端的方法并传递消息值。服务器端的方法应该在里面定义Private::ConversationChannel。定义方法:

    渠道/私营/ conversation_channel.rb 这将处理新消息的创建。该data参数,这是我们从传递的参数得到的,是一个嵌套的哈希值。所以为了将这种嵌套的复杂性降低到单个散列,使用了该each_with_object方法。

    如果您尝试在对话窗口内发送新消息,则实际上会创建新的消息记录。它只会在刷新网站时才会立即显示在对话窗口中。它会显示出来,但我们没有设置任何信息将新创建的消息广播到私人对话的频道。我们稍后会执行它。但在我们继续并提交更改之前,请快速回顾当前的邮件系统的工作原理。

    用户填写新的消息表单并提交消息 javascripts/channels/private/conversations.js获取对话窗口的数据,对话ID和消息值中的事件处理程序,并触发客户端send_message函数上的通道实例。

    1. send_message客户端的功能调用send_message服务器端的方法并将数据传递给它

    2. send_message客户端处理方法提供数据并创建新Private::Message记录

      提交更改。

      git add -A git commit -m“使私人对话窗口的新消息形式起作用

    3. 在 javascripts / channels / private / conversation.js中添加一个事件处理程序来触发提交按钮
    4. 定义一个通用行为 assets/javascripts/conversations/conversation.js
    5. Define a send_message function on both, client and server, sides" 广播一条新消息

      在创建新消息后,我们想以某种方式将其广播到相应的频道。那么,Active Record回调为我们提供了大量有用的模型回调方法。有一个after_create_commit回调方法,在创建新模型记录时运行。在Private::Message模型文件中添加

    车型/私营/ message.rb 正如你所看到的,创建一个记录之后,Private::MessageBroadcastJob.perform_later获取者会被调用。那是什么?这是一个后台工作,处理后端操作。它允许我们随时运行某些操作。它可能在特定事件之后立即发生,或者预定在事件发生后一段时间后运行。如果您不熟悉后台作业,请检查“ 活动作业基础”。

    为该previous_message方法添加规格。如果您现在要尝试运行规格,请注释掉该after_create_commit方法。我们还没有定义Private::MessageBroadcastJob,所以目前的规格会引发一个未定义的常量错误。

    规格/型号/私营/ message_spec.rb 现在我们可以创建一个后台作业,将一个新创建的消息广播到私人对话的频道。

    rail g私人/ message_broadcast 在文件里面我们看到一个perform方法。默认情况下,当您调用作业时,将调用此方法。现在在工作中,处理给定的数据并将其广播给频道的订户。

    工作/私有/ message_broadcast_job.rb 在这里,我们呈现一条消息并将其发送给两个频道的订阅者。我们还传递一些额外的键值对以正确显示消息。如果我们尝试发送新消息,用户会收到数据,但消息不会附加到消息列表中。没有可见的变化。

    当数据被广播到一个通道时,received客户端的回调函数被调用。这是我们有机会将数据附加到DOM的地方。在received函数内部添加下面的代码:

    资产/ Java脚本/渠道/私营/ conversation.js 在这里,我们看到发件人和收件人的处理方式有点不同。

    //在有看不见的消息时,改变conv窗口的风格 //向对话的窗口添加额外的类或其他类 我故意创造了这个,所以无论何时一个对话看不见消息,你都可以设置窗口的样式,但是你喜欢它。你可以改变一个窗口的颜色,使其闪烁,或任何你想要的。

    还有一些findConv,ConvRendered,ConvMessagesVisibility使用的功能。我们将把这些功能用于聊天类型,私人和群组。

    创建一个shared目录:

    资产/ Javascript角/信道/共享 conversation.js在这个目录下创建一个文件。

    资产/ Javascript角/信道/共享/ conversation.js 代码中提到了一个使者,我们还没有这个使者。信使将成为一种单独的方式来公开对话。为了防止未来出现很多小的变化,我现在已经包含了使用Messenger的案例。

    就是这样,实时功能应该可以工作。用户(发件人和收件人)都应该在DOM上接收并显示新消息。当我们发送一条新消息时,我们应该立即将它看到消息列表中。但现在有一个小问题。我们只有一种方法来呈现对话窗口。它仅在创建对话时才呈现。我们将添加额外的方式来呈现对话窗口。但在此之前,让我们回顾一下数据如何到达频道的订阅者。

    Private::Message创建新记录后,after_create_commit触发该方法,调用后台作业 Private::MessageBroadcastJob 处理给定数据并将其广播给频道的订户 在客户端received调用回调函数,它将数据附加到DOM 提交更改。

    git add -A git commit -m“广播一条新消息

    • Private :: Message内部定义了一个after_create_comit回调方法。
      • 创建一个Private :: MessageBroadcastJob
      • 在 assets / javascripts / channels / private / conversation.js中定义一个收到的函数
      • 在 assets / javascripts / channels / shared中创建一个conversation.js “ 导航栏更新 在导航栏上,我们将呈现用户对话列表。当对话列表打开时,我们希望看到最新消息排列的对话。与最近消息的对话将位于列表的顶部。这个列表应该可以在整个应用程序中访问。因此ApplicationController,商店里面的用户对话是在一个实例变量中进行的。我建议的做法是all_ordered_conversations在控制器内定义一个方法

    控制器/ application_controller.rb 添加一个before_action过滤器,以便@all_conversations实例变量在任何地方都可用。

    before_action:all_ordered_conversations 然后创建一个OrderConversationsService来关注对话的查询和排序。

    服务/ order_conversations_service.rb 目前该服务仅处理私人对话,这是迄今为止我们开发的唯一对话类型。将来我们会将私人和小组会话混合在一​​起,并按照最新消息对其进行分类。该sort方法用于对一组对话进行排序。再一次,如果我们不使用这个includes方法,我们会遇到一个N + 1查询问题。因为当我们对对话进行分类时,我们会检查每条对话的最新消息的创建日期并进行比较。这就是为什么在查询中我们包含了消息的记录。

    的<=>运算符计算其created_at值越高。如果我们使用
    a <=> b它,它会按升序对给定的数组进行排序。当您以相反的方式评估值时b <=> a,它会按降序对数组进行排序。

    我们还没有all_by_user在Private::Conversation模型中定义范围。打开模型并定义范围:

    车型/私营/ conversation.rb 编写服务和范围的规范:

    规格/型号/私营/ conversation_spec.rb

    投机/服务/ order_conversations_service_spec.rb 提交更改。

    git add -A git commit -m“

    • 创建OrderConversationsService并为其添加规范
    • 在Private :: Conversation 模型中定义一个all_by_user作用域,并为其添加规范” 现在在视图中,我们可以访问一系列有序对话。我们来渲染他们的链接列表。只要用户点击其中的任何一个,对话窗口就会在应用程序上呈现。如果您还记得,我们的导航栏有两个主要组件。在一个组件中,元素不断显示。在另一个组件中,元素在较小的设备上崩溃。因此,在导航标题中,组件始终可见,我们将创建一个会话下拉菜单。通常,为了防止有一个大的视图文件,将其分割成多个较小的文件。

      打开导航_header.html.erb文件并用以下内容替换其内容:

    布局/导航/ _header.html.erb 现在创建一个header包含_toggle_button.html.erb文件的目录

    布局/导航/报头/ _toggle_button.html.erb 这是一个以前位于_header.html.erb文件内部的切换按钮。在header目录中创建另一个文件

    布局/导航/报头/ _home_button.html.erb 这是来自主页的主页按钮_header.html.erb。此外还有一个额外的链接。在较小的设备上,我们将显示一个图标,而不是应用程序的名称。

    回头看_header.html.erb文件。有一个辅助方法nav_header_content_partials,它返回部分路径的数组。我们之所以不逐一渲染部分是因为阵列在不同情况下会有所不同。在NavigationHelper定义方法内部

    助手/ navigation_helper.rb 编写内部方法的规范 navigation_helper_spec.rb

    规格/助理/ navigation_helper_spec.rb 现在创建必要的文件来显示导航栏上的下拉菜单。首先创建一个_dropdowns.html.erb文件

    布局/导航/报头/ _dropdowns.html.erb dropdowns用_conversations.html.erb里面的文件创建一个目录

    布局/导航/报头/下拉菜单/ _conversation.html.erb 这是我们使用@all_conversations实例变量的地方,它在控制器之前定义,并呈现链接以打开对话。不同类型对话的链接会有所不同。我们需要为私人和群组对话创建两个不同版本的链接。首先定义conversation_header_partial_path里面的帮助器方法NavigationHelper

    助手/ navigation_helper.rb 为它写规格:

    规格/助理/ navigation_helper.rb 当然,我们还没有做过与群体对话的任何事情。所以你必须在规范中评论小组对话的一部分,以避免失败。

    为私人对话链接创建一个文件:

    布局/导航/报头/下拉菜单/会话/ _private.html.erb private_conv_seen_status在新的内部定义辅助方法Shared::ConversationsHelper

    助手/共享/ conversations_helper.rb 将此模块添加到 Private::ConversationsHelper

    包括Shared :: ConversationsHelper Inside specs创建一个shared包含conversations_helper_spec.rb文件的目录来测试private_conv_seen_statushelper方法。

    规格/助手/共享/ conversations_helper_spec.rb 当点击一个对话的链接时,Private::Conversation控制器的open动作被调用。定义到此操作的路线。在routes.rb文件post :open内部,在名称空间privateconversations资源内添加一个成员,位于该文件的正下方post :close。

    当然,不要忘记在控制器中定义动作本身:

    conversations_controller.rb 现在当您点击链接时,对话窗口应该打开。现在导航栏很混乱,我们必须照顾它的设计。要设置下拉菜单的样式,请将CSS添加到navigation.scss文件中。

    资产/样式表/谐音/布局/ navigation.scss 更新max-width: 767px内部的媒体查询mobile.scss

    资产/样式表/响应/ mobile.scss 在中更新min-width: 767px媒体查询desktop.scss

    资产/样式表/响应/ desktop.scss 该应用现在看起来像这样

    然后,您可以展开对话列表

    通过点击任何菜单链接,应用程序上将出现对话窗口

    如果您尝试缩小浏览器的大小,应该逐个隐藏对话

    另请注意,我们现在有主页图标,而不是collage标志。而对话列表在小屏幕上仍然可用。那么,如果对话窗口隐藏在较小的设备上,用户将如何在移动设备上进行通信?我们将创建一个将被打开而不是对话窗口的信使。

    提交更改

    git add -A git commit -m“呈现会话链接的下拉菜单

    • 将layouts / navigation / _header.html.erb文件的内容分割成部分
    • 在layouts / navigation / header 内创建_toggle_button.erb.html - 在layouts / navigation / header内创建_home_button.html.erb
    • 在NavigationHelper中定义nav_header_content_partials 和编写规范
    • 在layouts / navigation / header 内创建一个_dropdowns.html.erb - 在 layouts / navigation / header / dropdowns中创建一个_conversation.html.erb
    • 在NavigationHelper中定义一个conversation_header_partial_path 并为其编写规范
    • 创建一个_private。 html.erb在 layouts / navigation / header / dropdowns / conversations里
    • 定义一个Shared :: ConversationsHelper并为它写规格private_conv_seen_status inside

    • 在Private :: Conversations控制器中定义一个打开的动作

    • 将CSS添加到导航栏上的样式下拉菜单中。 里面的navigation.scss,mobile.scss和desktop.scss“ 现在是确保实时消息的所有功能都能正常工作的好时机。

      因为我们正在向DOM动态添加元素,有时元素被添加得太晚,并且Capybara认为元素不存在,因为默认的等待时间仅为2秒。为了避免这些故障,在内部rails_helper.rb,更改5到10秒之间的等待时间。

    投机/ rails_helper.rb 在spec/features/private/conversations folder创建一个window_spec.rb文件。

    规格/功能/私营/会话/ window_spec.rb 这里我没有定义规格,以测试收件人用户是否实时接收邮件。试着弄清楚如何自己编写这样的测试。

    提交更改

    git add -A git commit -m“添加规格以测试对话窗口的功能” 如果您登录了收到消息的帐户,您会注意到一个对话,标记为未见

    此时,没有办法标记所见的对话。默认情况下,新消息有一个看不见的值。以对话窗口打开或点击的方式对应用程序进行编程,其消息被标记为可见。另请注意,当下拉菜单展开时,我们目前只能看到高亮显示的未看到的会话。将来我们将创建一个通知功能,这样用户就会知道他们获得了新的消息而没有展开任何内容。

    我们来解决第一个问题。当应用程序已经呈现会话,但已折叠并且用户单击下拉菜单的链接打开该会话时,什么都不会发生。该折叠的会话保持折叠状态。我们必须添加一些JavaScript,所以在下拉菜单的链接点击的情况下,对话应该扩展并聚焦它的新消息区域。

    打开下面的文件并添加来自Gist的代码以实现该目标。

    资产/ Java脚本/交谈/ toggle_window.js

    资产/ Java脚本/交谈/ toggle_window.js 当你点击一个链接时,打开一个对话窗口,不管对话是否已经存在于应用程序中,它都会被展开。

    现在我们需要一个事件处理器。点击了看不见的消息的对话窗口后,私人对话客户端应该触发回调函数。首先,在私人对话客户端的文件底部定义一个事件处理程序

    资产/ Java脚本/渠道/私营/ conversation.js 这个代码片段已经包含了一个信使存在的例子。

    然后,在函数的private_conversation下面定义实例内部的回调send_message函数

    资产/ Java脚本/渠道/私营/ conversation.js 最后,在服务器端定义这个方法

    渠道/私营/ conversation_channel.rb 在用户点击链接打开对话窗口或直接点击对话窗口后,其未看到的消息将被标记为可见。

    提交更改

    git add -A git commit -m“添加标记未见消息的功能

    • 添加一个事件处理程序来扩展 assets / javascripts / conversations / toggle_window.js中的对话窗口
    • 添加一个事件处理程序来标记看不见的消息,如 assets / javascripts / channels / private / conversation.js中所示
    • 定义一个set_as_seen方法私人:: ConversationChannel” 通过编写规格确保一切正常。

      往来 要与人保持联系,您在应用中遇到了问题,您必须能够将其添加到联系人中。我们现在缺少这项功能。同时拥有联系人功能可以创建其他功能,只有被接受为联系人的用户才能执行其他功能。

      生成一个Contact模型

      轨道g模型联系 定义关联,验证和方法,通过提供用户的ID来查找联系人记录。

    车型/ contact.rb 定义联系人表

    分贝/迁移/ CREATION_DATE_create_contacts.rb 将需要一个联系工厂。定义它:

    规格/工厂/ contacts.rb 编写规格来测试模型

    规格/型号/ contact_spec.rb 提交更改

    git add -A git commit -m“创建联系人模型并为其编写规范” 在User模型文件中,我们必须定义适当的关联,并定义一些方法来帮助联系人的查询。

    车型/ user.rb 涵盖规格的关联和方法

    规格/型号/ user_spec.rb 提交更改

    git add -A git commit -m“将关联和辅助方法添加到用户模型中

    • 在用户与联系人模型之间建立关系
    • 方法帮助查询联系人记录“ 生成一个Contacts控制器并定义其操作

      导轨g控制器触点

      控制器/ contacts_controller.rb 如您所见,用户将能够创建新的联系人记录,更新其状态(接受用户到他们的联系人)并从联系人列表中删除用户。由于所有操作都是通过AJAX调用的,我们不想将任何模板呈现为响应,因此我们会响应成功响应。这样,Rails就不必考虑回应什么。

      定义相应的路线:

    的routes.rb 提交更改。

    git add -A git commit -m“创建一个ContactsController并定义其行为的路由” 私人对话的窗口更新 用户将能够发送和接受联系请求的方式是通过私人对话的窗口。稍后我们将通过导航栏的下拉菜单添加一个额外的方式来接受请求。

    创建一个新heading目录

    民营/会话/会话/标题 这是我们为私人对话窗口保留额外选项的地方。在目录中,创建一个_add_user_to_contacts.html.erb文件

    民营/会话/会话/标题/_add_user_to_contacts.html.erb 在_heading.html.erb文件的底部,呈现选项以将对话的相反用户添加到联系人:

    民营/会话/会话/ _heading.html.erb 定义专用范围内的辅助方法和附加方法

    佣工/私营/ conversations_helper.rb 为这些辅助方法编写规范

    规格/助理/私营/ conversations_helper_spec.rb 该instance_eval方法用于测试私人范围内的方法。

    因为我们要在对话窗口的标题元素上显示选项,所以我们必须确保其他选项完全符合标题。在_heading.html.erb文件内部,将该类替换为,以确定要添加哪个类。conversation-heading <%= conv_heading_class(@contact) %>

    定义辅助方法

    佣工/私营/ conversations_helper.rb 编写该方法的规格

    规格/助理/私营/ conversations_helper_spec.rb 用于发送或接受联系请求的选项将不会显示。需要添加更多元素。打开_conversation.html.erb文件

    民营/会话/ _conversation.html.erb 在文件的顶部,定义一个@contact实例变量,因此它可以在所有部分中访问

    民营/会话/ _conversation.html.erb 定义get_contact_record辅助方法

    佣工/私营/ conversations_helper.rb 根据规格覆盖方法

    规格/助理/私营/ conversations_helper_spec.rb 以前,我们用current_user和recipient let只在私人范围的上下文的方法。现在我们需要使用私有和公共方法访问它们。因此,将它们剪切并放置在私人范围的上下文之外。

    在.panel-body元素的顶部 ,渲染一个部分文件,该文件将显示一个额外的消息窗口来接受或拒绝联系请求

    民营/会话/ _conversation.html.erb 创建_request_status.html.erb文件

    民营/会话/会话/ _request_status.html.erb 定义所需的帮助方法

    佣工/私营/ conversations_helper.rb 为辅助方法编写规范

    规格/助理/私营/ conversations_helper_spec.rb 创建request_status目录,然后创建_send_request.html.erb,_sent_by_current_user.html.erb以及_sent_by_recipient.html.erb部分文件

    民营/会话/会话/ REQUEST_STATUS / _send_request.html.erb

    民营/会话/会话/ REQUEST_STATUS / _sent_by_current_user.html.erb

    民营/会话/会话/ REQUEST_STATUS / _sent_by_recipient.html.erb 提交更改

    git add -A git commit -m“在私人对话的窗口中添加一个按钮 以将收件人添加到联系人” 实施设计更改并关注由于对话窗口上的额外元素而出现的样式问题。将CSS添加到conversation_window.scss文件

    样式表/分音/ conversation_window.scss 提交更改

    git add -A git commit -m“将CSS添加到conversation_window.scss风格选项按钮” 当对话窗口折叠时,最好不要看到任何选项。只有在扩展对话窗口时才能看到选项,这是一种更方便的设计。要实现它,在toggle_window.js文件的切换功能中,在messages_visible变量的下面添加

    资产/ Java脚本/交谈/ toggle_window.js 现在折叠的窗口看起来像这样,它没有可见的选项

    展开的窗口可以选择将用户添加到联系人。还有一条信息表明要这样做

    实际上,您现在可以通过点击对话标题上的图标或点击Add to contacts链接来发送和接受联系请求。目前,点击这些链接和按钮后没有任何回应。稍后我们会添加一些反馈和实时通知系统。但从技术上讲,您可以将用户添加到您的联系人中,但它的用户友好性不高。

    发送联系请求后,对方用户的一侧看起来像这样

    提交更改

    git add -A git commit -m“在toggle_window.js中添加JS以显示和隐藏其他选项” 目前用户可以私下谈话,进行一对一的对话。由于该应用程序是关于协作的,因此也可以进行群组对话。 首先生成一个新模型

    轨道g模型组/会话 多个用户将能够参与一个对话。定义关联和数据库表

    车型/组/ conversation.rb

    车型/ user.rb 一个连接表将被用于跟踪谁属于哪个组对话

    然后为消息生成一个模型

    导轨g模型组/消息

    车型/组/ message.rb 我们将存储用户的已经看到消息的ID到一个数组中。要在数据库列中创建和管理对象(如数组),使用serialize方法。一个默认范围,最大限度地减少查询的数量,并添加一些验证。

    我们建立小组对话的方式与私人对话非常相似。事实上,这两种类型的对话之间的样式和一些部分将是共同的。

    编写模型的规格。另外还需要一个用于群组消息的工厂

    规格/工厂/ group_messages.rb

    规格/型号/ user_spec.rb

    规格/型号/组/ conversation_spec.rb

    规格/型号/组/ message_spec.rb 定义迁移文件

    分贝/迁移/ CREATION_DATE_create_group_conversations.rb

    分贝/迁移/ CREATION_DATE_create_group_conversations_users_join_table.rb

    分贝/迁移/ CREATION_DATE_create_group_messages.rb 小组对话的基本原则已经确定。

    提交更改

    git add -A git commit -m“创建Group :: Conversation和Group :: Message模型

    • 定义关联
    • 编写规范“ 创建一个群组对话

      如前所述,创建群组对话功能的过程将与我们对私人对话所做的相似。首先创建一个控制器和一个基本的用户界面。

      生成命名空间控制器

      导轨g控制器组/对话 控制器内部定义一个create动作和add_to_conversations,already_added?和create_group_conversation私人范围内的方法

    控制器/组/ conversations_controller.rb 创建一个新的群组会话有一些复杂性,所以我们将其提取到一个服务对象中。然后我们有add_to_conversations和already_added?私有方法。如果你还记得,我们也有他们的Private::ConversationsController,但这次它将小组对话的ID存储在会话中。

    现在在Group::NewConversationService里面定义一个新的group目录

    服务/组/ new_conversation_service.rb 新群体对话的创建方式实际上是通过私人对话。我们很快就会在私人对话的窗口上创建该界面作为选项。在这之前,请确保服务对象通过覆盖规格来正常运行。在里面services,group用new_conversation_service_spec.rb里面的文件创建一个新的目录

    投机/服务/组/ new_conversation_service_spec.rb 提交更改

    git add -A git commit -m“创建用于创建新组对话的后端

    • 创建一个Group :: ConversationsController 定义一个create action和add_to_conversations, create_group_conversation并already_added?私人方法
    • 创建一个Group :: NewConversationService并为其写入规范“ 定义组对话及其消息的路由

    的routes.rb 提交更改

    git add -A git commit -m“定义Group :: Conversations和Messages的规格” 目前我们只关心私人对话ApplicationController。只有私人对话正在订购,并且只有用户打开它们后才能在应用程序中使用它们。在里面ApplicationController,更新opened_conversations_windows方法

    控制器/ application_controller.rb 因为会话的顺序发生在一个帮助下OrderConversationsService,我们必须更新此服务

    order_conversations_service.rb 以前我们只有私人对话数组,并且按照最新消息的创建日期对它进行了排序。现在我们有私人和小组会话数组,然后我们将它们连接成一个数组并按照与之前一样的方式对它们进行排序。

    同时更新规格

    投机/服务/ order_conversations_service_spec.rb 提交更改

    git add -A git commit -m“在ApplicationController中获取组对话的数据

    • 更新 opened_conversations_windows method
      • Update the OrderConversationsService" 在短短的一段时间里,我们需要将一些数据从控制器传递到JavaScript。幸运的是,我们已经安装了gon宝石,这让我们可以轻松完成。里面ApplicationController,一个内private范围,加

    控制器/ application_controller.rb 使用before_action过滤器来调用此方法

    before_action:set_user_data 提交更改

    git add -A git commit -m“在ApplicationController中定义一个set_user_data私有方法” 从技术上讲,我们现在可以创建一个新的群组对话,但用户没有界面来做到这一点。如前所述,他们会通过私人对话来完成。我们在私人对话的窗口上创建这个选项。

    在 - 的里面

    意见/私营/会话/会话/标题 目录创建一个新文件

    民营/会话/会话/标题/ _create_group_conversation.html.erb 一种collection_select方法用于显示用户列表。只有在联系人中的用户才会包含在列表中。定义contacts_except_recipient辅助方法

    佣工/私营/ conversations_helper.rb 编写该方法的规格

    规格/助理/私营/ conversations_helper_spec.rb 呈现底部的部分 _heading.html.erb

    民营/会话/会话/ _heading.html.erb 定义辅助方法

    佣工/私营/ conversations_helper.rb 用规格包装它

    规格/助理/私营/ conversations_helper_spec.rb 提交更改。

    git add -A git commit -m“在私人对话中添加用户界面以创建群组对话” 添加CSS以对允许创建新组对话的组件进行样式设置

    资产/样式表/谐音/ conversation_window.scss 选择的联系人默认为隐藏。要打开选择,用户必须点击按钮。该按钮不具有互动性。options.js使用JavaScript内部创建一个文件,使选择列表可切换。

    资产/ Java脚本/交谈/ options.js 现在,与联系人的收件人的对话窗口看起来像这样

    有一个按钮可打开联系人列表,您可以在点击它时创建组对话

    提交更改。

    git add -A git commit -m“

    • 描述创建组对话选项的样式
    • 使选项可切换” 我们有一系列有序的会话,包括现在的群组会话,这些会话将在导航栏的下拉菜单中呈现。如果您记得,我们为不同类型的对话指定了不同的部分。当应用程序尝试呈现链接时,要打开组对话,它将查找与私人对话不同的文件。该文件尚未创建。

      创建一个_group.html.erb文件

    导航/报头/下拉菜单/会话/ _group.html.erb 定义group_conv_seen_status内部的助手方法Shared::ConversationsHelper

    助手/共享/ conversations_helper.rb 编写该方法的规格

    规格/助手/共享/ conversations_helper_spec.rb 提交更改。

    git add -A git commit -m“在导航栏上创建一个链接来打开组对话” 呈现应用中的群组对话窗口,就像我们呈现私人对话一样。在application.html.erb提供的私人对话下面,添加:

    布局/ application.html.erb 创建部分文件以逐个呈现组对话窗口:

    布局/应用/ _group_conversations_windows.html.erb 提交更改。

    git add -A git commit -m“在 application.html.erb中渲染组对话”窗口“ 我们有一种机制如何在应用上创建和呈现群组对话。现在让我们自己建立一个对话窗口。

    在group/conversations目录中,创建一个_conversation.html.erb文件。

    组/会话/ _conversation.html.erb 定义add_people_to_group_conv_list辅助方法:

    助手/组/ conversations_helper.rb 为帮手编写规格:

    规格/助理/组/ conversations_helper_spec.rb 就像私人对话一样,小组对话将在整个应用程序中被访问,显然,我们也需要访问各个Group::ConversationsHelper方法。在模块里面添加这个模块ApplicationHelper

    包括Group :: ConversationsHelper 提交更改。

    git add -A git commit -m“

    • 在组/对话中创建一个_conversation.html.erb
    • 定义一个add_people_to_group_conv_list and write specs for it" conversation用_heading.html.erb里面的文件创建一个新的目录:

    组/会话/会话/ _heading.html.erb 提交更改。

    git add -A git commit -m“在 组/对话/对话中创建一个_heading.html.erb ” 接下来我们有_select_user.html.erb和_messages_list.html.erb部分文件。创建它们:

    组/会话/会话/ _select_users.html.erb

    组/会话/会话/ _messages_list.html.erb 定义load_group_messages_partial_path辅助方法:

    辅助/组/ conversations_helper.rb 用规格包装它:

    规格/助理/组/ conversations_helper_spec.rb 提交更改。

    git add -A git commit -m“

    • 创建_select_user.html.erb和分组/对话/对话- 定义一个_messages_list.html.erb inside

      load_group_messages_partial_path helper method and write specs for it" 创建一个_link_to_previous_messages.html.erb文件,以获得一个加载以前消息的链接:

    组/会话/会话/ messages_list / _link_to_previous_messages.html.erb 提交更改。

    git add -A git commit -m“在 group / conversations / conversation / messages_list中创建一个_load_messages.html.erb ” 创建一个新的消息表单

    组/会话/会话/ _new_message_form.html.erb 提交更改。

    git add -A git commit -m“在 group / conversations / conversation / 里创建一个_new_message_form.html.erb ” 该应用程序现在也可以呈现组对话的窗口。

    但是,它们还不起作用。首先,我们需要加载消息。我们需要一个控制器来处理消息和视图。生成一个Messages控制器:

    导轨g控制器组/消息 包含Messages模块concerns并定义一个index操作:

    控制器/组/ messages_controller.rb 提交更改。

    git add -A git commit -m“创建一个Group :: MessagesController并定义一个索引操作” 创建一个 _load_more_messages.js.erb

    组/消息/ _load_more_messages.js.erb 我们已经确定的append_previous_messages_partial_path和remove_link_to_messages早期的辅助方法。我们只需要定义replace_link_to_group_messages_partial_path辅助方法

    助手/组/ messages_helper.rb 再一次地,这种方法就像私人方面一样,一旦我们开发信使,就会变得更加“聪明”。

    创建 _replace_link_to_messages.js.erb

    组/消息/ load_more_messages /窗/ _replace_link_to_messages.js.erb 另外添加Group::MessagesHelper到ApplicationHelper

    包括Group :: MessagesHelper 提交更改。

    git add -A git commit -m“创建一个_load_more_messages.js.erb inside the group/messages" 现在可以立即打开小组对话的唯一方式就是在初始化之后。显然,这不是一件令人兴奋的事情,因为一旦你破坏了会话,就没有办法再次打开同一个对话。open在控制器内创建一个动作。

    控制器/组/ conversations_controller.rb 创建_open.js.erb部分文件:

    组/会话/ _open.js.erb 现在,我们可以通过点击导航栏的下拉菜单链接打开对话。尝试使用您自己的功能规格进行测试。

    提交更改。

    git add -A git commit -m“添加打开组对话的能力

    • 在Group :: ConversationsController中创建一个打开的动作
    • 在组/会话中创建一个_open.js.erb“ 该应用程序将尝试呈现消息,但我们还没有为它们创建任何模板。创建一个_message.html.erb

    组/消息/ _message.html.erb 定义group_message_date_check_partial_path,group_message_seen_by并message_content_partial_path辅助方法。

    助手/ group_message_helper.rb 该group_message_seen_by方法将返回看到消息的用户列表。这些信息使我们能够创建额外的功能,例如向看到消息的对话参与者展示等。但在我们的案例中,我们将使用这些信息来确定当前用户是否看到过消息。如果不是,那么在用户看到它之后,该消息将被标记为可见。

    我们还需要Shared模块中的帮助器方法。在里面Group::MessagesHelper,添加模块。

    要求'shared / messages_helper' 包含Shared :: MessagesHelper 用规范包装帮助器方法:

    规格/助理/组/ messages_helper_spec.rb 提交更改。

    git add -A git commit -m“创建一个_message.html.erb inside group/messages -定义group_message_date_check_partial_path, group_message_seen_by并message_content_partial_path辅助 方法和为他们写规范” 为消息创建部分文件:

    组/消息/ _new_date.html.erb

    组/消息/消息/ _different_user_content.html.erb

    组/消息/消息/ _same_user_content.html.erb 提交更改。

    git add -A git commit -m“ 在group / messages / message /内创建_new_date.html.erb, _different_user_content.html.erb和_same_user_content.html.erb ” 现在我们需要一种能逐个呈现消息的机制。创建一个_messages.html.erb部分文件:

    组/会话/ _messages.html.erb 提交更改。

    git add -A git commit -m“在组/对话中创建_messages.html.erb” 为群组消息添加样式:

    资产/样式表/谐音/ conversation_window.scss 提交更改。

    git add -A git commit -m“为conversation_window.scss中的群组消息添加CSS” 通过close在内部定义一个动作来使关闭按钮有效Group::ConversationsController

    控制器/组/ conversations_controller.rb 创建相应的模板文件:

    组/会话/ close.js.erb 提交更改。

    git add -A git commit -m“添加一个关闭组对话窗口功能

    • 在里面定义一个关闭动作 Group::ConversationsController

      • Create a close.js.erb inside the group/conversations" 实时沟通

      就像私人对话一样,我们希望能够在同一个窗口与多个用户实时进行对话。实现这一功能的过程与我们用私人对话做的非常相似。

      为群组对话生成新频道

      导轨g通道组/对话

      通道/组/ conversation_channel.rb 这次我们在建立连接之前检查用户是否属于对话belongs_to_conversation。在私人对话中,我们通过提供current_user身份证号码从一个独特的频道进行流式传输。在群组对话的情况下,会话的ID从客户端传递。通过该belongs_to_conversation方法,我们检查用户是否没有进行任何操作,也没有尝试连接到他们不属于的频道。

      提交更改

      git add -A git commit -m“创建一个Group :: ConversationChannel” 创建 Group::MessageBroadcastJob

      Rails g工作组/ message_broadcast

      工作/组/ message_broadcast_job.rb 提交更改。

      git add -A git commit -m“创建一个Group :: MessageBrodcastJob” 最后一个缺失的难题 - 客户端:

    资产/ Javascript角/通道/组/ conversation.js 基本上,它与私人对话.js文件非常相似 。代码的布局有点不同。主要区别在于能够将会话传递id 到文件顶部的频道和循环。通过这个循环,我们将用户连接到其所有组对话的频道。这就是我们belongs_to_conversation在服务器端使用该方法的原因。会话的Id从客户端传递。服务器端的这种方法确保用户确实属于提供的对话。

    当你考虑它时,我们可以在服务器端创建这个循环,而不必处理所有的确认过程。但是,这就是为什么我们传递客户端对话ID的一个原因。当新用户被添加到群组对话中时,我们希望将他们立即连接到对话的频道,而无需重新加载页面。通过会话的ID可以让我们毫不费力地实现这一点。在即将到来的部分中,我们将为每个用户实时接收通知创建一个独特的频道。当新用户将被添加到群组对话中时,我们将调用subToGroupConversationChannel功能,通过他们独特的通知渠道,并将他们连接到群组对话渠道。如果我们不允许将对话的ID传递给频道,则只有在页面重新载入后才会连接到新频道。我们没有办法将新用户动态连接到对话频道。

    现在我们可以实时发送和接收群组消息。尝试使用您自己的规格来测试整体功能。

    提交更改。

    git add -A git commit -m“在 assets / javascripts / channels / group中创建一个conversation.js ” 里面的Group::ConversationsController定义update动作

    控制器/组/ conversations_controller.rb 创建Group::AddUserToConversationService,这将会注意到选定的用户将被添加到对话中

    服务/组/ add_user_to_conversation_service.rb 根据规格测试服务:

    投机/服务/组/ add_user_to_conversation_service_spec.rb 我们现在正在开展私人和小组对话。一些细微差别仍然缺失,我们稍后会执行,但核心功能在这里。用户可以一对一沟通,或者如果他们需要,他们可以与多人建立一个完整的聊天室。

    提交更改。

    git add -A git commit -m“创建一个Group::AddUserToConversationService and test it" 信使 有一个使者的目的是什么?在移动屏幕上,而不是打开对话窗口,应用程序将加载Messenger。在更大的屏幕上,用户可以选择在哪里聊天,在对话窗口或信使上。如果信使要填满整个浏览器的窗口,通信应该更舒适。

    由于我们将使用相同的数据和模型,因此我们只需要在不同的环境中打开对话。生成一个新的控制器来处理在Messenger中打开对话的请求。

    导轨g控制器使者

    控制器/ messengers_controller.rb get_private_conversation并且get_group_conversation操作将获得用户选择的对话。这些操作的模板将会将选定的对话附加到对话占位符。每次选择新对话打开时,旧对话将被删除并替换为新选对话。

    为动作定义路线:

    的routes.rb 提交更改。

    git add -A git commit -m“创建一个MessengersController并定义路由到它的动作” 在控制器中是一个open_messenger动作。此操作的目的是从任何页面直接转到信使并呈现选定的对话。在较小的屏幕上,用户将通过Messenger而不是对话窗口进行聊天。稍后,我们将切换较小屏幕的链接,以在Messenger中打开对话。

    为该open_messenger操作创建一个模板

    信使/ open_messenger.html.erb git add -A git commit -m“在/ messengers中创建一个open_messenger.html.erb” 然后我们看到ConversationForMessengerSerivce它会检索所选对话的对象。创建服务:

    服务/ conversation_for_messenger_service.rb 添加服务规格:

    投机/服务/ conversation_for_messenger_service_spec.rb 提交更改。

    git add -A git commit -m“创建一个ConversationForMessengerSerivce and add specs for it" 为index行动创建一个模板:

    信使/ index.html.erb 这将成为信使本身。在Messenger中,我们将能够看到用户对话列表和选定的对话。创建部分文件:

    信使/索引/ _conversations_list.html.erb 定义辅助方法:

    助手/ messengers_helper.rb 尝试使用自己的规格进行测试。

    创建链接的部分文件以打开对话:

    信使/索引/ conversations_list_item / _private.html.erb

    信使/索引/ conversations_list_item / _group.html.erb 现在为会话空间创建一个部分,选定的会话将在此处呈现:

    信使/索引/ _conversation.html.erb 提交更改。

    git add -A git commit -m“为MessengersController的索引操作创建一个模板” 为get_private_conversation行动创建一个模板:

    信使/ get_private_conversation.js.erb 创建一个_private_conversation.html.erb文件:

    信使/ _private_conversation.html.erb 该文件将在信使内部呈现私人对话。另请注意,我们重复使用私人对话视图中的部分内容。创建_details.html.erb部分:

    信使/ private_conversation / _details.html.erb 提交更改。

    git add -A git commit -m“为MessengersController的 get_private_conversation动作创建一个模板” 当我们去使用Messenger时,最好不要在导航栏上看到下拉菜单。为什么?我们不想在信使内部呈现对话窗口,否则它会显得混乱。对话窗口和信使同时与同一个人聊天。这将是一个非常错误的设计。

    起初,禁止会话窗口在信使页面上呈现。这并不难。要控制它,请记住应用程序上的对话窗口是如何呈现的。它们在application.html.erb文件内呈现。然后我们有@private_conversations_windows和@group_conversations_windows实例变量。这些变量是对话数组。而不是仅仅从这些数组中提取会话,而是定义帮助方法来决定是否将这些数组提供给用户,具体取决于他们所处的页面。如果用户在Messenger的页面中,他们将获得一个空数组,并且没有会话的窗口将被渲染。

    更换这些实例变量private_conversations_windows和group_conversations_windows辅助方法。现在在里面定义它们ApplicationHelper

    助手/ application_helper.rb 用规格包装它们

    规格/助理/ application_helper_spec.rb 提交更改

    git add -A git commit -m“ 定义private_conversations_windows和帮助ApplicationHelper内部的方法并测试它们”group_conversations_windows 接下来,为导航标题创建替代部分文件,因此不会呈现下拉菜单。在里面NavigationHelper,我们已经定义了nav_header_content_partials辅助方法。它确定要渲染哪个导航头。

    在 - 的里面

    布局/导航/报头 目录,创建一个_messenger_header.html.erb文件

    布局/导航/报头/ _messenger_header.html.erb 风格的使者。messenger.scss在partials目录中创建一个文件

    资产/样式表/谐音/ messenger.scss 提交更改

    git add -A git commit -m“在部分内部创建一个messenger.scss” 里面的desktop.scss,内部的min-width: 767px,加

    资产/样式表/响应/ desktop.scss 当我们点击对话来打开它时,我们希望能够以某种方式加载先前的消息。我们可以添加一个可见的链接来加载它们。或者我们可以自动加载一些消息,直到滚动条出现,这样用户可以通过向上滚动来加载以前的消息。创建一个辅助方法,它会照顾它

    助手/共享/ messages_helper.rb 用您自己的规格进行测试。创建部分文件

    共享/ load_more_messages /信使/ _load_previous_messages.js.erb

    共享/ load_more_messages /信使/ _remove_previous_messages_link.js.erb 提交更改

    git add -A git commit -m“在 Shared :: MessagesHelper中定义一个autoload_messenger_messages ” 在_load_more_messages.js.erb 文件正上方使用helper方法<%= render remove_link_to_messages %>

    私人/消息/ _load_more_messages.js.erb 现在我们有append_previous_messages_partial_path和
    replace_link_to_private_messages_partial_path辅助方法,我们应该更新,以使它们与信使兼容

    助手/共享/ messages_helper.rb 创建一个缺失的部分文件

    共享/ load_more_messages /信使/ _append_messages.js.erb 更新另一种方法

    佣工/私营/ messages_helper.rb 创建部分文件

    私人/消息/ load_more_messages /信使/ _replace_link_to_messages.js.erb 用你自己的规格测试助手方法。

    提交更改

    git add -A git commit -m“

    • 更新Private :: MessagesHelper”append_previous_messages_partial_path helper method in Shared::MessagesHelper
    • Update the replace_link_to_private_messages_partial_path method in

      现在,在初始加载消息链接点击后,应用程序将自动继续加载之前的消息,直到消息列表中出现滚动条。要进行初始点击,请添加一些JavaScript:

    资产/ Java脚本/ messenger.js 当你访问/messenger路径时,你会看到信使:

    然后你可以打开你的任何对话。

    提交更改。

    git add -A git commit -m“创建一个messenger.js” 现在在较小的屏幕上,当用户点击导航栏的链接打开对话时,他们的对话应该在Messenger中打开,而不是在对话窗口中打开。为了做到这一点,我们必须为小屏幕创建不同的链接。

    在导航的_private.html.erb部分内部,存储打开私人对话的链接,为较小的屏幕设备添加其他链接。将该链接添加open_private_conversation_path到文件中路径链接的下方

    布局/导航/报头/下拉菜单/会话/ _private.html.erb 在较小的屏幕上,将显示该链接而不是以前的链接,专用于较大的屏幕。添加其他链接以打开组对话

    布局/导航/报头/下拉菜单/会话/ _group.html.erb 我们在不同的屏幕尺寸上看到不同链接的原因是之前我们已经为CSS bigger-screen-link和smaller-screen-link类设置了CSS 。

    提交更改。

    git add -A git commit -m“在 布局/导航/标题/下拉菜单/对话中,在_private.html.erb和_group.html.erb内部, 为更小的设备添加替代链接以打开对话” Messenger在台式机和移动设备上的版本会有所不同。在里面写一些JavaScript messenger.js,所以在用户点击打开对话后,js将决定是否显示移动版本。

    资产/ Java脚本/ messenger.js 现在,当您在移动设备上打开对话时,看起来像这样

    提交更改。

    git add -A git commit -m“将JavaScript添加到messenger.js以 在移动设备上显示不同的Messenger版本” 现在让群组对话在信使上起作用。使用Messenger的大部分工作已经完成,因此设置群组对话将变得更容易。如果你回头看看MessengersController,我们有这个get_group_conversation动作。为它创建一个模板文件:

    信使/ get_group_conversation.js.erb 然后创建一个文件在信使中呈现群组对话:

    信使/ _group_conversation.html.erb 创建其部分:

    信使/ group_conversation / _details.html.erb

    信使/ group_conversation / _new_message_form.html.erb 提交更改:

    git add -A git commit -m“ 在信使内部创建一个get_group_conversation.js.erb模板及其部分” 这就是使者中的群组对话的外观:

    5.通知 该应用程序已经具备了所有基本功能。在本节中,我们将把精力放在增强这些重要功能上。当其他用户试图与您联系时,即时通知可提供更好的用户体验。让我们让用户知道他们何时获得联系请求更新或加入群组对话。

    联系请求 生成一个处理所有用户通知的通知通道。

    导轨g通道通知

    信道/ notification_channel.rb 提交更改。

    git add -A git commit -m“创建一个NotificationChannel” 每个用户都将拥有自己独特的通知渠道。然后我们有ContactRequestBroadcastJob,这将广播联系请求和答复。

    生成工作。

    rails g工作contact_request_broadcast

    工作/ contact_request_broadcast_job.rb 创建一个_contact_request.html.erb部分,用于在导航栏的下拉菜单中添加联系人请求。在这种情况下,我们将动态地添加这些请求ContactRequestBroadcastJob

    联系人/ _contact_request.html.erb 每次Contact创建新记录时启动作业:

    车型/ contact.rb 提交更改。

    git add -A git commit -m“创建一个ContactRequestBroadcastJob” 然后在导航栏上创建一个下拉菜单:

    布局/导航/报头/下拉菜单/ _contact_requests.html.erb 定义nav_contact_requests_partial_path辅助方法:

    助手/ navigation_helper.rb 用规范包装该方法,然后创建部分文件:

    布局/导航/报头/下拉菜单/ contact_requests / _requests.html.erb

    布局/导航/报头/下拉菜单/ contact_requests / _no_requests.html.erb 在_dropdowns.html.erb文件内部,呈现_contact_requests.html.erb对话下面的对话框。因此,我们可以在导航栏上看到联系人请求的下拉菜单

    布局/导航/报头/ _dropdowns.html.erb 提交更改。

    git add -A git commit -m“

    • 在 layouts / navigation / header / dropdowns 里面创建一个_contact_requests.html.erb
    • 定义一个nav_contact_requests_partial_path in NavigationHelper" 还为单个联系人请求创建部分文件:

    布局/导航/报头/下拉菜单/ _request.html.erb 提交更改。

    git add -A git commit -m“在 layouts / navigation / header / dropdowns中创建一个_request.html.erb ” 将CSS添加到样式并定位联系请求的下拉菜单:

    资产/样式表/谐音/布局/ navigation.scss 提交更改。

    git add -A git commit -m“在navigation.scss中添加CSS以设置 联系人请求的下拉菜单的样式和位置” 在导航栏上,我们现在可以看到联系请求的下拉菜单。

    我们有通知渠道和工作广播联系请求的更新。现在我们需要在客户端创建连接,以便用户可以实时发送和接收数据。

    资产/ Javascript角/信道/ notification.js 注意if ,在接受请求被拒绝的情况下,语句有空的代码块。你可以在这里玩耍并添加你自己的代码。

    还要创建一个contact_requests.js文件,以在某些事件发生后执行DOM更改,并使用contact_request_response回调函数向对方用户广播执行的操作

    资产/ Java脚本/ contact_requests.js 在对话窗口发出新的联系请求后,请删除重新发送请求的选项。在对话options.js文件中,添加以下内容:

    资产/ Java脚本/交谈/ options.js 现在,联系人请求将实时处理,用户界面将在特定事件发生后更改。

    感谢 Toni Shortsleeve。 Ruby on Rails程序设计Web开发软件开发启动 一个拍手,两个拍手,三个拍手,四十个? 通过鼓掌或多或少,您可以向我们表明哪些故事真正脱颖而出。

    845 19 跟随 转到Domantas G的个人资料 Domantas G sciencetone.com的创建者

    跟随 freeCodeCamp freeCodeCamp 我们的社区发布值得关于开发,设计和数据科学的故事。

    更多来自freeCodeCamp 如何训练AI将您的设计模型转换为HTML和CSS 转到EmilWallnér的个人资料 埃米尔沃尔内尔

    5.3K

    也标记为Web开发 我如何(重新)建立中等拍手效果 - 以及我从实验中得到的结果。 转到Ohans Emmanuel的个人资料 Ohans Emmanuel

    107K

    也标记了Startup 想要成为一个百万富翁?立即做这15件事。 转到Benjamin P. Hardy的个人资料 本杰明P.哈代

    36K

    回应 魏晓 写回应... 魏晓 Domantas G的鼓掌(作者) 转到Paul Gaumer的个人资料 保罗·高梅 2017年12月19日 一个字:尊重!

    15

    Domantas G的鼓掌(作者) 转到Diego van Dyk的个人资料 Diego van Dyk 2017年12月19日 伙计,这真棒!恭喜!

    8

    Domantas G的鼓掌(作者) 转到Debbie Jong的个人资料 黛比钟 1月26日 感谢你这个真棒详细的教程!

    只是一个注释,看起来像factory_girl gem已被重命名为factory_bot,所以我不得不在整个文件中更改名称以使其工作。(当我尝试使用它时,不断收到错误消息“The factory_girl gem is deprecated”)

    阅读更多…

    显示所有回复

    845

    19 下一个故事 在开始之前 - 如何避免错误输入用户电子邮件

    在本教程中,我将从vanilla操作系统安装到下载我们推荐的特定软件(如PostgreSQL,Redis和Git Bash)。

    [作者注意:我在几年前编写了本系列中的首批几十个教程,我正在更新内容以反映业界最佳实践的发展。请评论,如果你看到任何我错过了应该更新。谢谢!]

    在开始之前,我强烈建议您不要执行下面的教程,而是双启动到Ubuntu并按照本教程进行设置。

    如果你宁愿忽略这个警告,那么假设你有一个新版本的Windows(即这应该在8以上),下面是我建议你采取的步骤:

    (1)下载并安装Chrome

    (2)下载并安装Git,“官方Git for Windows xxx的完整安装程序”,其中xxx是您看到的最高版本。

    (3)在此处下载“开发工具包” 并将文件解压缩到c:/ DevKit,然后在同一页上下载并安装最新的Ruby 2.xx版本(页面顶部的“RubyInstallers”部分)。首先安装开发工具包非常重要。

    (4)下载并安装RubyGems

    (5)下载并安装Node.js(运行msi安装程序)

    (6)下载并安装PostgreSQL(9.x.x +适用于您的适用版本的Windows,64位),并在安装过程中选择默认选项(并在最后安装StackBuilder时选择yes,但不要现在不需要安装任何东西,以便关闭它)。

    (7)下载并安装适用于您的Windows版本的redis二进制文件。

    (8)抓住Firefox,Opera和Safari进行测试。

    (9)使用Sublime作为你的代码编辑器。

    (10)打开你的“Git Bash”程序(开始>所有程序> Git> Git Bash)并进入

    git config -global user.name“FIRST_NAME LAST_NAME” 接着

    git config -global user.email“[email protected]” ...填写你的姓名和电子邮件。

    (11)在Git中的Bash,进入六〜/ .bash_profile中,然后按我进入插入模式,然后粘贴在该行的文件中:

    export PATH =“/ c / DevKit / bin:/ c / DevKit:/ c / Program Files / PostgreSQL / 9.2 / bin:$ PATH ” 查看 由GitHub托管的原始bash_profile_windows_example.sh ...正确设置PATH变量。然后按下escape,然后 :wq然后输入保存(恭喜,您刚刚了解了一下关于unix vi编辑器)。

    (12)打开一个新的Git Bash终端,然后通过输入ssh-keygen并遵循所有默认值(不要输入密码,只需按Enter 键)来生成ssh公钥。然后您可以输入cat〜/ .ssh / id_rsa.pub来列出您的公钥,您需要使用它来访问远程代码存储库。

    (13)使用pgAdmin III工具创建一个用户(打开该工具,右键单击并连接到9.2服务器,右键单击并创建一个用户登录角色 - 确保选择允许它的选项一个超级用户并创建数据库,并确保设置密码,否则以后连接到它时会出现问题)。

    而已!您现在已经准备好在Rails代码的git存储库中进行克隆(或者开始自己的)。确保你的database.yml文件具有你的开发和测试数据库的用户名和密码,以匹配你在你的pgAdmin工具中创建的内容。

    • -

    加入Basecamp成为我们新的Rails程序员 Basecamp正在招聘!我们有一个罕见的开放,让Rails程序员在我们的全科医疗团队中开展新产品开发。几年来,我们还没有开始这种工作,所以我们很高兴地欢迎有人加入这个团队!

    这是一位有经验的Rails程序员的职位,但您不必是摇滚明星,忍者或超级英雄才能申请。事实上,如果你在这些类别中自我识别,我们宁愿你不要!

    我们正在寻找一位具有良好业绩记录的人,让Rails工作并将产品带入生活。这不是初级职位,但是,到处都是冒名顶替者,这对你来说是可行的。如果您运送稳定的工作,您将获得我们正在寻找的经验。

    我们希望来自不同背景,经验和身份的强大多样的团队。我们随时准备为正在进行的工作打造一个包容性的,支持性的地方,为您做好您职业生涯中的最佳工作。开始时每周工作时间不超过40小时,每晚睡眠时间超过8小时。我们的工作场所和我们的优势旨在支持与您工作的可持续,健康的关系。

    今天,我们的团队从遍布6个国家的32个不同城市开展工作。只要您的正常工作时间与芝加哥时间(CST / UTC-6)重叠4小时以上,您就可以在世界任何地方工作。游牧民族欢迎。

    关于工作 Basecamp的全科医疗小组按照Big Batch或Small Batch模式定期进行6周周期的节奏。我们的功能团队很小。您通常会与一位设计师,有时是另一位程序员以及通常的测试人员一起工作。

    这只是少数人希望在6周内定期发布一个大功能或在一两周内发布一个小功能。这是一个快速的步伐,但它从来没有疯狂。我们没有时间进行干练,匆忙的工作。我们重视一个冷静的公司,并且刻意协调努力。我们在这里工作40个小时(夏季更少!)。对于在80小时以上的马拉松中茁壮成长的工作狂英雄来说,这不是一份工作。不!

    我们的公式:有能力的人留下在合理的时间内完成伟大的工作,尽量避免分心。

    当然,您将得到业务中一些最好的Rails程序员的全力支持。我们字面上写了框架。这里的每个人都热衷于帮助和支持新人成为团队的一员,并最终做好自己职业生涯中的最佳工作。

    虽然为Basecamp 3创建新功能主要是绿地工作,但我们的平台上也有相当一部分遗留义务。我们创建的第一个Rails应用程序仍在运行并为满意的客户提供服务。您可以在Basecamp的第一版或任何其他我们不再销售但仍深受支持的产品上工作。我们珍惜我们的遗产。当“git blame”显示12岁或以上的线时,请重视😀。

    您将帮助我们直接支持客户。Basecamp的每个人都会每隔几个月参加支持Everyone的人员,并且您会定期帮助处理升级的技术问题。

    我们也是开源社区的坚定支持者。不仅仅是通过Rails,还有很多更小的项目,包括JavaScript中的很多。我们鼓励Basecamp的每位程序员回馈并分享我们的工具。

    关于你 在广泛的笔触中,一个管理者在Basecamp茁壮成长。我们致力于多面手,热心的学习者,有责任心的工作人员和策展人。我们很快相信。我们看到了一切。我们彼此善良,彼此尊重,彼此支持。我们一起实现。我们是同事,在这里做我们最好的工作。

    我们都是完全不同的人(我们绊倒,跌倒,伸手可及,就像任何人一样!)但这些都是我们分享的基本态度。什么漂浮你的船?什么在你身上点燃了火焰?什么让它燃烧?

    我们并不是在寻找意识形态的克隆,但我们正在寻找那些分享我们关于如何编写好软件的基本价值观和信念的人。它可以帮助您识别为软件作者。如果你关心写简洁,简洁的代码。如果一个雄伟的巨石的想法吸引你。如果你寻求震中。如果你说不。

    作为一名经验丰富的Rails开发人员,您应该熟悉框架,Ruby以及全栈Web开发的稳定版:HTTP,JavaScript,CSS,HTML,SQL。如果您广泛熟悉其他语言,这也是一大优势 - 我们在Swift中编写iOS应用程序,在Kotlin编写Android应用程序,并使用Go编写工具 - 但您的主要工作将是Ruby。我们❤️Ruby,如果现在还不清楚😄。

    福利与补偿 我们的薪酬处于前5% - 或更好! - 以芝加哥为基础的角色和经验的行业。无论你住在哪里。另外,两年之后,您将参与我们的利润增长分享计划。

    我们在Basecamp的好处是帮助您过上健康的生活。虽然我们在芝加哥有一个可爱的办公室,但您不会在这里找到桌上足球桌不断旋转,付费午餐或公司用来吸引员工长时间工作的其他任何服饰。

    工作可以等待。我们的福利包括4天夏季周,每年带薪休假,每3年休假一个月,CSA,健身,按摩和继续教育津贴。我们拥有顶级健康保险和一项慷慨比赛的退休计划。查看完整列表。

    如何申请 请发送一个适合这个职位的应用程序,与我们联系。作为一个同事介绍自己。告诉我们未来。

    我们重视伟大的作家,所以请花时间与应用程序。忘记通用简历。第一个提交没有奖品!

    我们希望看到您编写的软件的例子。实际的代码。我们感谢您在开发商业软件时可能很难分享代表性样本,所以您可以共同研究的任何内容都会很好。如果您有开源贡献,那么这些人就是很好的候选人,但您不一定要成为开源应用的贡献者。

    你可以在GitHub上分享私人回购@dhh,@packagethief,@sstephenson和@jeremy。他们将是你在编程方面的温和善良的评估者。

    去吧! 我们正在接受此职位的申请,直到2017年2月27日。我们会通知您我们已收到您的申请。之后,在申请截止日期过后,您可能不会期望收到我们的回复。我们希望给每个人公平的申请和评估机会。

    正如介绍中提到的,我们渴望组建一个更多元化的团队。事实上,我们并不害怕对Basecamp中代表性不足的候选人给予额外的重视。

    我们迫不及待想听到您的消息!

    (再说一遍,冒名顶替者:我们也是,加油,加油。)

    results matching ""

      No results matching ""