Rails 4:辅助方法在本地工作,在 Heroku 上中断

Rails 4: helper method working locally, breaking on Heroku

我有一个 Rails 4 应用程序,带有一个 Post 模型,其中包含一个自定义 :copy 属性。

,我在 posts_helper.rb 中创建了以下方法,以在 :copy 的内容中为链接、主题标签和提及添加特定样式:

def link_highlight(string)
    string.gsub!(/((https|http)?:\/\/[\S]+)/, '<span class="highlight"></span>')
  end

  def hashtag_highlight(string)
    string.to_s.gsub!(/\S*#(\[[^\]]+\]|\S+)/, '<span class="highlight">#</span>')
  end

  def mention_highlight(string)
    string.to_s.gsub!(/\B(\@[a-z0-9_-]+)/i, '<span class="highlight"></span>')
  end

  def new_highlight(string)
    link_highlight(string)
    hashtag_highlight(string)
    mention_highlight(string)
  end

然后,在我的 Calendars#Show 视图中,我显示 :copy 属性的内容,我有:

<%= raw new_highlight(post.copy) %>

——————

更新:我也曾尝试将 raw 方法从视图移动到助手,但仍然得到相同的结果。

——————

这在本地完美运行:

然而,一旦我部署到 Heroku,我应该有 :copy 属性的内容,我什么都没有。

我没有收到任何错误消息。

这是我的 Heroku 日志:

2015-10-22T22:14:32.177739+00:00 heroku[slug-compiler]: Slug compilation finished
2015-10-22T22:14:33.045814+00:00 heroku[web.1]: Starting process with command `bundle exec puma -C config/puma.rb`
2015-10-22T22:14:36.100952+00:00 app[web.1]: [3] Puma starting in cluster mode...
2015-10-22T22:14:36.100980+00:00 app[web.1]: [3] * Version 2.13.4 (ruby 2.0.0-p645), codename: A Midsummer Code's Dream
2015-10-22T22:14:36.100981+00:00 app[web.1]: [3] * Min threads: 5, max threads: 5
2015-10-22T22:14:36.100981+00:00 app[web.1]: [3] * Environment: production
2015-10-22T22:14:36.100982+00:00 app[web.1]: [3] * Process workers: 2
2015-10-22T22:14:36.100982+00:00 app[web.1]: [3] * Preloading application
2015-10-22T22:14:37.981682+00:00 heroku[web.1]: Starting process with command `bundle exec puma -C config/puma.rb`
2015-10-22T22:14:39.407860+00:00 app[web.1]: [3] * Listening on tcp://0.0.0.0:52687
2015-10-22T22:14:39.408079+00:00 app[web.1]: [3] Use Ctrl-C to stop
2015-10-22T22:14:39.424709+00:00 app[web.1]: [3] - Worker 0 (pid: 6) booted, phase: 0
2015-10-22T22:14:39.434794+00:00 app[web.1]: [3] - Worker 1 (pid: 11) booted, phase: 0
2015-10-22T22:14:44.770104+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2015-10-22T22:14:46.225951+00:00 app[web.1]: [3] - Gracefully shutting down workers...
2015-10-22T22:14:47.033061+00:00 app[web.1]: [3] === puma shutdown: 2015-10-22 22:14:47 +0000 ===
2015-10-22T22:14:47.033068+00:00 app[web.1]: [3] - Goodbye!
2015-10-22T22:14:48.119725+00:00 heroku[web.1]: Process exited with status 0
2015-10-22T22:15:09.137041+00:00 heroku[web.1]: Starting process with command `bundle exec puma -C config/puma.rb`
2015-10-22T22:15:13.024358+00:00 app[web.1]: [3] Puma starting in cluster mode...
2015-10-22T22:15:13.024410+00:00 app[web.1]: [3] * Version 2.13.4 (ruby 2.0.0-p645), codename: A Midsummer Code's Dream
2015-10-22T22:15:13.024430+00:00 app[web.1]: [3] * Min threads: 5, max threads: 5
2015-10-22T22:15:13.024454+00:00 app[web.1]: [3] * Environment: production
2015-10-22T22:15:13.024479+00:00 app[web.1]: [3] * Process workers: 2
2015-10-22T22:15:13.024502+00:00 app[web.1]: [3] * Preloading application
2015-10-22T22:15:16.803059+00:00 app[web.1]: [3] * Listening on tcp://0.0.0.0:30586
2015-10-22T22:15:16.803071+00:00 app[web.1]: [3] Use Ctrl-C to stop
2015-10-22T22:15:16.818204+00:00 app[web.1]: [3] - Worker 1 (pid: 10) booted, phase: 0
2015-10-22T22:15:16.823176+00:00 app[web.1]: [3] - Worker 0 (pid: 6) booted, phase: 0
2015-10-22T22:15:17.269140+00:00 heroku[web.1]: State changed from starting to up
2015-10-22T22:15:19.171926+00:00 app[web.1]: Started GET "/" for 66.249.88.82 at 2015-10-22 22:15:19 +0000
2015-10-22T22:15:19.325329+00:00 app[web.1]:    (2.9ms)  SELECT COUNT(*) FROM "users"
2015-10-22T22:15:19.342732+00:00 app[web.1]:    (2.8ms)  SELECT COUNT(*) FROM "posts"
2015-10-22T22:15:19.352489+00:00 app[web.1]:   Rendered layouts/_home_header.html.erb (4.9ms)
2015-10-22T22:15:19.357628+00:00 app[web.1]:   Rendered layouts/_cta.html.erb (0.6ms)
2015-10-22T22:15:19.305513+00:00 app[web.1]: Processing by PagesController#home as HTML
2015-10-22T22:15:19.334229+00:00 app[web.1]:    (3.6ms)  SELECT COUNT(*) FROM "calendars"
2015-10-22T22:15:19.345627+00:00 app[web.1]:   Rendered pages/home.html.erb within layouts/homepage (34.5ms)
2015-10-22T22:15:19.355907+00:00 app[web.1]:   Rendered layouts/_footer.html.erb (2.2ms)
2015-10-22T22:15:19.358397+00:00 app[web.1]: Completed 200 OK in 53ms (Views: 31.6ms | ActiveRecord: 18.2ms)
2015-10-22T22:15:19.361256+00:00 heroku[router]: sock=client at=warning code=H27 desc="Client Request Interrupted" method=GET path="/" host=calendy.herokuapp.com request_id=258aefce-534f-4612-b3df-ba4930bca1d9 fwd="24.205.62.204,66.249.88.82" dyno=web.1 connect=0ms service=192ms status=499 bytes=6532
2015-10-22T22:15:20.171154+00:00 app[web.1]: Started GET "/" for 24.205.62.204 at 2015-10-22 22:15:20 +0000
2015-10-22T22:15:20.310024+00:00 app[web.1]: Processing by CalendarsController#index as HTML
2015-10-22T22:15:20.219029+00:00 app[web.1]:   User Load (3.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =   ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
2015-10-22T22:15:20.491337+00:00 app[web.1]:   Calendar Load (3.1ms)  SELECT "calendars".* FROM "calendars" INNER JOIN "administrations" ON "calendars"."id" = "administrations"."calendar_id" WHERE "administrations"."user_id" =   [["user_id", 1]]
2015-10-22T22:15:20.727624+00:00 app[web.1]:   Comment Load (4.2ms)  SELECT "comments".* FROM "comments" INNER JOIN "posts" ON "comments"."post_id" = "posts"."id" INNER JOIN "calendars" ON "posts"."calendar_id" = "calendars"."id" INNER JOIN "administrations" ON "calendars"."id" = "administrations"."calendar_id" WHERE "administrations"."user_id" =  AND ("comments"."user_id" != )  ORDER BY created_at DESC  [["user_id", 1], ["user_id", 1]]
2015-10-22T22:15:20.813360+00:00 app[web.1]:   Post Load (2.8ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" =  LIMIT 1  [["id", 39]]
2015-10-22T22:15:20.716275+00:00 app[web.1]:    (5.5ms)  SELECT COUNT(*) FROM "comments" INNER JOIN "posts" ON "comments"."post_id" = "posts"."id" INNER JOIN "calendars" ON "posts"."calendar_id" = "calendars"."id" INNER JOIN "administrations" ON "calendars"."id" = "administrations"."calendar_id" WHERE "administrations"."user_id" =  AND ("comments"."user_id" != )  [["user_id", 1], ["user_id", 1]]
2015-10-22T22:15:20.907612+00:00 app[web.1]:   Calendar Load (1.3ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" =  LIMIT 1  [["id", 2]]
2015-10-22T22:15:20.901873+00:00 app[web.1]:   User Load (2.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  LIMIT 1  [["id", 2]]
2015-10-22T22:15:20.911719+00:00 app[web.1]:   Post Load (1.3ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" =  LIMIT 1  [["id", 17]]
2015-10-22T22:15:20.916169+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  LIMIT 1  [["id", 2]]
2015-10-22T22:15:20.919457+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" =  LIMIT 1  [["id", 3]]
2015-10-22T22:15:20.924117+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  LIMIT 1  [["id", 2]]
2015-10-22T22:15:20.922513+00:00 app[web.1]:   Post Load (1.3ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" =  LIMIT 1  [["id", 12]]
2015-10-22T22:15:20.927020+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" =  LIMIT 1  [["id", 3]]
2015-10-22T22:15:20.928461+00:00 app[web.1]:   Rendered calendars/index.html.erb within layouts/calendars (477.2ms)
2015-10-22T22:15:20.936844+00:00 app[web.1]:   Rendered layouts/_app_footer.html.erb (0.6ms)
2015-10-22T22:15:20.939230+00:00 app[web.1]: Completed 200 OK in 627ms (Views: 449.5ms | ActiveRecord: 53.5ms)
2015-10-22T22:15:20.939775+00:00 heroku[router]: at=info method=GET path="/" host=calendy.herokuapp.com request_id=185b8006-2a24-4c46-ab7a-a54dfd28426a fwd="24.205.62.204" dyno=web.1 connect=0ms service=774ms status=200 bytes=6085
2015-10-22T22:15:20.891430+00:00 app[web.1]:   Calendar Load (1.7ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" =  LIMIT 1  [["id", 3]]
2015-10-22T22:15:20.909413+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  LIMIT 1  [["id", 2]]
2015-10-22T22:15:20.905320+00:00 app[web.1]:   Post Load (1.5ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" =  LIMIT 1  [["id", 36]]
2015-10-22T22:15:20.914656+00:00 app[web.1]:   Calendar Load (2.0ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" =  LIMIT 1  [["id", 4]]
2015-10-22T22:15:20.918590+00:00 app[web.1]:   Post Load (1.4ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" =  LIMIT 1  [["id", 16]]
2015-10-22T22:15:20.933923+00:00 app[web.1]:   Rendered layouts/_app_header.html.erb (3.1ms)
2015-10-22T22:15:20.920311+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  LIMIT 1  [["id", 2]]
2015-10-22T22:15:20.926179+00:00 app[web.1]:   Post Load (1.3ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" =  LIMIT 1  [["id", 10]]
2015-10-22T22:15:20.923275+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" =  LIMIT 1  [["id", 3]]
2015-10-22T22:15:20.928028+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  LIMIT 1  [["id", 2]]
2015-10-22T22:15:21.126130+00:00 heroku[router]: at=info method=GET path="/assets/application-e8cebe24aff6ef7ad69efb41d7c5711a9989222e399d255e9e837b1d885140d5.css" host=calendy.herokuapp.com request_id=5fd9e6c0-171b-4ce6-a131-0f5373e938f6 fwd="24.205.62.204" dyno=web.1 connect=0ms service=25ms status=304 bytes=93
2015-10-22T22:15:21.224378+00:00 heroku[router]: at=info method=GET path="/assets/application-6ffeee9db4d53ff7b400a1972dc1e2b2a70f00df1f241a15e6f46ebb4a960b08.js" host=calendy.herokuapp.com request_id=ef81fff1-287b-403a-aff1-34169f1d0650 fwd="24.205.62.204" dyno=web.1 connect=0ms service=2ms status=304 bytes=93
2015-10-22T22:15:21.328775+00:00 heroku[router]: at=info method=GET path="/assets/calendy-social-media-calendar-tool-logo-216edd59c104b197d08537c3e1725cc02f70fdb89f5218c6b84ca2677feb32a5.png" host=calendy.herokuapp.com request_id=5cec4773-d7a8-42a4-beac-965e8ae3638a fwd="24.205.62.204" dyno=web.1 connect=0ms service=7ms status=304 bytes=93
2015-10-22T22:15:21.427726+00:00 heroku[router]: at=info method=GET path="/logos/small_thumb/missing.png" host=calendy.herokuapp.com request_id=79728d60-fdbd-4587-8adb-71d8f1146aab fwd="24.205.62.204" dyno=web.1 connect=0ms service=4ms status=200 bytes=1390
2015-10-22T22:15:21.434150+00:00 heroku[router]: at=info method=GET path="/assets/bootstrap/glyphicons-halflings-regular-fe185d11a49676890d47bb783312a0cda5a44c4039214094e7957b4c040ef11c.woff2" host=calendy.herokuapp.com request_id=d9f5b809-806b-4ec3-a148-0413ec58b7e7 fwd="24.205.62.204" dyno=web.1 connect=0ms service=18ms status=304 bytes=93
2015-10-22T22:15:21.440134+00:00 heroku[router]: at=info method=GET path="/images/create_new_calendar.png" host=calendy.herokuapp.com request_id=04cd55fd-f830-4993-80c8-02fd7c21e98f fwd="24.205.62.204" dyno=web.1 connect=2ms service=18ms status=200 bytes=1315
2015-10-22T22:15:21.656933+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=calendy.herokuapp.com request_id=908c6fae-fa39-454c-a947-89a54dbfb8e5 fwd="24.205.62.204" dyno=web.1 connect=12ms service=58ms status=200 bytes=3885
2015-10-22T22:15:29.556393+00:00 app[web.1]: Started GET "/calendars/2" for 24.205.62.204 at 2015-10-22 22:15:29 +0000
2015-10-22T22:15:29.698319+00:00 app[web.1]: Processing by CalendarsController#show as HTML
2015-10-22T22:15:29.698341+00:00 app[web.1]:   Parameters: {"id"=>"2"}
2015-10-22T22:15:29.797049+00:00 app[web.1]:   Calendar Load (3.1ms)  SELECT  "calendars".* FROM "calendars" WHERE "calendars"."id" =  LIMIT 1  [["id", 2]]
2015-10-22T22:15:30.377005+00:00 app[web.1]:   User Load (5.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =   ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
2015-10-22T22:15:30.689275+00:00 app[web.1]:   Calendar Load (2.4ms)  SELECT  "calendars".* FROM "calendars" INNER JOIN "administrations" ON "calendars"."id" = "administrations"."calendar_id" WHERE "administrations"."user_id" =  AND "calendars"."id" =  LIMIT 1  [["user_id", 1], ["id", 2]]
2015-10-22T22:15:31.034753+00:00 app[web.1]:    (3.9ms)  SELECT COUNT(*) FROM "posts" WHERE "posts"."calendar_id" =  AND (Extract(month from date) = 10) AND (Extract(year from date) = 2015)  [["calendar_id", 2]]
2015-10-22T22:15:31.044658+00:00 app[web.1]:   Post Load (1.9ms)  SELECT "posts".* FROM "posts" WHERE "posts"."calendar_id" =  AND (Extract(month from date) = 10) AND (Extract(year from date) = 2015)  ORDER BY date ASC  [["calendar_id", 2]]
2015-10-22T22:15:31.380322+00:00 app[web.1]:   Comment Load (2.5ms)  SELECT "comments".* FROM "comments" WHERE "comments"."post_id" IN (8, 34, 35, 36, 9, 37, 38, 11)
2015-10-22T22:15:31.490695+00:00 app[web.1]:   Administration Load (2.5ms)  SELECT  "administrations".* FROM "administrations" WHERE "administrations"."user_id" =  AND "administrations"."calendar_id" =  LIMIT 1  [["user_id", 1], ["calendar_id", 2]]
2015-10-22T22:15:32.022820+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "administrations".* FROM "administrations" WHERE "administrations"."user_id" =  AND "administrations"."calendar_id" =  LIMIT 1  [["user_id", 1], ["calendar_id", 2]]
2015-10-22T22:15:32.046003+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "administrations".* FROM "administrations" WHERE "administrations"."user_id" =  AND "administrations"."calendar_id" =  LIMIT 1  [["user_id", 1], ["calendar_id", 2]]
2015-10-22T22:15:32.073869+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "administrations".* FROM "administrations" WHERE "administrations"."user_id" =  AND "administrations"."calendar_id" =  LIMIT 1  [["user_id", 1], ["calendar_id", 2]]
2015-10-22T22:15:32.098074+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "administrations".* FROM "administrations" WHERE "administrations"."user_id" =  AND "administrations"."calendar_id" =  LIMIT 1  [["user_id", 1], ["calendar_id", 2]]
2015-10-22T22:15:32.137289+00:00 app[web.1]:   Rendered calendars/show.html.erb within layouts/calendars (1294.9ms)
2015-10-22T22:15:32.146407+00:00 app[web.1]:   Rendered layouts/_app_footer.html.erb (1.5ms)
2015-10-22T22:15:32.035637+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "administrations".* FROM "administrations" WHERE "administrations"."user_id" =  AND "administrations"."calendar_id" =  LIMIT 1  [["user_id", 1], ["calendar_id", 2]]
2015-10-22T22:15:32.065673+00:00 app[web.1]:   User Load (2.8ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  LIMIT 1  [["id", 2]]
2015-10-22T22:15:32.084310+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "administrations".* FROM "administrations" WHERE "administrations"."user_id" =  AND "administrations"."calendar_id" =  LIMIT 1  [["user_id", 1], ["calendar_id", 2]]
2015-10-22T22:15:32.116082+00:00 app[web.1]:   CACHE (0.0ms)  SELECT  "administrations".* FROM "administrations" WHERE "administrations"."user_id" =  AND "administrations"."calendar_id" =  LIMIT 1  [["user_id", 1], ["calendar_id", 2]]
2015-10-22T22:15:32.143435+00:00 app[web.1]:   Rendered layouts/_app_header.html.erb (4.1ms)
2015-10-22T22:15:32.147188+00:00 app[web.1]: Completed 200 OK in 2449ms (Views: 1344.0ms | ActiveRecord: 144.9ms)
2015-10-22T22:15:32.159294+00:00 heroku[router]: at=info method=GET path="/calendars/2" host=calendy.herokuapp.com request_id=34fe86a2-9114-4f39-b90a-91b787a4df4a fwd="24.205.62.204" dyno=web.1 connect=1ms service=2616ms status=200 bytes=37572
2015-10-22T22:15:32.489404+00:00 heroku[router]: at=info method=GET path="/assets/font-awesome/fontawesome-webfont-3c4a1bb7ce3234407184f0d80cc4dec075e4ad616b44dcc5778e1cfb1bc24019.woff2" host=calendy.herokuapp.com request_id=510f9bf5-29de-4ad6-b02d-4c937edbe1a1 fwd="24.205.62.204" dyno=web.1 connect=0ms service=44ms status=304 bytes=93

——————

更新 2:

好的,所以我继续研究代码并发现了三件事:

  1. 该代码适用于实现该方法后创建的帖子,即:显示在推送到 Heroku 之前创建的 post.copy 帖子中的 none,无论是什么post.copy

  2. 里面
  3. 一旦我们实施该方法,post.copy 仅当它包含我们使用正则表达式查找的元素之一时才会显示,即:http#@。这有意义吗?

  4. 上述所有情况实际上也在本地发生,与我最初观察到的不同。

——————

知道这里出了什么问题吗?

我找到了问题的根本原因。

我在终端启动了 IRB 运行 一些测试:

h = "hello"
h.gsub!(/((https|http)?:\/\/[\S]+)/, '<span class="highlight"></span>')
# => nil

l = "http://www.link.com"
l.gsub!(/((https|http)?:\/\/[\S]+)/, '<span class="highlight"></span>')
# => "<span class=\"highlight\">http://www.link.com</span>"

当我试图突出显示的字符串 包含我们正在使用正则表达式寻找的任何模式时,问题实际上发生了。

为了解决这个问题,我不得不用 .gsub 替换 .gsub!,并执行条件语句,以便方法 returns 在未检测到模式时初始字符串不变,而不是零。

这是我的新 posts_helper.rb:

module PostsHelper

  def link_highlight(string)
    init1 = string
    result1 = string.to_s.gsub!(/((https|http)?:\/\/[\S]+)/, '<span class="highlight"></span>')
    if result1.nil?
      init1
    else
      result1
    end
  end

  def hashtag_highlight(string)
    init2 = string
    result2 = string.to_s.gsub!(/\S*#(\[[^\]]+\]|\S+)/, '<span class="highlight">#</span>')
    if result2.nil?
      init2
    else
      result2
    end
  end

  def mention_highlight(string)
    init3 = string
    result3 = string.to_s.gsub(/\B(\@[a-z0-9_-]+)/i, '<span class="highlight"></span>')
    if result3.nil?
      init3
    else
      result3
    end
  end

  def new_highlight(string)
    link_highlight(string)
    hashtag_highlight(string)
    mention_highlight(string)
  end

end

这可能不是最干净/最精简的代码,但它在本地和远程都有效,它允许我在 new_highlight 最终方法中链接所有三个方法。

gsub! returns nil 当没有做任何改变时,所以你有两种方法。

您可以保留大部分助手,但将最后一个更改为

def new_highlight(string)
  link_highlight(string)
  hashtag_highlight(string)
  mention_highlight(string)
  string
end

我个人不喜欢这样,因为我不希望视图助手修改它的参数。像这样不小心更改数据库中的数据并不难。

或者改变各种方法看起来像

def link_highlight(string)
  string.gsub(...)
end

并将最终助手更改为

def new_highlight(string)
  mention_highlight(
    hashtag_highlight(
      link_highlight(string)
    )
  )
end

如果您愿意,您可以通过多种方式重写最后一个,例如

%i(link_highlight hashtag_highlight mention_highlight).inject(string) do |value, transform|
  public_send(transform, value)
end

尽管我认为我不会为这样一个简单的案例而烦恼(尽管它确实让我希望使用 elixir 的管道运算符)