首页 > 解决方案 > Heroku Production - 属性未保存在生产中,但在开发中有效

问题描述

App 正在使用 Gems 的组合创建一个多租户应用程序,帐户所有者可以在其中邀请用户。然后根据当前用户的 :account_id 值将显示的所有数据限定为 :account_id 列。它正在为帐户和用户使用设计。它使用 Devise Invitable 允许帐户通过电子邮件向用户发送邀请以创建他们的帐户,然后在创建时为该用户分配邀请他们加入的帐户 ID 的 :account_id。

在开发环境中, :account_id 在 InvitationsController#Create 操作时被正确分配。在 Heroku 的生产环境中,它无法通过相同的操作将 :account_id 保存给用户。

宝石文件:

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.7.1'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3', '>= 6.0.3.2'
# Use postgresql as the database for Active Record
gem 'pg', '>= 0.18', '< 2.0'
# Use Puma as the app server
gem 'puma', '~> 4.1'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 4.0'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.7'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'
# Gem for Users and Account control
gem 'devise'
# Gems for making things pretty
gem 'bootstrap'
gem 'font-awesome-rails'
# Use for creating graphs and grouping data
gem 'chartkick'
gem 'groupdate'
# Pagination gem
gem 'kaminari'
# Use Active Storage variant
# gem 'image_processing', '~> 1.2'

#Use to make mulitenancy simpler
gem 'acts_as_tenant'

#For Account owners to invite their company's Users
gem 'devise_invitable'

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.2', require: false

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '~> 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of web drivers to run system tests with browsers
  gem 'webdrivers'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

路由.rb

Rails.application.routes.draw do
  
  devise_for :accounts, controllers: { sessions: 'accounts/sessions', registrations: 'accounts/registrations', invitations: 'users/invitations' }

  devise_for :users, controllers: { sessions: 'users/sessions', invitations: 'users/invitations' }

  resources :downtimes
  resources :downtime_criteria

  resources :actionitems do
    resources :comments
  end

  resources :production_runs do
    resources :production_hours
  end

  root 'welcome#index'

end

应用控制器

class ApplicationController < ActionController::Base

  set_current_tenant_through_filter
  before_action :find_current_tenant

  def find_current_tenant
    current_account_id = user_signed_in? ? current_user.account : nil
    set_current_tenant(current_account_id)
  end

  def authenticate_inviter!
    authenticate_account!(force: true)
  end
end

/users/InvitationsController

class Users::InvitationsController < Devise::InvitationsController  
  before_action :configure_permitted_parameters, if: :devise_controller?

  def create
    super
    User.invite!(:email => params[:email], :account_id => current_account.id)
    User.where(email: params[:user][:email]).update_all(account_id: current_account.id)
  end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:invite, keys: [:account_id])
  end

end

账户.rb

class Account < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_many :users, dependent: :destroy
  include DeviseInvitable::Inviter
end

用户.rb

class User < ApplicationRecord
  acts_as_tenant(:account)
  belongs_to :account
  validates :email, :account_id, presence: true
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :invitable, :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end

/users/invitations/_new.html.erb

<h2><%= t "devise.invitations.new.header" %></h2>

<%= form_for(resource, as: @invitation, url: invitation_path(resource_name), html: { method: :post }) do |f| %>
  <%= render "users/shared/error_messages", resource: resource %>

  <% resource.class.invite_key_fields.each do |field| -%>
    <div class="field">
      <%= f.label field %><br />
      <%= f.text_field field %>
    </div>
  <% end -%>

  <div class="actions">
    <%= f.submit t("devise.invitations.new.submit_button") %>
  </div>
<% end %>

heroku 日志 --tail

