简单的Rails功能指南

我最近制作了我的第一个Ruby on Rails应用程序-以下是我用来使其工作的一些资源和策略,包括:

  • OAuth登录/注册(Google)
  • 授权助手和控制器方法( current_userlogged_inauthorize(user) ,呈现403错误)
  • 多态ActiveRecord关系(关注用户,消息和对帖子的反应)
  • 复杂的ActiveRecord类方法(最受欢迎的帖子)
  • 设置Bootstrap(与Rails的表单一起使用)
  • 通过用户输入渲染Markdown( kramdown设置, rouge语法突出显示,自定义sanitize

Google认证

[Google OAuth gem](https://github.com/zquestz/omniauth-google-oauth2)

如果您需要用来查询用户的唯一属性,或者想要使用Google API的更高级功能(并允许脱机刷新令牌),则可以向user表添加google_uid列和google_refresh_token 。 因为我具有用户email的唯一性验证,并且仅使用Google进行身份验证,所以我不需要这些列,但无论如何都添加了它们,以防万一我将来进行设计更改。

在我的模式中,我使useremail验证唯一性,以便使用Google登录将检查该电子邮件的现有帐户。 如果找到,则您将登录到该帐户(使用更新的google_uid且未更改密码),如果未找到,它将创建一个新帐户。
注意:要使此方法变得万无一失,如果帐户是传统帐户(即不使用OAuth),请务必验证用户的电子邮件,这一点很重要。

另外,您需要执行专门用于处理OAuth回调的操作。 该操作需要与您在Google API页面中指定的回调路由相关联(指向该页面的链接位于上面链接的Google OAuth gem的GitHub上)。 我在routes.rb文件中定义的回调的自定义路由为: get 'auth/google_oauth2/callback, to: 'sessions#googleAuth'

我在SessionsController回调操作利用了用User模型编写的自定义类方法,该方法将OAuth流程的返回值传递给了该方法,如下所示:

从那里,您只需检查用户是否有效,如果有效则登录他们,否则显示错误。

注意: RandomPasswordStrategy只是我使用的类,它使用sysrandom/securerandom方法SecureRandom.hex(64)结合所需符号和数字的随机排序(根据密码策略的要求)来创建复杂的有效随机密码。

授权方法,错误页面

我在ApplicationController中放置了多个私有方法,以在整个应用程序中抽象出身份验证,从而更容易以正确的方式对用户进行身份验证,并在出现问题时向他们显示适当的消息。

我希望注销的用户能够看到大部分应用程序,但将某些方面限制为仅具有帐户的用户可以访问。 另外,我想确保只有所有者才能编辑/删除他们的帖子,并以他们的名字发布新帖子。 另外,我希望某些页面根据用户是否登录而显示不同。

为了帮助以模块化和简单的方式执行这些任务,我向ApplicationController添加了两个方法,以便它们对所有Controller(从ApplicationController继承)都可用,并在必要时将它们添加为helper_methods以使其在视图中可用:

这些文件主要用作某些页面上显示内容的决策者,或用作更高级授权方法的基础。

如果未经授权的用户尝试访问您不希望他们访问的页面,则最好显示403错误页面。 通过创建public/403.html.erb文件,并通过ApplicationController另一个方法调用它,可以轻松实现此目的。

可以接受自定义Flash消息作为参数,并且可以作为其他方法的良好构建块,例如:

如果在没有用户参数的情况下调用authorize ,则仅当用户未登录时才会显示403错误页面。如果使用用户参数(不为null )进行调用,则除非该特定用户为403,否则将调用403。已登录。它还返回一个布尔值以指示成功或失败。

注意:如果在调用authorize之后需要在控制器中使用current_user ,则在授权失败时会出现错误。 解决此问题的一种简单方法是将if-else块与授权检查一起使用,而不是将其用作控制器操作顶部的独立功能。 这样,除非授权成功,否则将不会运行任何调用current_user代码;如果授权失败,则一旦控制器操作完成,它将呈现403错误页面。

关注用户,发送消息,对帖子做出反应,范围方法

对于某些关系,ActiveRecord关系不像has_many :classes, through: :user_classes

特别是三种情况,我必须变得更有创造力才能工作:

关注其他用户:

  • 多对多关系,即,一个用户正在关注许多用户,并被许多用户关注。
  • 这个问题的答案只是一个简单的联接表,但是它与标准联接表略有不同,因为它将一个表联接到自身,并且在ActiveRecord类方法中需要一些额外的单词。 我使用的联接表是:

然后使用户模型正常工作:

讯息传递

  • 这与实现跟随者/跟随者非常相似,不同的是模型Message是联接表,也是我们感兴趣的模型,因此只是:

对帖子做出反应

有一些解决该问题的方法是可行的,但是我决定创建一个数据库表reaction_types ,它对任何可reaction_types事物都具有多对多的关系,在我的案例和topicsreactablesreaction_types之间的reactables表。 我这样做不是代替通过字符串保存反应类型的反应,以最大程度地减少错误并提供灵活性-例如,将来可以轻松扩展允许的reaction-types

这样, reactions使userreactablesreaction_types之间成为3向reactables表。 必须将reaction_types种子化为您希望用户可以使用的类型。 我选择likedislikegeniusreport

您可以使用多态关系以相同的方式创建可附加到可taggable对象的标记,并将回复张贴到taggable对象上。

先进的ActiveRecord类方法

当我尝试使用正确的ActiveRecord类方法来检索用户仪表板的特定“统计信息”或为我的主页查找热门主题时,我发现最好的资源是查看其他高级特定类方法并使用它们实例作为参考。 我将把我的一些放在这里,希望其他人可以将其用作参考。

要为我的主页创建当天的“焦点话题”,请选择过去24小时内反应最积极的话题:

查找由特定User对特定类型的反应最多的Topic 。 您可以使用它来添加到他们的仪表板,以便他们可以看到他们最liked帖子,例如:

设置引导程序

[这篇文章](https://medium.freecodecamp.org/add-bootstrap-to-your-ruby-on-rails-project-8d76d70d0e3b)逐步介绍了如何在几分钟内使用引导程序设置Rails应用程序。 引导程序有一个复杂的问题,即不是“开箱即用”的理想方法:当表单输入出现问题时,rails会自动为您的form_for字段提供fields_with_errors类,而Bootstrap不会对此做出响应。 相反,它响应类is-invalid
– [此博客](https://jasoncharnes.com/bootstrap-4-rails-fields-with-errors/)显示了一个很好的可行解决方案,可以使表单错误与引导程序一起很好地工作。 它只包括向config/initializers文件夹中添加文件和代码,并且基本上所做的就是将默认field-with-errors类更改is-invalid ,这是引导程序用来指示错误填写的字段。

渲染降价

我介于两个图书馆kramdownkramdown 。 我最终选择了[kramdown](https://github.com/gettalong/kramdown),因为:

  • 它是最近提交的,似乎维护得更多
  • 它的受欢迎程度在增加,而红redcarpet在减少
  • 它允许与渲染LaTex方程的MathJax集成。
  • 获得基本集成相对简单。 要实现以下两个目标变得有些复杂:
  • →突出显示代码的语法
  • →能够清理用户的输入,同时允许所有Markdown功能正确实施。

我使用[rouge](https://github.com/jneen/rouge)进行语法突出显示。 我将向您展示下面的代码,以使其与Kramdown一起使用,但是要查找的难点信息是如何获取正确的CSS文件,以使突出显示发生。 这是一个很难找到的好[堆栈溢出答案](https://stackoverflow.com/questions/43905103/kramdown-rouge-doesnt-highlight-syntax)。 基本上,一旦告诉kramdown您要使用rouge (并且同时安装了kramdown gemrouge gem ),就可以在终端中运行rougify help style ,并且可以看到可以添加的所有自定义CSS文件。到您的app/assets/stylesheets路径。 要获取原始CSS,请在终端中键入rougify style然后键入允许的样式之一。 例如: rougify style colorful 。 CSS将被打印在您的终端中。 你也可以跑

 丰富多彩的样式化> ./app/assets/stylesheets/rouge_style.css 

现在,降价促销相对容易。 我做了一个辅助方法,使其变得更加简单:

自定义消毒方法:

如您在这里看到的,我没有使用raw.html_safe呈现此HTML数据,因为最终它来自用户并且无法信任 。 但是,安全sanitize方法不允许某些我想呈现的东西,例如表格。 您可以通过执行如下所示的操作,手动添加到通过`sanitize`允许的白名单标签中,从而获得适当的卫生和所需的HTML标签。

一般提示

  • 使用PostgreSQL设置应用程序 [这里是博客文章](https://medium.com/@micah.shute/setting-up-windows-subsystem-for-linux-wsl-6346ff23b8bb)我写过有关设置WSL的信息,但是底部有一个部分介绍了如何使用pgAdmin和使用PostgreSQL设置Rails应用程序
  • 将所有密钥保存为我使用[Figaro](https://github.com/laserlemon/figaro)来简化的环境变量
  • 避免N + 1问题当您获得要查询并显示嵌套模型的模型集合时,会发生这种情况。 如果您要遍历模型n次来执行此操作,那么您将进行n + 1次数据库调用,这对于大量数据而言可能是非常昂贵的,尤其是在通过网络请求时。 进行初始查询时,可以通过使用includes方法轻松解决此问题。 [查看此站点](https://guides.rubyonrails.org/active_record_querying.html)并转到“解决N + 1个查询问题的方法”部分以获取更多信息。
  • 在销毁对象时自动清理数据库在向ActiveRecord类方法中适当地添加dependent: :destroy (示例可以在上面的代码段中看到)之后,您要告诉ActiveRecord在销毁模型时销毁这些关系。 如您在上面看到的,我在post.rb实现了此功能。 这告诉Rails, post被销毁时,所有用户对此的reactions也应被销毁。 这可以防止无缘无故的喜欢和不喜欢的事物等在您的数据库中随意浮动。 另外,请注意,这应该是单方面的关系。 如果用户破坏了一个post ,您就不会希望该post被销毁。
  • 添加自定义文件和类在MVC之外,您可能希望应用程序执行某些操作。 这意味着您将要添加标准`model`,`view`和`controller`目录之外的文件。 以下是一些有关如何执行此操作的建议的资源:

→[一个StackOverflow答案](https://stackoverflow.com/questions/15260984/guidelines-for-where-to-put-classes-in-rails-apps-that-dont-fit-anywhere)

→[一个GitHub要点文章](https://gist.github.com/maxim/6503591)

就我个人而言,我在我的app目录中使用了一个lib目录,因为它渴望在生产环境中加载,而在开发中则是延迟加载。 对于该目录中文件所引用的类,我不需要更改任何配置或环境文件。