Search code examples
ruby-on-rails-3sqliteactioncontrollermodel-associationsnosuchmethoderror

How do I correct this model association?


I've created an album model and a photo model and added it to an existing rails application. I've made the photos model belong to the album model and the album model belong to an existing profile model that belongs to a user model. I don't know if I've associated them wrong and why I'm getting an error.

It's worth noting that when I go to URL/albums then everything works as it should but when I go to URL/profiles/1 (the code below is pasted in the show.html.erb file in the views/profile/ folder) then I get the error below.

This is a simple problem that I just can't solve. The four model files are below:

Album.rb:

class Album < ActiveRecord::Base
  belongs_to :profile
  has_many :photos, :dependent => :destroy
  accepts_nested_attributes_for :photos, :allow_destroy => true
end

Profile.rb:

class Profile < ActiveRecord::Base

belongs_to :user
has_many :albums

def self.get_location(profile)
  location = []

  location << profile.city unless profile.city.blank?

  location << profile.state unless profile.state.blank?

  location << profile.country unless profile.country.blank?

  location << profile.postal_code unless profile.postal_code.blank?

  location
end

def self.missing_fields(profile)
  missing = []

  if profile.first_name.blank?
    missing << "first name"
  end

  if profile.last_name.blank?
    missing << "last name"
  end

  if profile.job_title.blank?
    missing << "job title"
  end

  missing
end

end

Photo.rb:

require 'paperclip'
class Photo < ActiveRecord::Base

  belongs_to :album
  has_attached_file :upload,
                :url => "/images/:id/:style/:basename.:extension",
                :path => ":rails_root/public/images/:id/:style/:basename.:extension",
                :styles => {
                  :thumb => "75x75>",
                  :small => "200x200>"
                }
  #add in any validations you may want
end

User.rb:

class User < ActiveRecord::Base

  include Gravtastic
  gravtastic :size => 120

  # associations
  has_many :albums
  has_many :photos, :through => :albums
  has_many :authorizations, :dependent => :destroy
  has_one :profile, :dependent => :destroy
  has_many :resumes, :dependent => :destroy, :order => 'created_at DESC'
  has_many :thoughts, :dependent => :destroy, :order => 'created_at DESC'
  has_many :user_threads, :dependent => :destroy, :order => 'created_at ASC'

  accepts_nested_attributes_for :profile

  # virtual attributes
  attr_accessor :first_name, :last_name

  # validations
  validates_presence_of :first_name
  validates_presence_of :last_name
  validates_length_of :username, :minimum => 4, :message => " is too short"
  validates :email, :email => {:message => " is not valid"}
  validates_uniqueness_of :email, :case_sensitive => false
  validates_uniqueness_of :username, :case_sensitive => false
  validates_length_of :password, :minimum => 4, :message => " is too short"

  # authlogic
  acts_as_authentic do |config|
  config.crypto_provider = Authlogic::CryptoProviders::MD5
  config.maintain_sessions = false
  config.validate_email_field = false
  config.validate_login_field = false
  config.validate_password_field = false
  config.login_field = :email
  config.validate_login_field = false
end

  def self.create_from_hash!(hash)
    user = User.new(:username => Time.now.to_i, :email => '', :auth_provider => hash['provider'])
    user.save(:validate => false)
    if hash['provider'].downcase == 'twitter'
    user.profile = Profile.create(:first_name => Twitter::Client.new.user(hash['user_info']    ['nickname'].to_s).name)
else
  user.profile = Profile.create(:first_name => hash['user_info']['first_name'], :last_name => hash['user_info']['last_name'])
end
user
end

  def deliver_password_reset_instructions!
    reset_perishable_token!
    UserMailer.deliver_password_reset_instructions(self)
  end

  def activate!
   self.active = true
   save(false)
  end

  def deliver_activation_instructions!
   reset_perishable_token!
   UserMailer.deliver_activation_instructions(self)
  end

end

The profile controller has this snippet:

  def show
    @user = User.find_by_username(params[:id])
    @profile = @user.profile

    @location = Profile.get_location(@profile)

    @resumes = @user.resumes

    @albums = @user.albums

    @photos = @user.photos

    @thoughts = @user.thoughts

    @shouts = UserThread.find_profile_shouts(@profile)

    @shouters = UserThread.find_shouters(@shouts)

    @user_thread = UserThread.new
  end

The view has this:

<div id="profile_right_col">
    <h2>Albums</h2>
    <p>
      <b>Name:</b>
      <%= @albums %><br />

      <% @albums.photos.each do |photo| %>
        <h3><%= photo.title %></h3>
        <%= image_tag photos.upload.url(:small) %>
      <% end %>
    </p>

    <%= link_to 'Edit', edit_album_path(@albums) %> |
    <%= link_to 'Back', albums_path %>
</div>

The Action Controller exception shows:

ActiveRecord::StatementInvalid in Profiles#show

Showing /Users/pawel/Ruby/Apps/cvf/app/views/profiles/show.html.erb where line #137 raised:

SQLite3::SQLException: no such column: albums.user_id: SELECT     "albums".* FROM       "albums"  WHERE     ("albums".user_id = 4)

Extracted source (around line #137):

 <h2>Albums</h2>
<p>
<b>Name:</b>
<%= @albums %><br />

<% @albums.photos.each do |photo| %>
<h3><%= photo.title %></h3>

Solution

  • It worked after I added Paperclip::Railtie.insert to my application.rb.