Active Record query - ruby-on-rails

I have two models ForumThread and Post set-up like this:
class ForumThread < ActiveRecord::Cached
has_many :posts
end
class Post < ActiveRecord::Cached
end
class CreateForumThreads < ActiveRecord::Migration
def self.up
create_table :forum_threads do |t|
t.column :thread_name, :text
end
add_index :forum_threads, :thread_name
end
def self.down
drop_table :forum_threads
end
end
class CreatePosts < ActiveRecord::Migration
def self.up
create_table :posts do |t|
t.column :post_body, :text
t.integer :forum_thread_id, :null => false
t.integer :priority
end
end
def self.down
drop_table :posts
end
end
I'd like to create a query that returns all forum threads where there's at least one post in each thread with priority of one. How do I create this query?
I've been considering something like ForumThread.joins(:posts).select(:priority => 1). I'm relatively new to Active Record (and totally new to joins) so any help is appreciated.

ForumThread.joins(:posts).where(:posts => {:priority => 1})
see join with conditions

First of all you should rename thread_id field to forum_thread_id in posts table and add posts_count to forum_threads table.
In Post class add belongs_to :forum_thread, :counter_cache => true
Now you can query ForumThread.where("posts_count > ?", 1).joins(:posts).where("posts.priority = ?", 1) which will return you a collection of posts.

Related

How to migrate with data update on *one time* joined columns?

I'm adding a new association to existing models with existing data in a Rails 3.2.x + AR project.
The Migration script:
class AddUserToSignups < ActiveRecord::Migration
def up
add_column :signups, :user_id, :integer, :default => nil
add_index :signups, :user_id
# UPDATE SIGNUPS S JOIN USERS U ON S.EMAIL=U.EMAIL SET S.USER_ID = U.ID
end
def down
drop_column :signups, :user_id
end
end
How do I do a joined update per the comment above with AR? I come from a Sequel ORM background, so Sequel's approach would be:
DB[:signups___s].join(:users___u, :u__id => :s__user_id).update(:s__user_id => :u__id)
def up
add_column :signups, :user_id, :integer, :default => nil
add_index :signups, :user_id
ActiveRecord::Base.connection.execute("UPDATE SIGNUPS S JOIN USERS U ON S.EMAIL=U.EMAIL SET S.USER_ID = U.ID")
end

How can I add index, and reindex to the existing attribute?

I'm fetching a record by the code just like these
#community = Community.find_by_community_name(params[:community_name])
#user = User.find_by_username(params[:username])
I want to make it faster loading, so I'm thinking of adding index to them just like this.
If I do rake db:migrate, does it reindex to the existing records also?
Or just the records that will be created from now on?
Do it improve the speed of loading by adding index just like this?
class AddIndexToCommunity < ActiveRecord::Migration
def self.up
add_index :communities, [:community_name, :title, :body], :name=>:communities_idx
end
def self.down
remove_index :communities, [:community_name, :title, :body], :name=>:communities_idx
end
end
class AddIndexToUser < ActiveRecord::Migration
def self.up
add_index :users, [:username, :nickname, :body], :name=>:users_idx
end
def self.down
remove_index :users, [:username, :nickname, :body], :name=>:users_idx
end
end
rake db:migrate will perform database migrations and apply indeces immediately.You should apply indeces only to columns which you use in searching. Remember that indeces add time penalty on insert and update operations. If you load records on by their names, add indeces only to names:
class AddIndexToCommunity < ActiveRecord::Migration
def self.up
add_index :communities, :community_name
end
def self.down
remove_index :communities, :community_name
end
end
class AddIndexToUser < ActiveRecord::Migration
def self.up
add_index :users, :username
end
def self.down
remove_index :users, :username
end
end

Accessing has_many model records

