inherited_resources and multiple belongs_to without nesting - belongs-to

Let's get down to brass tacks.
Rails: 2.3.11
I have a controller using inherited_resources to reference two separate and non-nested resources.
My controller is as shown:
class Tools::DeploymentLinesController < ToolsController
inherit_resources
belongs_to :deployment
belongs_to :ticket
end#Tools::DeploymentLinesController
However, inherit_resources is assuming that the belongs_to :ticket is a nested resource of deployment.
Is there any way of using two belongs_to in my controller without nesting? Or do I need to write out my own business logic to account for a missing inherited_resources association?

You should be able to use:
belongs_to :deployment, :ticket

Related

rails multiple has_many relationships between the same models

I'm trying to figure out the best way to model a many-to-one relationship in rails where there are multiple scopes to the relationship.
An example would be a restaurant has-many photos. I want to be able to call
restaurant.lounge_photos
and receive only the lounge photos,
but also be able to call
restaurant.food_photos
and receive just the food photos.
The two methods I can think of are:
to use multiple joins table, and a has_many to has_one relationship for each type of photo.
to add a 'type' attribute to the photo model and write a scoping method.
Both of these seem a bit clunky to me.
Is there a better solution here?
I think you have to go has_many and Single Table Inheritance(STI), as follow.
Make association with restaurant and photo
class Restaurant < ActiveRecord::Base
has_many :photos
end
class Photo < ActiveRecord::Base
belongs_to :restaurant
end
Then you have to use STI in Photo model. The reason is that you have almost all fields are common for lounge_photos and food_photos.
OR
Using scope directly you can differentiate it and achieve your goal.
For more details of use STI you can refer this link.
This is one way, using a type column
has_many :food_photos,
class_name: 'Photo',
foreign_key: :restaurant_id,
-> { where(type: 'food') }
has_many :lounge_photos,
class_name: 'Photo',
foreign_key: :restaurant_id,
-> { where(type: 'lounge') }

Return two tables, nested together, with one request

I have a project management app with Projects, Tasks and Assignments.
Project
has_many :tasks
Task
belongs_to :project
has_many :assignments
Assignment
belongs_to :task
belongs_to :user
I want to be able to GET all of a Project's Tasks and Assignments with just one request.
Currently I have to request each Task's Assignments, which could be very inefficient if a user has more than just a few Tasks.
If you do something like this, Rails will figure out the best queries to run
# Assuming params[:id] is the project id.
#project = Project.includes(:tasks => :assignments).find(params[:id])
So when you ask for #project.tasks and the loop through each task with task.assignments, the associations are already loaded.
Add a has many through to the Project model like so:
has_many :tasks
has_many :assignments, through: :tasks
Now you'll be able to call #project.assignments to get ALL assignments of that project or #project.assignments.uniq to list unique assignments (that don't repeat) in the event that an assignment would be under two tasks if you expand your associations to include that functionality.

How to implement has_many :through relationship in rails with this example

i've been searching through similar questions but i still don't get how implement this relationship. I have of course three models :
class Recetum < ActiveRecord::Base
attr_accessible :name, :desc, :duration, :prep, :photo, :topic_id
has_many :manifests
has_many :ingredients, :through => :manifests
end
class Ingredient < ActiveRecord::Base
attr_accessible :kcal, :name, :use, :unity
has_many :manifests
has_many :recetum, :through => :manifests
end
class Manifest < ActiveRecord::Base
attr_accessible :ingredient_id, :quantity, :receta_id
belongs_to :recetum
accepts_nested_attributes_for :ingredient
belongs_to :ingredient
end
Recetum would be a recipe (typo when scaffolding), this recipe may have one or more ingredients (already on the db). So when i create a new Recetum, i need the new recetum to be created and one record inserted in manifest for each ingredient entered by the user.
I would need some help now with views and controllers, how do i create the form for recetum with fields for the ingredients and more important what do i have to modify recetum controller.
Any suggestions or help would be very much appreciated as this part is crucial for my project, thanks in advance.
You have a couple options, and mainly they depend on what you want to do in your view. Do you want to display a set number of max_ingredients or do you want it to be completely dynamic? The dynamic case looks better for the user for sure, but it does make for some more complicated code.
Here is a good RailsCast which explains how to do it dynamically via JavaScript:
http://railscasts.com/episodes/74-complex-forms-part-2
Unfortunately, not everyone runs with JavaScript enabled so you may want to consider doing it the static way.
Firstly, I don't think you need accepts_nested_attributes_for in your Manifest model. However, I do think you need it in your Recetum model. If you're going the static route, you'll probably want to set a reject_if option too.
accepts_nested_attributes_for :manifests, reject_if: :all_blank
Once you do this, you'll need to add manifests_attributes to your attr_accessible.
With the static route, you'll need to prebuild some of the manifests. In your new controller you'll want something like this:
max_ingredients.times do
#recetum.manifests.build
end
In your edit and the error paths of your create and update, you may want:
(max_ingredients - #recetum.manifests.count).times do
#recetum.manifests.build
end
Finally, your view will need some way to set the ingredient. I'll assume a select box for now.
f.fields_for :manifests do |mf|
mf.label :ingredient_id, "Ingredient"
mf.collection_select :ingredient_id, Ingredient.all, :id, :name
You'll want to add some sort of formatting through a list or table probably.
Hopefully, that's enough to get you started.

Undefined Method on has_many :through

I have three models:
Class Project < ActiveRecord::Base
has_many :tasks
has_many :tags, :through => :tasks
end
Class Tasks < ActiveRecord::Base
belongs_to :project
has_and_belongs_to_many :tags
end
Class Tags < ActiveRecord::Base
has_and_belongs_to_many :tasks
has_many :projects, :through => :tasks
When I open up console, I can get my Project and Task information as expected:
Tag.find(1).projects
Tag.find(1).tasks
If I want, I can get all the tasks for each project regardless of the tag:
Project.find(1).tasks
For whatever reason, I can't access tasks if I get projects by tag...
something = Tag.find(1).projects
something.tasks
...I get the error:
undefined method `tasks' for #<ActiveRecord::Relation:0x007feae4af0e70>
I've looked for a couple hours and can't find anything that corrects this problem. Based on everything I've found, it should be working... but it's not.
I'm using Rails 3.2.3.
Shouldn't Tag.find(1).tasks give you the same result?
Anyway, the problem you're facing is that you're trying to retrieve an association from a Relation object instead of an instance of your model. Relations can be used to chain query conditions, but you can't directly reference associations from them. So, to get your example working, you'd need to do
p = Tag.find(1).projects.includes(:tasks)
Then reference tasks like this: p[0].tasks.
However I'd just make sure that Tag.find(1).tasks will generate the same SQL and ultimately return the same collection of tasks.

I need to specify a field name different than the table for association

Given I have an Artifact model and a User model: I would like to define two Artifact fields, opened_by and assigned_to, who values are User ids and inherit all of the proper association methods.
What is the proper belongs_to or has_one or has_many options I should set?
The goal is to be able to reference the user's name through the statement hld.assiged_to.name where hld is an artifact.
Thanks for the help. I've gotten myself confused with terminology with all of the reading i've done on the problem.
The following is what I determined was correct.
class Artifact < ActiveRecord::Base
belongs_to :project
belongs_to :opened_by, :class_name => 'User'
belongs_to :assigned_to, :class_name
=> 'User'
The first argument in the belongs_to specifies the field to reference. The second indicates the model/class to use as the reference.