How to filter all ad by category name? - ruby

My use case is simple:
Get all ads that have a category name of params[:category_name].
Here are my model associations:
class Ad < ActiveRecord::Base
belongs_to :category
attr_accessible :anonymous, :celular, :name, :precio, :category_id
end
class Category < ActiveRecord::Base
has_many :ads
attr_accessible :name
end
Here is my controller code:
def by_category
#ads = Ad.where(:category => params[:category_name])
end
But it's not working as intended and I get an exception:
SQLite3::SQLException: no such column: ads.category: SELECT "ads".* FROM "ads" WHERE "ads"."category" = 'aeronautica'
How can I filter the ad objects by category name?

In your ads database you only have a column called category_id, so searching the ads database for a category name has no use.
Category.find_by_name(params[:category_name]).ads
This would show all ads for a category with the category_name that is in the params.

Ad.where(:category => {:name => params[:category_name]})

Ad.where(:category => Category.find_by_name(params[:category_name]))
params[:category_name] is only a string, whereas :category is an object of type Category.
Category.find_by_name
will give you a Category object, which you can compare with :category
Edit:
For this particular case, you could try the following, since you might've used category_id:integer instead of category:reference for creating the Ad model.
Ad.where(:category_id => Category.find_by_name(params[:category_name]).id)

Related

removing duplicate entry for csv import in ruby

while importing csv row i need to check wether this is duplicate entry or new entry.
my csv looks like this,
company,location,region,service,price,duration,disabled
Google,Berlin,EU,Design with HTML/CSS,120,30,false
Google,San Francisco,US,Design with HTML/CSS,120,30,false
Google,San Francisco,US,Restful API design,1500,120,false
Apple,London,EU,Design with HTML/CSS,120,30,false
Google,Berlin,EU,Design with HTML/CSS,120,30,false
Google,San Francisco,US,Restful API design,1500,120,false
Also the row value should be imported in different table whose association is like this
A Company:
can have multiple regions: US, EU and each region multiple branches, i.e. London, Berlin. Define a hierarchy to represent this logic.
has many Services. If there are more branches, they will all share the same services
can be disabled
A Service:
has a duration
has a price
can be disabled
if the company is disabled, all services are disabled.
for which i have implemented association like this
class Company < ApplicationRecord
has_many :regions
has_many :services
has_many :locations, through: :regions
end
class Region < ApplicationRecord
belongs_to :company
has_many :locations
end
class Location < ApplicationRecord
belongs_to :region
belongs_to :company
end
class Service < ApplicationRecord
belongs_to :company
end
How will I import this?
I am doing something like this
namespace :import do
desc "Import data"
task company: :environment do
CSV.foreach('lib/data/companies_data.csv', headers:true) do |row|
company = Company.create(:name => row["company"])
region = company.regions.create(:name => row["region"])
if region.id and company.id
location = company.locations.create(:name =>row["location"],
:region_id => region.id)
service = company.services.create(:name => row["service"],
:price => row["price"], :duration =>
row["duration"], :disabled =>row["disabled"])
end
end
end
end
How do I check wether a row is already present in database as it already contains associated table.
You can use .first_or_create. This will only create new db records if there is not a match on the previous ActiveRecord Relation call:
Model.where(some_unique_field: row['Unique Column']).first_or_create(row)
You can also pass a block to first_or_create as listed in the docs if you want to apply any additional logic to the CSV row ie model.price = row['price'] + fee

has_and_belongs_to_many model creation needed?

I have orders and items table. I also have a third table called orders_items. Which I learned on creating from the following link (2nd graph) http://www.tutorialspoint.com/ruby-on-rails/rails-models.htm
models/order.rb
class Order < ActiveRecord::Base
has_and_belongs_to_many :items, through: :item_order
end
models/item.rb
class Item < ActiveRecord::Base
has_and_belongs_to_many :orders, through: :item_order
end
[orders_items] table has the following:
integer :order_id
integer :item_id
Do I have to create a models/order_item.rb file to add:
belongs_to :order
belongs_to :item
If so what is the correct naming format that it should be?
Would the name for the model file [order_item.rb] correct to distinguish which table it refers to?
models/order_item.rb ??
class OrdersItem ??? < ActiveRecord::Base
belongs_to :order
belongs_to :item
end
From the API
The join table should not have a primary key or a model associated
with it. You must manually generate the join table with a migration
such as this
class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration
def change
create_table :developers_projects, id: false do |t|
t.integer :developer_id
t.integer :project_id
end
end
end
Specifies a many-to-many relationship with another class. This
associates two classes via an intermediate join table. Unless the join
table is explicitly specified as an option, it is guessed using the
lexical order of the class names. So a join between Developer and
Project will give the default join table name of “developers_projects”
because “D” precedes “P” alphabetically
In your case the join table name should be items_orders.
Your model must be named OrderItem. And you don't need belongs_to in this class. The file name (order_item.rb) is correct.
I think you need this relationship to fulfill your needs, except if orders is an item too
class Order < ActiveRecord::Base
has_many :items
end
and
class Item < ActiveRecord::Base
belongs_to :order
end

How to update a single field in has_many object

I am having a user object which has one-to-many relation with Address object. My class looks like this
class User
has_many :address
end
class Address
belongs_to :user
end
I want to update only city column in address table for a particular user.
How to do this?
I tried like this
#user.address.each do |a|
a.city = 'Alabama'
end
#user.save
But this is not working.
a.update_attributes(:city => 'Alabama')
This should work.
#user.address.update_all(:city => 'Albama')

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.

Rails 3.1 distinct find and missing attributes

class State < ActiveRecord::Base
has_many :cities
end
class City < ActiveRecord::Base
belongs_to :state
has_many :companies
end
class Company < ActiveRecord::Base
belongs_to :city
end
I'm trying to list all states, and their respective cities, that contain at least one company registered. My first try was the following query:
states = State.joins(:cities => :companies).includes(:cities)
Which works, but I end up getting duplicates if a state has more than one city with companies in it. I then changed the query to:
states = State.joins(:cities => :companies).includes(:cities).select("distinct(states.id)")
This query almost works. I have access to the cities (states[0].cities), and there are no duplicates, but if I try to access an attribute from the State object, I get the following error:
ruby-1.9.2-p290 :056 >states[0].name
ActiveModel::MissingAttributeError: missing attribute: name
How can I solve this?
Thanks in advance
Your select statement overrides the default (SELECT * FROM ... becomes SELECT distinct(state.id) FROM...) so the results don't include the columns of your state table (where the attributes are inferred from). Try changing your select method to the following:
.select("distinct(states.id), states.*")

Resources