I have the following 2 tables defined in migrations
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :name
t.string :phone
t.string :email
t.string :address
t.string :resume
t.timestamps
end
end
end
Class CreateResumeSections < ActiveRecordMigration
def self.up
create_table :resume_sections do |t|
t.string :section_name
t.string :html
t.timestamps
end
end
end
I have following 2 models
class User
has_many :resume_sections, :dependent => :destroy
attr_accessor :section_layout
after_save :save_sections
private
def save_sections
self.section_layout = ###Someother logic here that sets this variable
end
end
class ResumeSection
belongs_to :user
end
In my users_controller, I have the following code
class UserController < ApplicationController
def create
#user = User.new(params[:user])
#user.save
#user.section_layout.each {|key,value|
rs = ResumeSection.new(:section_name => key, :html => value, :user => #user)
rs.save
}
end
end
In my view I have the following code
<% #user.resume_sections.each do |section| %>
<%= section.section_name %>
<%= section.html %>
<% end %>
I get Undefined method error for Nil:NilClass in the view. The expression #user.resume_sections is not returning to me the records that I just created and saved in the UsersController. Instead it returns nil to me. When I check the database the records are there.
Is the expression #user.resume_sections the correct expression to access these records?
Thanks
Paul
It seems to me that your you missed something in you migrations. ResumeSection needs to have and integer field called user_id. Just create a new migration that has something like this in it:
def change
add_column :resume_section, :user_id, :integer
end

Rails Beginner Attempting TDD:

I'm new to unit testing and Rails in general. I've decided to build my projects in a TDD environment, but this has left me with some early questions.
I need help building the models to pass this test:
describe User do
it "should add user to team" do
team = Team.create(:name => "Tigers")
akash = User.create(:name => "Akash")
akash.teams << team
akash.memberships.size.should == 1
end
it "should allow buddyup"
john = User.create(:name => "John")
john.buddyup_with(akash)
john.memberships.size.should == 1
end
it "should validate linked buddys"
akash.buddys.should include(john)
end
end
Basically, ALL I want to do right now is pass the tests. Here is what I have so far:
class Team < ActiveRecord::Base
has_and_belongs_to_many :users
attr_accessubke :name
validates :name, :presence = true
:uniqueness => true
end
class User < ActiveRecord::Base
has_and_belongs_to_many: :teams
attr_accessible :name
validates :name, :presence = true
:uniqueness => true
end
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :users
end
end
class CreateTeams < ActiveRecord::Migration
def self.up
create_table :teams do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :teams
end
end
class CreateTeamsUsersJoinTable < ActiveRecord::Migration
def self.up
create_table :teams_users, :id => false do |t|
t.integer :team_id
t.integer :user_id
end
end
def self.down
drop_table :teams_users
end
end
That is all I have so far, and clearly it is nowhere near completion. Could you provide some insight, and perhaps code I should use to complete this? My biggest problem right now is the buddyup_with part. Adding a buddy will add a person to every team you are a member of, think of teams as parts of a development company, and buddys as understudies or something.
Suggestions I would make:
Use before do
# code #
end
to set up your conditions.
Do 1 test per. You have a lot going on there :)
Use Factory Girl.
Try what you have and work from there (Agile approach, even to adding tests).

Rails3, Unknown key(s): client_id, on belongs_to association

I've been searching for a while now, but google isn't really helping me.
The ArgumentError Unknown key(s): client_id appears in the ProjectsController:
# projects_controller.rb
class Management::ProjectsController < Management::ManagementController
def index
#projects = Project.find( :client_id => current_user.client )
end
end
This is the project model:
# project.rb
class Project < ActiveRecord::Base
belongs_to :client
end
This is the client model:
# client.rb
class Client < ActiveRecord::Base
has_many :projects
end
And finally, the migration:
# 20110404155917_create_projects.rb
class CreateProjects < ActiveRecord::Migration
def self.up
create_table :projects do |t|
t.string :name
t.datetime :date
t.text :description
t.integer :client_id
t.timestamps
end
end
def self.down
drop_table :projects
end
end
Should be possible, right?
Can't see what I'm missing here..
Anyone got a suggestion?
Thanks!
Use
#projects = Project.where( :client_id => current_user.client.id)
or
#projects = Project.find_by_client_id(current_user.client.id)
or you could do
#projects = current_user.client.projects
Little bit cleaner perhaps?

Resources