简体   繁体   中英

Rails app and sqlite (dev) vs postgresql (prod)

I'm learning RoR and my development db is the default, sqlite and I'm deploying my app to Heroku which uses posgresql. I understand that to avoid such issues, I should develop with postgresql as well, and in future I intend to do this. However, I've got an issue that appears in production but not dev.

Issue : I've got a User and an Account model. A User can have many Accounts .

I made a migration so that when an Account is created, its active field is set to true by default.

class UpdateDefaultAccountActiveValue < ActiveRecord::Migration
  def change
    change_column_default(:accounts, :active, true)
  end
end

This appears to work in dev.

In /views/accounts/index.html.erb , the following code outputs true or false depending on whether an account is active or not.

<% @accounts.each do |account| %>
    <tr>
      <% if !(account.credit) %>
        <td><%= link_to account.name, history_url(id: account.id) %></td>
      <% else %>
        <td><%= link_to account.name + ' (Credit)', history_url(id: account.id) %></td>
      <% end %>
      <td><%= account.active %></td>
      <td><%= link_to 'Edit', edit_account_path(account) %></td>
    </tr>
<% end %>

However, in production, the /views/accounts/index.html.erb doesn't output true or false depending on whether an account is active or not.

Why is this and how can I resolve this?

papertrail log:

2016-05-25T21:34:06.348465+00:00 app[web.1]: Started GET "/accounts" for 176.248.123.34 at 2016-05-25 21:34:06 +0000

2016-05-25T21:34:06.355649+00:00 app[web.1]: Processing by AccountsController#index as HTML

2016-05-25T21:34:06.447420+00:00 app[web.1]: Completed 200 OK in 94ms (Views: 64.5ms | ActiveRecord: 18.2ms)

2016-05-25T21:34:06.452111+00:00 heroku[router]: at=info method=GET path="/accounts" host=???.herokuapp.com request_id=f33ab960-5c1b-4883-a28c-8c2b40388bad fwd="176.248.123.34" dyno=web.1 connect=0ms service=107ms status=200 bytes=4073

This may not solve the exact issue that you are having but there is a far better way to add distinct states to a model than boolean flags.

ActiveRecord::Enum lets create an enum attribute where the values map to integers in the database.

class Account
  enum status: [:active, :closed, :supended] # basically whatever you want
end

Acount.active     # => Acount.where(status: :active)
acount.active!    # => Acount.update!(status: :active)
acount.active?    # => true
acount.closed?    # => false
acount.suspended? # => false
acount.status     # => "active"

Of course you need to add the integer column to the database:

rails g migration add_status_to_accounts status:integer:index

Don't migrate it yet! We also want to add a default:

class AddStatusToAccounts < ActiveRecord::Migration
  def change
    add_column :accounts, :status, :integer, default: 0, null: false
    add_index :accounts, :status
  end
end

In order to set a model property when a record created, you must change it inside the model, if you run a migration, it will help with existing records only.

You need to add three lines of code to your model for it to work for new accounts created:

before_save do
 self.active = true
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM