Data in loop from belongs_to relationship - ruby-on-rails

I have house with apartments (belongs_to house). The summary shows the house with the apartments with some info as short description and price range. The code i have is this(works fine)
- house.appartments.each do |a|
%li
%a.main_img
= link_to image_tag(a.attachments.first.file.url(:thumb), :height=>"93px", :width=>"135px", :class => "box"), apartment_path(a)
%br/
= link_to "#{a.name}", apartment_path(a), :class => "link_homepage"
Description: #{a.short_desc}
Price range: #{a.price_range}
I added a new model price with belongs_to relation to apartment. In this model/db the prices/rents data is stored of the apartments.
Question - Instead of a.price_range (apartment db-table) i want the data from the new price model/db-table in the summary.

If I'm understanding correctly, you have a model named something like House which has an association with Apartment which then has an association to a new model you made called something like ModelPrice? If so...
I assume in your new table ModelPrice you have a column for apartment_id or whatever the apartment ID column would be named in order to setup the association to the Apartment model.
Can you do a.model_price.price?
Of course, the names of each object would change based on the actual names of your new model/table name and the price column that is within it.

Related

How to use joint query in this association - Ruby on Rails

I am working in ruby 2.1.5 and rails 3.2.1. I want to list all the company in grid which is associated to company_name = John
Company table:
company model:
has_many :partner_relationships, :class_name => "CompanyRelationship",:foreign_key => 'partner_id',
company_relationships table:
I want to get all the company information from company table where company.id = partner_id. I tried the below query
Company.joins(:partner_relationships).where('company_relationships.partner_id' => company.id)
This is returning 3 set of same data that is <#id:2, company_name:John, description:I am John#>
I want to return the records as follows <#id:1, company_name:Jose, description:I am Jose#>, <#id:3, company_name:George, description:I am George#>,..<#id:5, company_name:Alwin, description:''#>
Please help me in solving this.
Shouldn't you use "partner_id"?

ActiveScaffold or ActiveRecord how to search on an associated model's column

I have following models
Customer: name:string, phone:string
has_many :sales
Sale: amount:float, item_name:string
belongs_to :customer
Now in ActiveScaffold I get a simple single line input box to search for sales.
What I need to do is, be able to search sales by the customer name as well.
There should be a way to do this with ActiveScaffold, or atleast with native active record functionality.
One way I can think of is, adding the customer name as a column and populate it along with sale while it is created.Not sure what the best approach to achieve this should be.
Edit: Adding info from comment:
Is it possible to define something like
Sales
searchable_columns :amount, :association => {:customer => name}, :as => yumyum_column
now when i search by
Sale.where(:yumyum_column => 1000)
or
Sale.where(:yumyum_column => "Customer name")
both will return the same record.
Try something like this:
# Sales Controller
config.columns[:customer].search_sql = "customers.name"
config.search.columns = [:item_name, :customer] # Search by sale's item_name or customers's name.
To show the customer name in the list of results try something like:
# Customer model
def to_label
name
end
# Sales Controller
config.list.columns = [:item_name, :customer]
For more info, see the API: Search page
If you have (and you should have) a customer_id in your sales table, then you can query sales with any customer attribute you like with a simple join:
Sales.joins(:customers).where(:'customers.name' => :john)
which translates to the following SQL
"SELECT `sales`.* FROM `sales` INNER JOIN `customers` ON `sales`.`customer_id` = `customers`.`id` WHERE `customers`.`name` = 'john'"

Implementing model subclasses - the correct way

