Link To Parent From Nested Resource - ruby-on-rails

How on earth do I link up to a parent resource? My Companies have many Orders.
In my orders view, I have listed the associated company with
#order.company.name
However, when I try and use link_to, it links only to the order:
<%= link_to #order.company.name, company_path %>
In my routes, I have this:
resources :companies do
resources :orders do
resources :comments
end
end
What's the fix and where can I read more about it?

<%= link_to #order.company.name, company_path(#order.company) %>
You have to pass something to company_path so that it knows which Company to get the path for. That is distinct form companies_path which returns the path for all the companies.
/companies/12
vs
/companies

I guess you have a model orders and a model companies. so companies has_many orders. If you setup this with the usual way your records are all have id as identifier. In this case company.id is the record id if you want to make a link back to the company page.

Related

How do I create a form for an associated model?

I have a company model and a bank_account model.
company has_many bank_accounts and bank_account belongs_to company.
I have a route companies/:company_id/bank_accounts/new which generates a form:
<%= form_for #bank_account do |form| %>
(form elements here)
<% end %>
But when I get to that page, I get: undefined method bank_accounts_path
Here's my resource routes in routes.rb:
resources :companies do
resources :bank_accounts, module: :companies
end
and my nested bank_account_controller.rb in controllers/companies/
I need my form to post the entered data to the create action. Ruby should know this already right because I'm in the new action? But clearly it doesn't recognise the route.
Let me know if you need more information.
So I was changing a few things to match a similar model for company contacts. I knew these we're the same concept in my application so the same routing and form should work.
First I moved my nested bank_account_controller.rb out of companies and just placed it in app/controllers.
I moved all my bank_account views out of the nested bank_account folder inside views/companies to just app/views/bank_accounts.
I then removed the module companies from my routes.rb so I just had resources :bank_accounts within my companies resources.
Finally, I changed the form_for to: form_with (model: [#company, #bank_account], local: true) do |form| %>
Forms constantly trip me up as a somewhat newbie to RoR. I need to understand better what the difference is between for and with :)
You have nested resource, therefore you need
<%= form_for [#company, #bank_account] do |form| %>

Restricting a model to only view their own items in the has_many

So I'm trying to think about how to route my site and I need a little help. I have a business who can .build (as in business creates) buildings (sorry for the repetition haha) in a has_many. Each property has many something else.
I would like it so even though there will be more than one building, each business should only be able to view their own buildings, so if someone tries to alter a url, it would redirect home.
I have
resources :buildings
so as it is set up, anyone could just type in
host/buildings/whatever
I would like to redirect with an error if the building ID does not belong to the current_business (devise) it will redirect to their home page. each building has a business_id
Would I have to break the RESTful for this?
Thank you!
Assuming you have user_id in builduing resource:
buildings_controller.rb
def index
#buildings = current_user.buildings
end
def show
#building = current_user.buildings.find(params[:id])
end
buildings/index.html.erb
<% #buildings.each do |building| %>
<%= building.whatever_atribute %>
<% end %>
buildings/show.html.erb
<%= #building.whatever_atribute %>
With the above code when user will go to /buildings he will see only his buildings, and if he'll go to buildings/3 he will see this building if he owns it, in other case he will see a not found error that you can customize it with a redirect or display a styled page.

Ruby on Rails - Dropdown with Has Many relationship

I have four tables in my database. One is users, another is organizations. One user can have many organizations, and one organization can have many users. This relationship is stored in a third table, called user_organizations, with columns user_id and organization_id.
The fourth table is called organization_details, where I store additional, multi-row information about the organization.
What I want to happen is this: when a signed in user wants to add organization details to an org they are linked to through user_organizations, only the organizations they are linked to should appear in the dropdown list.
I am unsure of how to go about this. The system returns information about the signed in user through current_user, for example <%= current_user.first_name %>.
So I'm trying to do something like this:
collection_select(:organization_detail, :organization_id, Organization.where({id: current_user.id...something something about user_organization being here too}), :id, :name_and_state)
What is the best way to approach this? Thank you very much!
You should be able to use the built in association. Since User has_many Organizations you can call current_user.organizations like this:
collection_select(:organization_detail, :organization_id, current_user.organizations, :id, :name_and_state)
This assumes you have everything hooked up correctly in the models.
You should also check out the Rails Guide to associations if you are new to them.
current_user.organizations will do the trick.
your dropdown would look something like this:
<ul>
<%- current_user.organizations.each do |organization| -%>
<li><%= link_to organization.name, your_path_here %></li>
<%- end -%>
</ul>

Rails 4 site-wide filter records

Is it somehow possible to filter database records site wide? My models are league, match, team, player and detail. Now I would like when I enter the site and select a league that everything on the site is only displaying data for this specific league.
My relations are:
league has_many matches
match belongs_to team1
match belongs_to team2
team has_many players
player has_many details
Would that be possible?
You could do it like this:
Principle
If the league option is going to be the main decider of the content on your app, you might want to design around the league model
To do this, you'd make your root the league controller, and then show data based on the league's associated content
I.E instead of Team.joins(:league).where(league: "x"), you would do:
#Leagues
league = League.find(x)
league.matches
This would mean you could load the league directly from the database, making it much simpler for the user
Nested Resources
The alternative to this is to use the nested resources method that Michael Szyndel recommended in his comment. This would make it so you'd have to visit the URLs as follows:
domain.com/leagues/1/matches/2/teams/1
The benefit of this would be to DRY up your code, but it would add lots of extra levels to your system, which you may not want. I'll give an overview of what I'd look at below:
Code
#config/routes.rb
root to: "leagues#index"
#app/controllers/leagues_controller.rb
def index
league = params[:league] ? params[:league] : "0"
#league = League.find(league)
end
#app/views/league/index.html.erb
<%= form_tag('/') do %>
<%= select_tag 'league', options_for_select(League.all.collect {|u| [u.name, u.id] }) %>
<% end %>
<% #league.matches.each do |match| %>
<%= "#{match.team_1.name} vs #{match.team_2.name} : #{match.created_at}" %>
<% end %>
This would need to be re-factored & extended to include match details, make the "league" a session variable etc, but as the question might be closed, I thought I'd give you some ideas
The bottom line is that it comes down to how you want the app to function

How do I access information from multiple associated models in the Controller in an effiecient manner?

First, some background.
My application models are like so:
User has_many :subscriptions; has_many :courses, :through => :subscriptions
Subscription belongs_to :course, :user
Course has_many :subscriptions; has_many :users, :through => :subscriptions
Subscription is a join table used to store information such as state (:active, :inactive, :failed, :passed, :unpaid) as well as serve as a connector to all the information that comes with taking a course (such as the Grade model(not yet added), the Payment model(work in progress), etc).
I want to add the Payment model to store a history of payments on a subscription. Each payment can be for one or more subscriptions. So far, I've tried a Payment has_many :subscriptions, but I'm having trouble with the controller logic and I'm thinking maybe there's a better way to associate the models for "a Payment from a User on a Subscription to a Course."
Technically speaking, in a payment show action, I would need information from each of these models (course.name, user_id of user who paid, payment.amount, all of which are connected to a Subscription) and in a Payment.create action, I'd need to set the state of the subscription (that I can do).
If this is a logical/efficient way to associate the various models, how do I access the needed information(some information from each model course, user, payment, and subscription) in the Payment show action with minimal database calls? I'm using Rails 3.2/Ruby 1.9 and would like to stick with ActiveRecord/ARel instead of straight sql statements. I'm open to "you're doing it wrong" answers as well. If changing the associations will make it more efficient to access the tables from the controller, I'm open to that as well.
Do (in config/routes.rb)
resources :users do
resources :courses do
resources :subscriptions
end
end
Which will allow you to do #user.courses.subscriptions
If you want to go from courses back to users, for example, you can modify the route to be like
resources :users, :shallow => true do
#...
end
Edit:
For Payment, I would just do like you said has_many :subscriptions
When you show a payment. You would do something like
payment_history = Payment.find(params[:id])
#subscriptions = payment_history.subscriptions
Now you have the list of subscriptions for the link to that payment history, for example
You would loop in the view and display each subscription
<% #subscriptions.each do |subscription|%>
<%= subscription.payment.id %>
<%= subscription.users.size %>
<%= subscription.courses.size %>
<%= subscription.paying_user.name %> <!-- or whereever it exists-->
<% end%>
You need to make sure you have a route for that and restart the server after you change the routes
resources :payments, :shallow => true do
resources :subscriptions
end
#D3mon-1stVFW's answer set me on the right track to figure this problem out.
For the Payment show action, the queries would go something like:
#payment = Payment.find_by_id(params[:id])
#subscriptions = #payment.subscriptions.includes(:course, :user)
This will make it possible to access the course and user data associated with a subscription like so:
<% #subscriptions.each do |subscription|%>
<%= subscription.payment.amount %>
<%= subscription.user.email %>
<%= subscription.course.name %>
<%= subscription.state %>
<% end%>
For a payment new/create action where there is not yet a payment.id, the queries are slightly different:
#unpaid_subs = Subscription.where(:user_id => current_user.id).unpaid.includes(:course)
#payment = Payment.new
Where current_user is the user that is going to pay(create a new payment) and .unpaid is a scope on the Subscription model that looks like this:
scope :unpaid, -> { where('subscriptions.payment_id' => nil)}
And in the view, you can access the data in the same way as with the show view:
<% #unpaid_subs.each do |sub| %>
<%= sub.course.name %> | <%= sub.course.credits %><br />
<% end %>
My main point of confusion had been that I didn't know you could access parent associations from the child. Subscription belongs_to Courses, yet you can still do subscription.course.something.

Resources