0

I have decided to add slugs to my URLs, I added a column named "slug", created migration, successfully migrate it, verified the existence of a column in the database:

enter image description here

But I am unable to create records because I get a following error:

NoMethodError: undefined method `slug=' for #Hotel:0x3d19a60

I am using friendly_id library, but this problem is not probably bound to the library itself. Anyway here are some relevant data:

  • Rails version: 4.2.4
  • Ruby version: 2.1.7
  • Frienldy ID version: 5.1.0
  • Database: Postgres 9.3.5

Part of the Hotel model class:

class Hotel < ActiveRecord::Base
  extend FriendlyId
  friendly_id :generate_slug, use: :slugged

  def generate_slug
    "#{self.name} #{self.id}"
  end

  def should_generate_new_friendly_id?
    name_changed? || new_record?
  end

  def normalize_friendly_id(text)
    super(I18n.transliterate(text))
  end

Part of code, where the error is thrown when calling save (data is hidden):

  rest = Hotel.new(:name => "*", :telephone => "*", :email => "*", :web_page => "*", :state => 1, :city_search => "*", :smoking => *,
                  :address_attributes => {:city => "*", :street => "*", :postal_code => "*", :country_code => "*"})
  ObjectSkipValidator.setup_validations(rest, nil)
  rest.save!

Of course the table has slug column, my migration:

AFFECTED_TABLES = [:restaurants, :hotels]

  def change
    AFFECTED_TABLES.each do |tab|
      add_column tab, :slug, :string
      add_index tab, :slug, unique: true   
    end
  end

I have tried to override ActiveRecord so i could see where the problem is and it looks that the attributes hash, which is needed in attribute_missing method doesn't contain the column "slug" but all the other columns are present.

ActiveRecord::AttributeSet::Builder.build_from_database - when called, values doesn't contain slug column

Also this part of method ActiveModel::AttributeMethods.method_missing:

match = match_attribute_method?(method.to_s)
match ? attribute_missing(match, *args, &block) : super

Never calls attribute_missing so no getters and setters are being created for this particular column because the matcher could not find the slug column.

So why I can't access or set "slug" attribute on my model? Thanks for any responses.

EDIT: Thanks to Sean's comment it looks like the problem is in some steps before the database population. Population is being done in this task - I have used it for a long time without any problems - error is thrown during db:populate task:

task prepare_all: :environment do
  puts "==== PREPARING DATABASE ===="
  Rake::Task["db:drop"].invoke()
  Rake::Task["db:create"].invoke()
  Rake::Task["db:migrate"].invoke()
  Rake::Task["db:populate"].invoke()
  Rake::Task["db:codetables_populate"].invoke()
  Rake::Task["db:geocode"].invoke()
  puts "==== DATABASE PREPARED ===="
end

Task is executed using:

bundle exec rake db:prepare_all RAILS_ENV=development

If I run the tasks one by one, eg. db:drop, db:create, db:migrate, db:populate, it works as expected and slugs are beying created. It looks like the invocation of tasks in a way I am doing it is wrong.

Giron
  • 350
  • 3
  • 16
  • What does `Hotel.column_names.include?('slug')` return? – Sean Huber Apr 08 '16 at 16:05
  • It returns false - btw the code for creation is inside a rake task, I forgot to mention that. – Giron Apr 08 '16 at 17:02
  • What does this query return: `ActiveRecord::Base.connection.execute("SELECT `version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` DESC LIMIT 1").first[0]` What timestamp does your migration have? What version do you see defined in `db/shema.rb`? Are you certain your Rails environment is connecting to the correct database? – Sean Huber Apr 08 '16 at 17:40
  • Hmm this helped me a lot...first I have yet again verifid, that I am connected to the right database using Rails.configuration.database_configuration[Rails.env] and than I have tried your select and suprisingly it returned nil. But when I looked into the database, all migrations were there. The thing is, that database population is a part of a larger rake task, which completely drops the database, recreates it, migrate it than starts population....but it looks like there is something which causes to changes not being commited or something like that. I have added my rake task to the question. – Giron Apr 08 '16 at 18:29

1 Answers1

0

Looks like the problem was with the rake task itself. I am not sure about the reason why error occurred (why the last migration wasn't added), but it works with the following setup if I drop and create database outside of the task. The task now looks like this:

task prepare_all: :environment do
  puts "==== PREPARING DATABASE ===="
  Rake::Task["db:migrate"].invoke
  Rake::Task["db:reset"].invoke
  Rake::Task["db:populate"].invoke
  Rake::Task["db:codetables_populate"].invoke
  Rake::Task["db:geocode"].invoke
  puts "==== DATABASE PREPARED ===="
end
Giron
  • 350
  • 3
  • 16