2020-09-03T02:57:16.793404+00:00 heroku[router]: at=info method=POST path="/users/invitation" host=gentle-cliffs-24710.herokuapp.com request_id=cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8 fwd="108.166.134.134" dyno=web.1 connect=0ms service=646ms status=500 bytes=1827 protocol=https
2020-09-03T02:57:16.744528+00:00 app[web.1]: D, [2020-09-03T02:57:16.744380 #4] DEBUG -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8]   User Load (1.2ms)  SELECT "users".* FROM "users" WHERE "users"."invitation_token" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["invitation_token", "f865f1a5e1e8e8f1576567e1f539ba6d9d3a1e85d5b21fa8e8fc72a0a7a1341d"], ["LIMIT", 1]]
2020-09-03T02:57:16.750905+00:00 app[web.1]: D, [2020-09-03T02:57:16.750774 #4] DEBUG -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8]    (3.2ms)  BEGIN
2020-09-03T02:57:16.753036+00:00 app[web.1]: D, [2020-09-03T02:57:16.752895 #4] DEBUG -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8]   User Create (1.3ms)  INSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at", "invitation_token", "invitation_created_at", "invitation_sent_at", "invited_by_type", "invited_by_id") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id"  [["email", "testing12345@gmail.com"], ["encrypted_password", "$2a$11$sPBv6kzgZNZcaDhRpNORcuThcEFQQh8xqTiIJ45izWX0v3eyBtgKK"], ["created_at", "2020-09-03 02:57:16.746102"], ["updated_at", "2020-09-03 02:57:16.746102"], ["invitation_token", "f865f1a5e1e8e8f1576567e1f539ba6d9d3a1e85d5b21fa8e8fc72a0a7a1341d"], ["invitation_created_at", "2020-09-03 02:57:16.744928"], ["invitation_sent_at", "2020-09-03 02:57:16.744928"], ["invited_by_type", "Account"], ["invited_by_id", 2]]
2020-09-03T02:57:16.758183+00:00 app[web.1]: D, [2020-09-03T02:57:16.758057 #4] DEBUG -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8]    (4.4ms)  COMMIT
2020-09-03T02:57:16.765162+00:00 app[web.1]: I, [2020-09-03T02:57:16.765033 #4]  INFO -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8]   Rendering users/mailer/invitation_instructions.html.erb
2020-09-03T02:57:16.767966+00:00 app[web.1]: I, [2020-09-03T02:57:16.767824 #4]  INFO -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8]   Rendered users/mailer/invitation_instructions.html.erb (Duration: 2.6ms | Allocations: 517)
2020-09-03T02:57:16.771219+00:00 app[web.1]: I, [2020-09-03T02:57:16.771101 #4]  INFO -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8]   Rendering users/mailer/invitation_instructions.text.erb
2020-09-03T02:57:16.773629+00:00 app[web.1]: I, [2020-09-03T02:57:16.773519 #4]  INFO -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8]   Rendered users/mailer/invitation_instructions.text.erb (Duration: 2.2ms | Allocations: 393)
2020-09-03T02:57:16.777350+00:00 app[web.1]: D, [2020-09-03T02:57:16.777199 #4] DEBUG -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8] Devise::Mailer#invitation_instructions: processed outbound mail in 18.2ms
2020-09-03T02:57:16.788770+00:00 app[web.1]: I, [2020-09-03T02:57:16.788627 #4]  INFO -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8] Delivered mail 5f505b8cbe3f1_493944479@739a533a-af2a-474c-a8c4-7bacfd76c8ca.mail (11.2ms)
2020-09-03T02:57:16.788846+00:00 app[web.1]: D, [2020-09-03T02:57:16.788754 #4] DEBUG -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8] Date: Thu, 03 Sep 2020 02:57:16 +0000
2020-09-03T02:57:16.788847+00:00 app[web.1]: From: please-change-me-at-config-initializers-devise@example.com
2020-09-03T02:57:16.788847+00:00 app[web.1]: Reply-To: please-change-me-at-config-initializers-devise@example.com
2020-09-03T02:57:16.788848+00:00 app[web.1]: To: testing12345@gmail.com
2020-09-03T02:57:16.788849+00:00 app[web.1]: Message-ID: <5f505b8cbe3f1_493944479@739a533a-af2a-474c-a8c4-7bacfd76c8ca.mail>
2020-09-03T02:57:16.788850+00:00 app[web.1]: Subject: Invitation instructions
2020-09-03T02:57:16.788850+00:00 app[web.1]: Mime-Version: 1.0
2020-09-03T02:57:16.788851+00:00 app[web.1]: Content-Type: multipart/alternative;
2020-09-03T02:57:16.788851+00:00 app[web.1]: boundary="--==_mimepart_5f505b8cbd144_493944334";
2020-09-03T02:57:16.788852+00:00 app[web.1]: charset=UTF-8
2020-09-03T02:57:16.788852+00:00 app[web.1]: Content-Transfer-Encoding: 7bit
2020-09-03T02:57:16.788853+00:00 app[web.1]:
2020-09-03T02:57:16.788853+00:00 app[web.1]:
2020-09-03T02:57:16.788853+00:00 app[web.1]: ----==_mimepart_5f505b8cbd144_493944334
2020-09-03T02:57:16.788854+00:00 app[web.1]: Content-Type: text/plain;
2020-09-03T02:57:16.788854+00:00 app[web.1]: charset=UTF-8
2020-09-03T02:57:16.788854+00:00 app[web.1]: Content-Transfer-Encoding: 7bit
2020-09-03T02:57:16.788855+00:00 app[web.1]:
2020-09-03T02:57:16.788855+00:00 app[web.1]: Hello testing12345@gmail.com
2020-09-03T02:57:16.788855+00:00 app[web.1]:
2020-09-03T02:57:16.788856+00:00 app[web.1]: Someone has invited you to https://gentle-cliffs-24710.herokuapp.com/:3000/, you can accept it through the link below.
2020-09-03T02:57:16.788856+00:00 app[web.1]:
2020-09-03T02:57:16.788857+00:00 app[web.1]: https://gentle-cliffs-24710.herokuapp.com/:3000/users/invitation/accept?invitation_token=yGi2R5_2acRXY3XJXSVN
2020-09-03T02:57:16.788857+00:00 app[web.1]:
2020-09-03T02:57:16.788857+00:00 app[web.1]:
2020-09-03T02:57:16.788858+00:00 app[web.1]: If you don't want to accept the invitation, please ignore this email. Your account won't be created until you access the link above and set your password.
2020-09-03T02:57:16.788858+00:00 app[web.1]:
2020-09-03T02:57:16.788858+00:00 app[web.1]: ----==_mimepart_5f505b8cbd144_493944334
2020-09-03T02:57:16.788859+00:00 app[web.1]: Content-Type: text/html;
2020-09-03T02:57:16.788859+00:00 app[web.1]: charset=UTF-8
2020-09-03T02:57:16.788859+00:00 app[web.1]: Content-Transfer-Encoding: 7bit
2020-09-03T02:57:16.788860+00:00 app[web.1]:
2020-09-03T02:57:16.788860+00:00 app[web.1]: <p>Hello testing12345@gmail.com</p>
2020-09-03T02:57:16.788861+00:00 app[web.1]:
2020-09-03T02:57:16.788861+00:00 app[web.1]: <p>Someone has invited you to https://gentle-cliffs-24710.herokuapp.com/:3000/, you can accept it through the link below.</p>
2020-09-03T02:57:16.788861+00:00 app[web.1]:
2020-09-03T02:57:16.788862+00:00 app[web.1]: <p><a href="https://gentle-cliffs-24710.herokuapp.com/:3000/users/invitation/accept?invitation_token=yGi2R5_2acRXY3XJXSVN">Accept invitation</a></p>
2020-09-03T02:57:16.788862+00:00 app[web.1]:
2020-09-03T02:57:16.788863+00:00 app[web.1]:
2020-09-03T02:57:16.788863+00:00 app[web.1]: <p>If you don&#39;t want to accept the invitation, please ignore this email. Your account won&#39;t be created until you access the link above and set your password.</p>
2020-09-03T02:57:16.788864+00:00 app[web.1]:
2020-09-03T02:57:16.788864+00:00 app[web.1]: ----==_mimepart_5f505b8cbd144_493944334--
2020-09-03T02:57:16.788865+00:00 app[web.1]:
2020-09-03T02:57:16.789171+00:00 app[web.1]: I, [2020-09-03T02:57:16.789103 #4]  INFO -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8] Completed 500 Internal Server Error in 586ms (ActiveRecord: 21.3ms | Allocations: 11597)
2020-09-03T02:57:16.790582+00:00 app[web.1]: F, [2020-09-03T02:57:16.790480 #4] FATAL -- : [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8]
2020-09-03T02:57:16.790584+00:00 app[web.1]: [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8] Errno::ECONNREFUSED (Connection refused - connect(2) for "localhost" port 25):
2020-09-03T02:57:16.790584+00:00 app[web.1]: [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8]
2020-09-03T02:57:16.790585+00:00 app[web.1]: [cdfe6b7c-7473-47d9-9ff1-ebca721ba0e8] app/controllers/users/invitations_controller.rb:5:in `create'

heroku run rails c

irb(main):006:0> User.last
D, [2020-09-03T02:58:48.541138 #4] DEBUG -- :   User Load (1.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]
=> #<User id: 8, email: "testing12345@gmail.com", created_at: "2020-09-03 02:57:16", updated_at: "2020-09-03 02:57:16", ***account_id: nil***>
irb(main):007:0>

我试过运行heroku重启。没有想法......有人有一些见识吗?谢谢

标签: ruby-on-railsrubyherokuruby-on-rails-6heroku-postgres

解决方案


推荐阅读