Rails 3 relationship definition problem? - ruby

I'm new to Rails 3, i'm creating a web app that use active admin, i get a problem with him, and asked for help inside github plugin, someone told me maybe a relationship definitions.
I really dont know what is that, i have nested elements and in active admin i want to make nested element independent.
but now, im totally lost. what i missed? thanks.
here is my model definition
class Company < ActiveRecord::Base
before_save :getsubdomain
has_attached_file :logo, :styles => { :thumb => '150x150>', :medium => '250x250>', :normal => '350x350>'}
has_many :buildings
accepts_nested_attributes_for :buildings
end
Building model
class Building < ActiveRecord::Base
belongs_to :companies
end
in my db, i have colum company_id in buildings table.
Here the error message i get..
NameError in Admin/buildings#index
Showing /Library/Ruby/Gems/1.8/bundler/gems/active_admin-c3a1ffa98072/app/views/active_admin/resource/index.html.arb where line #1 raised:
uninitialized constant Building::Companies
Rails.root: /Users/username/Sites/myapps
Request
Parameters:
{"order"=>"id_desc"}
Response
Headers:
None
thanks for your help

belongs_to expects a singular name. Try
belongs_to :company

Related

Rails 3 - Scopes

I have models set up similar to this:
class Book < ActiveRecord::Base
has_many :histories, as: :object
end
class Magazine < ActiveRecord::Base
has_many :histories, as: :object
end
class Action < ActiveRecord::Base
belongs_to :object, polymorphic: true
default_scope order(:done_at)
# a history contains an action and the time that action
# occurred on the object it belongs to
end
Now, I want to get a list of the 5 lastest actions that have occurred on all objects. So I can do something like:
Action.limit(5)
However, the problem is that if two actions have recently occurred on the same book, both actions will be retrieved. I want to only retrieve the lastest one. How do I achieve this?
Figured out that what I wanted was the group option. So I can do something like:
Action.group(:object_id).group(:object_type).limit(5)

Rails - belongs_to association not updating foreign key

I have the following:
class Publication < ActiveRecord::Base
belongs_to :project, :inverse_of => :publication
before_create :bind_project
private
def bind_project
self.create_project
end
end
class Project < ActiveRecord::Base
has_one :publication, :inverse_of => :project
end
According to this when creating a new Publication the publication_id attribute on the project model should be set by the create_project method.
Why it does not happen?
This is what I see on bind_project:
self.project_id is set correctly
self.project.publication_id is NULL
self.project.publication.id is set correctly
The database reflects this also: the projects.publication_id column is NULL.
Seems a bit strange, that you try to access the create_project method in a before_create callback. Typo? An after_create callback seems to be more appropriate.
Moreover: What for do you need the publication_id attribute on the has_one side of an association? There only needs to be one _id attribute on the belongs_to side.
Addendum to my first paragraph: As I see it, you are trying to use Rails magic on the associated object (the create_project method) before the actual base object is finished being created. Although this might work, this would be my first point to investigate.

Many-to-Many Uniqueness Constraint Test Not Working

I have a many-to-many relationship with a join table in my Rails application. I'm using the has_many :through idiom in my models. To keep things simple, lets call my first class Student, my second class Course, and the join table class Enrollment (which contains fields student_id and course_id). I want to make sure that a given Student is associated with a given Course at most once (i.e. the {student_id, course_id} tuple should be unique in the enrollment table).
So I have a migration a that enforces this uniqueness.
def change
add_index :enrollments, [:student_id, :course_id], :unique => true
end
In addition my model classes are defined as such:
class Student < ActiveRecord::Base
has_many :enrollments
has_many :courses, :through => :enrollment
end
class Course < ActiveRecord::Base
has_many :enrollments
has_many :students, :through => :enrollment
end
class Enrollment < ActiveRecord::Base
belongs_to :student
belongs_to :course
validates :student, :presence => true
validates :course, :presence => true
validates :student_id, :uniqueness => {:scope => :course_id}
end
In a rails console, I can do the following:
student = Student.first
course = Course.first
student.courses << course
#... succeeds
student.courses << course
#... appropriately fails and raises an ActiveRecord::RecordInvalid exception
In my RSpec test, I do the exact same thing and I get no exception with the following code:
#student.courses << #course
expect { #student.courses << #course }.to raise_error(ActiveRecord::RecordInvalid)
And so my test fails and reports:
expected ActiveRecord::RecordInvalid but nothing was raised
What's going on here? What could I be doing wrong? How do I fix it?
Rails uses model level validation, if you want strict checking for uniquiness you need to use database level - foreign keys for example. But in this case you need to catch exceptions from database connector.
This is strange because in my code (very similar to your) validation for unique raises exception.
There's a couple of things here that could be happening:
#courses has changed between uses.
#student has changed between uses.
By using let you'll protect these values from changing between expectations.
let(:course) { Course.first }
let(:student) { Student.first }
subject{ student.courses << course << course }
it { should raise_error(ActiveRecord::RecordInvalid) }
Or, there could just be something wrong with your code :)

Rails get related items through two different relationships

I have a "two middleman" model setup as shown below:
User
has_many :comments
has_many :ratings
Comment
belongs_to :user
belongs_to :movie
Rating
belongs_to :user
belongs_to :movie
Movie
has_many :comments
has_many :ratings
Whats the best way to get all Movies that a User is associated with (either commented on or rated)?
I'd like to be able to call User.get_movies(user_id) and get back an ActiveRecord::Relation object so that it's chainable (i.e. User.get_movies(user_id).limit(3).order(...)). This returns a regular old array, and I suspect I'm hitting the database way more than I need to be.
def self.get_movies(user_id)
user = self.where(:id => user_id).includes({:comments => :movie}, {:ratings => :movie})
movies = []
user.comments.each do |comment|
movies.push(comment.movie)
end
user.ratings.each do |rating|
movies.push(rating.movie)
end
movies.uniq!
end
def movies
Movie.includes(:ratings, :comments).where("`ratings`.user_id = ? OR `comments`.user_id = ?", self.id, self.id)
end
Untested, but I'm pretty sure using a joins instead of includes also works.

Approaches to sub categories of polymorphic associations in Rails

Hello Everyone,
I have a polymorphic association currently in use with a few different models. Each model has it's own video file associated with it, so it uses a "videoable" polymorphic association. I recently found the need however, to create a new model that has 2 separate types of videos. I will let the code do the talking.
#current setup
class Video < ActiveRecord::Base
belongs_to :videoable, :polymorphic => true
end
class Project < ActiveRecord::Base
has_one :video, :as => videoable
end
# New model I am working on
class Assignment < ActiveRecord::Base
has_one :video_draft
has_one :video_final
end
Ideally the assignment model would have two special types of video objects while still using the polymorphic association. I have considered single table inheritance, but I am not sure that is the best approach here. What are my options? I do not want to create a video_draft model and a video_final model because in the end, they are just video attachments like everything else. The only difference is that they are specialized video attachments that need their own unique reference.
What you need to do is to tell ActiveRecord what model are you referring to when declaring :video_draft instead of :video like in Project model. This can be done by passing :class_name option to has_one
Keeping this in mind, this should work fine:
class Assignment < ActiveRecord::Base
has_one :video_draft, :as => :videoable, :class_name => "Video"
has_one :video_final, :as => :videoable, :class_name => "Video"
end
See rails guides at section 4.2.2.3 for more info about need for passing :class_name.

Resources