I have an Event model and I want to create two subclasses of it: FixedEvent and TasksEvent
Event model has these attributes:
uid :string
title :string
starts_at :datetime
ends_at :datetime
FixedEvent inherits from Event and also has this attribute:
all_day :boolean
TasksEvent inherits from Event and has these attributes:
task_id :integer
occurrence :integer
(Occurrence attribute is a special way for tasks to say: Do this task two/three/x times. Occurrence represents which occurrence of the task this is (e.g. this is second time user is performing the task))
I spent the whole day yesterday reading about Single Table Inheritance and Polymorphic Associations and I'm still not 100% sure what's the correct way to implement this in Rails.
Single Table Inheritance leaves me with lot of null values in my database as I'll end up having one table with: uid, title, starts_at, ends_at, all_day, task_id, occurence, type.
Will this behaviour make server response slower as rails will fetch more (null) data for every event query?
On the other hand, Polymorphic Associations look more like I'm adding some extra functionality to model, rather than subclassing it. Also it creates more tables (three in this case) in the db:
events:
id, uid, title, starts_at, ends_at,
created_at, updated_at,
event_type_id, event_type_type
(suggest better naming for type if something comes to your mind)
fixed_events:
id
all_day
created_at
updated_at
tasks_events:
id
task_id
occurrence
created_at
updated_at
Will this behaviour make server response slower as rails will have to do several db joins every time I want to fetch all FixedEvent/TasksEvent attributes?
Also, how can I create new ActiveRecord objects using STI and/or Polymorphic Associations?
I tried something like this for Polymorphic Association:
def new
#fixed_event = FixedEvent.new
#fixed_event.build_event
respond_to :html
end
And then in form_for:
= f.fields_for :event do |event|
.field
= event.label :title
= event.text_field :title
.field
= event.label :starts_at
= event.datetime_select :starts_at
.field
= event.label :ends_at
= event.datetime_select :ends_at
.field
= event.label :description
= event.text_field :description
.field
= event.label :uid
= event.text_field :uid
I had to add these two things in FixedEvent and TasksEvent and it worked:
attr_accessible :event_attributes
accepts_nested_attributes_for :event
Is this the correct way to do it or STI is better (or any other solution)?
You want to go with STI as it is simple and will be much faster than loading associations. Loading a bunch of null values is nothing to be concerned about, performance wise. On the other hand, joins (or even eager loading) is much more likely to cause performance problems once your events table contains tens of thousands of entries.
If selecting all of the columns ever becomes a problem for you, you can always just select a subset of all columns with:
FixedEvent.select('foo, bar').all
It seems like you already understand STI so I don't have to teach you how to do it here. It's simple, really—just create the "events" table with "type" column, and Event class, then subclass it.

Using single model for multiple tables

I am wondering if it is possible to combine columns from of different tables and use it as one model in Rails. I have two tables below, one holds generic columns and other specialize columns.
posts
--------------
id
title
description
created_at
updated_at
jobs
--------------
post_id
category_id
job_type
duration
salary
In Rails model,
class Job < ActiveRecord::Base
#
end
On saving Job model should save columns in respective tables. I thought about using single table inheritance (STI) but look like I can't split columns in multiple tables with this approach.
Hello you just need to use accepts_nested_attributes_for, then you can fill column of post on saving jobs using the posts_attributes key.
Adding posts to job
job[posts_attributes] = [{ :title => "test", :description => "Lorem ipsum"}]
Deleting posts from job
job[posts_attributes = [{ :id:20, :_destroy => true}]
Hope that will help you ;)

How to create links between two tables

Ok so I'm starting on normalising my database. Currently I have one model "Products" which is populated with about 60,000 products via a data feed (XML), which contains a product with a category name and a merchant name. I want to split these into 3 models; products, categories and merchants.
Each product has one category and one merchant so the natural idea is to create these models:
category_id | category_name
merchant_id | merchant_name
I can work out the code to associate between the models i.e. has_one, belongs_to etc but I'm struggling to work out to automatically associate a new Product with a category and a merchant programatically.
I've seen examples in books where your start with an empty database and that seems pretty straightforward. However, I'm starting off with a full database and a list of Category names.
Here is my product creation statement which is working great:
Product.create(:name => node.xpath("./text/name/text()").inner_text.downcase,
:description => node.xpath("./text/desc/text()").inner_text,
:brand => node.xpath("./brand/text()").inner_text,
:merchant => node.xpath("../#name").inner_text,
:category => node.xpath("./cat/text()").inner_text.downcase,
:price => "£" + node.xpath("./price/btext()").inner_text)
Would I need to do something like this, see the :category line, (i know the following is wrong btw!)...
Product.create(:name => node.xpath("./text/name/text()").inner_text.downcase,
:description => node.xpath("./text/desc/text()").inner_text,
:brand => node.xpath("./brand/text()").inner_text,
:merchant => node.xpath("../#name").inner_text,
:category => << Category.find_by_name(node.xpath("./cat/text()").inner_text.downcase),
:price => "£" + node.xpath("./price/btext()").inner_text)
Any ideas? Does this even make sense!?
Assuming the columns are called category_name and merchant_name, and you've set up the associations on Category and Merchant, you could do something like this:
Product.all do |product|
product.category = Category.find_or_create_by_category_name(product.category_name)
product.merchant = Merchant.find_or_create_by_merchant_name(product.merchant_name)
product.save!
end
It will take a while, so for large datasets you might need a better solution.
So would this actually set the :category value in the products table to a category_id or set the value to the category_name?
.find_or_create_by does a find on the attribute and returns the matching row, or creates one if it does not exist. When creating the association via `.category=, Rails will set the foreign key to match the id of the row in the categories table.
So to answer your question more directly:
Product.create(:category=>Category.find_or_create_by_name("Magic Beans"))
is like doing this:
category = Category.find_by_name("Magic Beans")
if category.nil?
category = Category.create(:name=>"Magic Beans")
end
product = Product.new
product.category = category
product.save
where the penultimate step sets the foreign key category_id to the value category.id. By convention associations are set up such that the foreign key is the model name suffixed with _id, so your products table should have both category_id and merchant_id.

Resources