0

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
6
  • 1
    Could you show the logs (install papertrail addon from heroku if don't have it yet)? I guess the value is nil on the columns, so use the $heroku run rails console in terminal, find an account instance and check out the attr. If nil find all the instances of the class and set it true. Then add a null: false constraint to the db column with migration. Extra: change the order of the 2 options and use <% if account.credit %>. And you should change the development db to pg as soon as possible. Commented May 25, 2016 at 21:20
  • @SzilardMagyar I've installed papertrail and it's attached to my app. How do I view the logs? Commented May 25, 2016 at 21:28
  • 2 ways: 1. from terminal: $heroku logs --tail 2. from papertrail: you just click on papertrail from heroku dashboard Commented May 25, 2016 at 21:30
  • @SzilardMagyar I've attached the log to the OP. Commented May 25, 2016 at 21:35
  • In the logs everything is fine as you get 200 status code. Have you checked the attr values of the boolean field? Commented May 25, 2016 at 21:54

2 Answers 2

1

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
Sign up to request clarification or add additional context in comments.

Comments

0

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

1 Comment

Sorry to rain on your parade but pretty much everything in this answer is wrong. If you set a default in the DB schema ActiveRecord will set it for new model instances. When you add or change a database default it only effects new rows / records. That callback would change self.active = true every time you update an account!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.