Rails 3 sorting through parent association - ruby-on-rails

I have a fairly straightforward question in Rails 3 to which I can't seem to find the answer:
Let's say I have 2 models: Customer, Project.
A Customer has_many projects
Project belongs_to customer
Now I want to sort a list of projects by "customer name" using Active Record (doing it with a Ruby array is easy enough, but I imagine this will get problematic once the number of project records grows).
How do I go about doing this with ActiveRecord?

Project.joins(:customer).order('customers.name')

Related

Has_many through - Rails 5

I’m a rails newbie here and have this issue.
I have 3 models: Group, User, Subject, between Group and Subject I have a has_many through relation called GroupSubjects it works fine, the next is GroupUsers with a has_many through relation and works fine too, as new at this (like 1 mint learning rails) I want to assign a subject, with another view, not the new or edit templates, and with this view, and make the relation between Groups and Subjects, I want to save the user_id, group_id, and due date, in the GroupSubjects table.
I really need help, this has been a problem for at least 3 days.
Thanks for your help

Rails HABTM: Select everything a that a record 'has'

I have three tables: projects, technologies, and projects_technologies (a map from project IDs to/from technology IDs). I have two models: projects and technologies. Projects have and belong to many (HABTM) technologies and vice versa. Now I'm trying to get all the names (or active records, if there's a way to do that) of technologies that belong to a given project. Here's the SQL statement I've made, using 5 as the given project ID:
SELECT name FROM technologies WHERE id IN (
SELECT projects_technologies.technology_id FROM projects_technologies
WHERE projects_technologies.project_id = 5
);
I could just connect to the database and run the query, but since I already have the models set up with HABTM relationships, I'm wondering if there's a "Rails way" to execute this. I've been looking at this documentation, http://guides.rubyonrails.org/active_record_querying.html, but I can't figure out if and how I can apply that to this kind of query.
UPDATE
Turns out all I needed was this:
Project.find(5).technologies
The equivalent active record query would be
Technology.select('name').where("id IN (?)", ProjectTechnology.where("project_id = ?", 5).pluck(:technology_id))
Hope this helps!

Group Query in Rails involving associations

I have two tables (and associated models) in my Rails database with a one-to-many relationship.
billable_totals
---------------
id
project_id
adjusted_amount
projects
---------
id
project_type
The associated models are BillableTotal and Project with the following relationships:
BillableTotal belongs_to Project
Project has_many BillableTotals
I want to do a group query which outputs the project_type from projects table and the sum of adjusted_amount from billable_totals grouped by project_type. I am running into all sorts of problems. Both activerecord and Postgres keep complaining. Please advise on how to structure this query.
I think this should work:
Project.joins(:billable_totals).group(:project_type).sum('billable_totals.adjusted_amount')
I could at least run a query on that format in my own project and get reasonable results.

Adding categories to a Ruby on Rails application

I've had some issues with this before when creating applications and I think I'm starting to run into it again, hence I'm asking this on StackOverflow to save me a lot of time.
I've spent the last few weeks setting up a perfected product model for my system. The model performs exactly as I want it to and has several complex features (such as search via sunspot). I wanted to setup the category to product structure before I started this heavy development - however struggling with this kind of thing was just putting me off creating the application so I got straight into the product structure.
Now I've got the product model setup - what would be the easiest way to add a category ownership to encompass the products? (All products have a category_id column which store their father category id)
My plan is to have the category index to be a list of all the categories, the category show to be a list of the products inside that category and the product show being the view of the actual product. This would eliminate the product index and so I'll have to come up with a way to port the search feature (sunspot) from my index view to the category show somehow.
As for the actual listing of the products - I assume I'll have to do some kind of partial? (I don't know a lot about it).
Most basically, my relationships are planned to be:
category:
has_many :products
product:
has_one :category
My products then have a category_id column to store the ID of it's parent category.
Any tips on how to accomplish the relationships (category show to list the products etc)?
Best Regards,
Joe
Relationships like the one you're wanting are built into ActiveRecord support. Understanding the model relationships in Rails is critical to doing anything in Rails that's non-trivial, so study up.
Also, the relationship you're looking for is something like:
product:
belongs_to :category
category:
has_many :products

Rails ActiveRecord Relationships

How do the relationships magically function when only the models are altered?
If I want a "has__and___belongs___to__many" relationship, what should I name the table (so Rails can use it) that contains the two foreign keys?
Short answer: You can't just tell the models that they're related; there have to be columns in the database for it too.
When you set up related models, Rails assumes you've followed a convention which allows it to find the things you wrote. Here's what happens:
You set up the tables.
Following conventions in Rails, you name the table in a particular, predictable way (a plural noun, e.g. people). In this table, when you have a relationship to another table, you have to create that column and name it in another predictable way (e.g. bank_account_id, if you're relating to the bank_accounts table).
You write a model class inheriting from ActiveRecord::Base
class Person < ActiveRecord::Base
When you instantiate one of these models, the ActiveRecord::Base constructor looks at the name of the class, converts it to lowercase and pluralizes it. Here, by reading Person, it yields people, the name of the table we created earlier. Now ActiveRecord knows where to get all the information about a person, and it can read the SQL output to figure out what the columns are.
You add relationships to the model: has_many, belongs_to or has_one.
When you type something like, has_many :bank_accounts, it assumes a few things:
The name of the model that you relate to is BankAccount (from camel-casing :bank_accounts).
The name of the column in the people table which refers to a bank account is bank_account_id (from singularizing :bank_accounts).
Since the relationship is has_many, ActiveRecord knows to give you methods like john.bank_accounts, using plural names for things.
Putting all of that together, ActiveRecord knows how to make SQL queries that will give you a person's bank accounts. It knows where to find everything, because you followed a naming convention that it understands when you created the table and its colums.
One of the neat things about Ruby is that you can run methods on a whole class, and those methods can add other methods to a class. That's exactly what has_many and friends are doing.
This works because you are following "Convention over Configuration".
If you state that a customer model has many orders then rails expects there to be a customer_id field on the orders table.
If you have followed these conventions then rails will use them and will be able to build the necessary SQL to find all the orders for a given customer.
If you look at the development.log file when you are developing your application you will be able to see the necessary SQL being built to select all orders for a given customer.
Rails does not create tables without you asking it to. The creation of tables is achieved by generating a migration which will create/alter tables for you. The fact that you create a customer model and then state within it that it has_many :orders will not create you an orders table. You will need to do that for yourself within a migration to create an orders table. Within that migration you will need to either add a customer_id column or use the belongs_to: customer statement to get the customer_id field added to the orders table.
The rails guide for this is pretty useful

Resources