Rails - how to reference namespaced table attributes in views - ruby-on-rails

I am trying to learn how to use namespaces in my Rails 5 app.
I have an organisation model and I have also made a series of nested models under the folder name "stance". One of those models is called overview.
The associations are:
Organisation.rb
has_one :overview, class_name: Stance::Overview
accepts_nested_attributes_for :overview, reject_if: :all_blank, allow_destroy: true
Stance::Overview
class Stance::Overview < ApplicationRecord
belongs_to :organisation, inverse_of: :overview
My controllers for stance resources are nested under a folder called stance.
My routes are:
namespace :stance do
resources :overviews
end
In my stance view partial, I am trying to render the attributes from the overview table.
I have tried:
<p><%= #overview.internal_explanation %></p>
<p><%= #stance_overview.internal_explanation %></p>
<p><%= #stance.overview.internal_explanation %></p>
<p><%= #stance::overview.internal_explanation %></p>
I want to display this partial in my organisation show. I am trying to do that with:
<%= render 'stance/overviews/internal', overview: #overview %>
But I can't figure out how to access the overview table. Do I need to add a reference to 'stance' in the associations?
I can see that in the console I need to write:
o = Stance::Overview.create(internal_explanation: "test")
o = Stance::Overview.first
but I can't see how to use that in the code itself.
I can see in the console that there is a record for this attribute.
The name of the table in the schema is "stance_overview".
My organisation controller has:
class OrganisationsController < ApplicationController
before_action :set_organisation, only: [:show, :edit, :update, :destroy]
def index
#organisations = Organisation.all
end
def show
end
def new
#organisation = Organisation.new
#organisation.build_overview
end
def edit
#organisation.build_overview unless #organisation.overview
end
def create
#organisation = Organisation.new(organisation_params)
respond_to do |format|
if #organisation.save
format.html { redirect_to #organisation, notice: 'Organisation was successfully created.' }
format.json { render :show, status: :created, location: #organisation }
else
format.html { render :new }
format.json { render json: #organisation.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #organisation.update(organisation_params)
format.html { redirect_to #organisation, notice: 'Organisation was successfully updated.' }
format.json { render :show, status: :ok, location: #organisation }
else
format.html { render :edit }
format.json { render json: #organisation.errors, status: :unprocessable_entity }
end
end
end
def destroy
#organisation.destroy
respond_to do |format|
format.html { redirect_to organisations_url, notice: 'Organisation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_organisation
#organisation = Organisation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def organisation_params
params.fetch(:organisation, {}).permit(:title, :comment,
overview_attributes: [:internal_explanation, :external_explanation ]
)
end
end
I have also tried defining the strong params for organisation as:
stance_overview_attributes: [:internal_explanation, :external_explanation ]
I keep getting an error that says:
undefined method `internal_explanation' for nil:NilClass
Can anyone refer me to materials to help me learn how to use namespaces in my app. I am trying to understand the fundamentals of this so that I can bank some knowledge. I am finding things through trial and error but not understanding what's actually required (although in this case, none of my attempts are working out).

To access Overview model(table) when you working not in Stance namespace you have to use Stance::Overview. If working for example in a controller that in Stance namespace you can use just Overview for access.
To get access from the relation you don't need any additional notation just #organisation.overview.
If I understand correctly in you case you have to declare your partial as
<%= render 'stance/overviews/internal', overview: #organisation.overview %>
and in the partial you have to use overview without #.

Related

Redirect to a post with specific name from user input in Ruby on Rails?

I am a newbie in RoR, thus sorry for stupid question :(
I have a Game model, with a code string. There is a welcome/index view in my app with a simple form_to input. I wish to redirect user to a Game with a specific code after he submits the form.
I understand that I should somehow combine a .where method and redirect_to in Welcome_controller, but I just can't figure out how...
Welcome_controller.rb:
class WelcomeController < ApplicationController
def index
end
def redirect
redirect_to ?game with a code that equals :param from input?
end
end
Welcome/index:
<h1>Let's join the game!</h1>
<%= form_tag redirect_path do %>
<%= text_field_tag(:param) %>
<%= submit_tag("Search") %>
<% end %>
routes.rb:
Rails.application.routes.draw do
get 'welcome/index'
resources :games
get 'games/index'
root 'welcome#index'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
game.rb:
class Game < ApplicationRecord
validates :name, :presence => true
end
games_controller:
PREFACE = ('A'..'Z').to_a << ?_
SUFFIX = ('0'..'9').to_a
PREFACE_SIZE = 2
SUFFIX_SIZE = 3
class GamesController < ApplicationController
before_action :set_game, only: %i[ show edit update destroy ]
# GET /games or /games.json
def index
#games = Game.all
end
# GET /games/1 or /games/1.json
def show
end
# GET /games/new
def new
#game = Game.new
#game.code = gen_name
end
def gen_name
PREFACE.sample(PREFACE_SIZE).join << SUFFIX.sample(SUFFIX_SIZE).join
end
# GET /games/1/edit
def edit
end
# POST /games or /games.json
def create
#game = Game.new(game_params)
respond_to do |format|
if #game.save
format.html { redirect_to game_url(#game), notice: "Game was successfully created." }
format.json { render :show, status: :created, location: #game }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #game.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /games/1 or /games/1.json
def update
respond_to do |format|
if #game.update(game_params)
format.html { redirect_to game_url(#game), notice: "Game was successfully updated." }
format.json { render :show, status: :ok, location: #game }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #game.errors, status: :unprocessable_entity }
end
end
end
# DELETE /games/1 or /games/1.json
def destroy
#game.destroy
respond_to do |format|
format.html { redirect_to games_url, notice: "Game was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_game
#game = Game.find(params[:id])
end
# Only allow a list of trusted parameters through.
def game_params
params.require(:game).permit(:code, :name)
end
end
In config/routes.rb you have defined resources :games, which creates default paths for CRUD actions. For the show action, which you are trying to get here, it would lead to /games/:id and the helper method would be game_path. You can also check this by running rails routes -c games command in the app directory. It should return all paths for games_controller
In the before_action callback for GamesController#show action, you are finding a Game object using Game.find(params[:id]). :id parameter is what you need to pass to the path helper that I mentioned earlier for the action to fire properly, so the path to a specific game would look like game_path(id: game.id). This will then automatically get converted to params. Alternatively, you can just pass the game object to the path helper and it will do the job for you like this: game_path(game)
Now in the WelcomeController#redirect action, you get the game code in params from the form submit. You need to first find the game for the submitted code like this:
game = Game.find_by(code: params[:param])
This should work if the code is unique for each game. Now that you have the correct game record, all you need is to redirect to the path that I've mentioned eariler:
redirect_to game_path(game)

Rails Form collection_select not saving to database

I am a rails newbie and building a little application to help with my work.
I have client, site and quote models and controllers with views set up.
I have created a form on the quote model that pulls data from the other two models in a collection_select field. The documentation on collection_select for rails that I have found is pretty bad. I want to take a client name and site name and associate/ display the name on the quote.
I have set this up in the form, but it does not save the data or show it.
I really want to understand the inputs for the collection_select as I am sure mine are probably wrong and causing the issue.
<%= f.collection_select :client, Client.all, :quote_client, :client_name , {:prompt => "Please select a client for the site"} %>
I did some research and learned this from #juanpastas here
My form looks like so
quotes/views/_form.html
<%= form_for(quote) do |f| %>
<% if quote.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(quote.errors.count, "error") %> prohibited this quote from being saved:</h2><ul>
<% quote.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %><div class="field">
<%= f.label :client %>
<%= f.collection_select :client, Client.all, :quote_client, :client_name , {:prompt => "Please select a client for the site"} %>
</div><div class="field">
<%= f.label :site_name %>
<%= f.collection_select :site, Site.all, :quote_site, :site_name , {:prompt => "Please select a site for the quote"} %>
</div><div class="field">
<%= f.label :quote_contact %>
<%= f.text_field :quote_contact %>
</div><div class="field">
<%= f.label :quote_value %>
<%= f.text_field :quote_value %>
</div><div class="field">
<%= f.label :quote_description %>
<%= f.text_field :quote_description %>
</div><div class="actions">
<%= f.submit %>
</div>
<% end %>
EDIT
Answers/clarifications
Quotes can only have one client and one site. The site would also have to belong to the client.
I have a list of clients called from the Client model via Client.all and a list of sites via the Site Model called via Site.all. I only need the name of one Client and one Site for each quote but want to be able to select in a cascading fashion. Select Client, then selects Site from those available for the Client.
Relations are set up between the three models like so:
class Quote < ApplicationRecord
belongs_to :site, optional: true
belongs_to :client, optional: true
has_and_belongs_to_many :assets
end
class Site < ApplicationRecord
has_attached_file :site_image, styles: { small: "64x64", med: "100x100", large: "200x200" }
do_not_validate_attachment_file_type :site_image
belongs_to :client , optional: true
has_and_belongs_to_many :assets
has_and_belongs_to_many :quotes
end
class Client < ApplicationRecord
has_and_belongs_to_many :sites
has_and_belongs_to_many :assets
has_and_belongs_to_many :quotes
end
Controllers
class QuotesController < ApplicationController
before_action :set_quote, only: [:show, :edit, :update, :destroy]
# GET /quotes
# GET /quotes.json
def index
#quotes = Quote.all
end
# GET /quotes/1
# GET /quotes/1.json
def show
end
# GET /quotes/new
def new
#quote = Quote.new
end
# GET /quotes/1/edit
def edit
end
# POST /quotes
# POST /quotes.json
def create
#quote = Quote.new(quote_params)
respond_to do |format|
if #quote.save
format.html { redirect_to #quote, notice: 'Quote was successfully created.' }
format.json { render :show, status: :created, location: #quote }
else
format.html { render :new }
format.json { render json: #quote.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /quotes/1
# PATCH/PUT /quotes/1.json
def update
respond_to do |format|
if #quote.update(quote_params)
format.html { redirect_to #quote, notice: 'Quote was successfully updated.' }
format.json { render :show, status: :ok, location: #quote }
else
format.html { render :edit }
format.json { render json: #quote.errors, status: :unprocessable_entity }
end
end
end
# DELETE /quotes/1
# DELETE /quotes/1.json
def destroy
#quote.destroy
respond_to do |format|
format.html { redirect_to quotes_url, notice: 'Quote was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_quote
#quote = Quote.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def quote_params
params.require(:quote).permit(:quote_client, :quote_site, :client_name, :site_name, :quote_contact, :quote_value, :quote_description)
end
end
class SitesController < ApplicationController
before_action :set_site, only: [:show, :edit, :update, :destroy]
# GET /sites
# GET /sites.json
def index
#sites = Site.all
#clients = Client.all
end
# GET /sites/1
# GET /sites/1.json
def show
#sites = Site.all
#clients = Client.all
end
# GET /sites/new
def new
#site = Site.new
end
# GET /sites/1/edit
def edit
end
# POST /sites
# POST /sites.json
def create
#site = Site.new(site_params)
respond_to do |format|
if #site.save
format.html { redirect_to #site, notice: 'Site was successfully created.' }
format.json { render :show, status: :created, location: #site }
else
format.html { render :new }
format.json { render json: #site.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /sites/1
# PATCH/PUT /sites/1.json
def update
respond_to do |format|
if #site.update(site_params)
format.html { redirect_to #site, notice: 'Site was successfully updated.' }
format.json { render :show, status: :ok, location: #site }
else
format.html { render :edit }
format.json { render json: #site.errors, status: :unprocessable_entity }
end
end
end
# DELETE /sites/1
# DELETE /sites/1.json
def destroy
#site.destroy
respond_to do |format|
format.html { redirect_to sites_url, notice: 'Site was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_site
#site = Site.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def site_params
params.require(:site).permit(:site_client, :client_name, :site_name, :site_image, :site_address, :site_contact)
end
end
class ClientsController < ApplicationController
before_action :set_client, only: [:show, :edit, :update, :destroy]
# GET /clients
# GET /clients.json
def index
#clients = Client.all
#sites = Site.all
end
# GET /clients/1
# GET /clients/1.json
def show
#clients = Client.all
#sites = Site.all
end
# GET /clients/new
def new
#client = Client.new
end
# GET /clients/1/edit
def edit
end
# POST /clients
# POST /clients.json
def create
#client = Client.new(client_params)
respond_to do |format|
if #client.save
format.html { redirect_to #client, notice: 'Client was successfully created.' }
format.json { render :show, status: :created, location: #client }
else
format.html { render :new }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /clients/1
# PATCH/PUT /clients/1.json
def update
respond_to do |format|
if #client.update(client_params)
format.html { redirect_to #client, notice: 'Client was successfully updated.' }
format.json { render :show, status: :ok, location: #client }
else
format.html { render :edit }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
# DELETE /clients/1
# DELETE /clients/1.json
def destroy
#client.destroy
respond_to do |format|
format.html { redirect_to clients_url, notice: 'Client was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_client
#client = Client.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def client_params
params.require(:client).permit(:client_name, :client_address, :client_phone, :client_email, :client_website)
end
end
Additions
You may notice I have tried to scale so that a client is called in a site and a site and a client is called in a quote.
First of all: I'm assuming you have relations set up between the three models! There has to be a has_many relation from quote to client and from quote to site.
There are two issues which could prevent your form from saving.
Firstly it is in how you create your collection_select. The third parameter in collection select is what will be sent to the controller. This should be an array of IDs (I assume a quote can have more than ONE client). I see you call it :quote_client. I'd rename it to :client_ids. In the end that's what you want to send to your controller: an array of IDs.
The second thing you have to take care of is your controller. It would be nice if you shared your controller code, but I assume you have a quotes_controller with a quote_params method inside it. It will probably look like this:
def quote_params
params.require(:quote).permit(:quote_contact, etc., etc.)
end
This controller method has to respond with your form_for, so every field in your form_for (like quote_contact) should be in the permit, otherwise it won't get saved. If you want to save an array of IDs, you have to tell this method you're expecting an array of IDs. You can do that like so: client_ids: [].
So your new quote_params method should look like this:
def quote_params
params.require(:quote).permit(:quote_contact, client_ids: [], site_ids: [], all_other_fields...)
end
I hope this answer provides you with your much needed help. If I need to clarify more: just ask :)
Cheers
EDIT: the answer above is still relevant for those who do want to save multiple records, but because you stated you do only want to save one record here is my updated answer:
The logic I summed up above stays roughly the same.
What you do not seem to understand at the moment, and what is (IMO) quite vital to understanding Rails applications is the way forms map to controllers and controllers map to the database. The method quote_params, as stated above, should permit all fields from forms you want to save to the database. This means all fields in your permit-part should BE in your database, otherwise they can't be saved. If you look closely at your quote table in the database, you will see that it has fields for client_id and site_id. These two fields hold the reference for your quote/client and quote/site associations. That is why your permit currently is not working, because you have quote_client and quote_site in place. The database does not have a quote_client or quote_site and hence when trying to save, doesn't update associations. The database does have client_id and site_id, so that's what you should pass into your quote params method.
This should of course correspond to the fields in your form_for. So you need change two things to make this work:
Change your two collection_selects and swap :quote_client for :client_id and :quote_site for :site_id.
Change your controller method to reflect the changes in your form_for. Here also you have to swap quote_site and quote_client for quote_id and site_id, like this:
def quote_params
params.require(:quote).permit(:client_id, :site_id, etc.)
end
The important thing to remember when using Rails MODELNAME_params methods (which we call strong parameters -> READ IT! http://edgeguides.rubyonrails.org/action_controller_overview.html)
is that both your form and your permit action should list the fields EXACTLY like they are in the database, otherwise the database won't understand and your record won't be properly saved.
I hope with this edit you'll figure it out.
Cheers

param is missing or the value is empty: module_list

I'm trying to enter a list of new modules and when I press 'new module list' which should take me to the form to fill out it throws up the error from the title. The application trace points at the bottom, the code inside 'def module_list_params' and also just above it where 'def set_student' is. I have no idea why it's doing it. I'm using ruby on rails.
class ModuleListsController < ApplicationController
before_action :set_module_list, only: [:show, :edit, :update, :destroy]
before_action :set_student, only: [:new, :create]
# GET /module_lists
# GET /module_lists.json
def index
#module_lists = ModuleList.all
end
# GET /module_lists/1
# GET /module_lists/1.json
def show
end
# GET /module_lists/new
def new
#module_list = #student.module_lists.new
end
# GET /module_lists/1/edit
def edit
end
# POST /module_lists
# POST /module_lists.json
def create
#module_list = #student.module_lists.new(module_list_params)
respond_to do |format|
if #module_list.save
format.html { redirect_to #module_list, notice: 'Module successfully created.' }
format.json { render :show, status: :created, location: #module_list }
else
format.html { render :new }
format.json { render json: #module_list.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /module_lists/1
# PATCH/PUT /module_lists/1.json
def update
respond_to do |format|
if #module_list.update(module_list_params)
format.html { redirect_to #module_list, notice: 'Module list was successfully updated.' }
format.json { render :show, status: :ok, location: #module_list }
else
format.html { render :edit }
format.json { render json: #module_list.errors, status: :unprocessable_entity }
end
end
end
# DELETE /module_lists/1
# DELETE /module_lists/1.json
def destroy
#module_list.destroy
respond_to do |format|
format.html { redirect_to module_lists_url, notice: 'Module list was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_module_list
#module_list = ModuleList.find(params[:id])
end
def module_list_params
params.require(:module_list).permit(:student_id, :title, :description, :credit_value)
end
def set_student
#student = Student.find_by(id: params[:student_id]) ||
Student.find(module_list_params[:student_id])
end
end
Rake routes screenshot
I believe your issue is the line before_action :set_student, only: [:new, :create]. set_student is being run when you go to the page with the form, but since there is no student_id included in the URL, it can't find anything to set it to.
To create a dependent object, there are two main ways: you can either have a form page tied to a specific parent object already, ie /students/4/module_lists/new, in which case submitting the form will create a module list tied to the student with an ID of 4. The other way is to have a general form not tied to any specific parent object, with some way of selecting a parent inside the form, eg a select or something. In that case the url would just be something like /module_lists/new.
If you want to go the first route, you'll want to nest the resources :module_lists inside of students. Check out the docs for how to do that, but it would basically look like
resources :students do
resources :module_list
end
And then in the link_to you click to go to that page, you'll need to pass in the student_id:
link_to 'Create Module List', new_student_module_list_path(#student)
For the second option, you can just remove :new from the before_action, change the new method to
def new
#module_list = ModuleList.new
end
And then add a way of picking which student to tie it to to the form.

Trouble creating my first association object: teachers in a school

Would like to create a teacher, within a school in the web browser. Unsure exactly what code I need to do this. Used scaffold to create school and controller and model to create teacher. My goal is to be able to add teachers, after I create a school.
School model
class School < ActiveRecord::Base
has_many :teachers
end
Teacher model
class Teacher < ActiveRecord::Base
belongs_to :school
end
School controller
class SchoolsController < ApplicationController
before_action :set_school, only: [:show, :edit, :update, :destroy]
# GET /schools
# GET /schools.json
def index
#schools = School.all
end
# GET /schools/1
# GET /schools/1.json
def show
end
# GET /schools/new
def new
#school = School.new
end
# GET /schools/1/edit
def edit
end
# POST /schools
# POST /schools.json
def create
#school = School.new(school_params)
respond_to do |format|
if #school.save
format.html { redirect_to #school, notice: 'School was successfully created.' }
format.json { render :show, status: :created, location: #school }
else
format.html { render :new }
format.json { render json: #school.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /schools/1
# PATCH/PUT /schools/1.json
def update
respond_to do |format|
if #school.update(school_params)
format.html { redirect_to #school, notice: 'School was successfully updated.' }
format.json { render :show, status: :ok, location: #school }
else
format.html { render :edit }
format.json { render json: #school.errors, status: :unprocessable_entity }
end
end
end
# DELETE /schools/1
# DELETE /schools/1.json
def destroy
#school.destroy
respond_to do |format|
format.html { redirect_to schools_url, notice: 'School was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_school
#school = School.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def school_params
params.require(:school).permit(:name)
end
end
Teachers controller
class TeachersController < ApplicationController
end
School/view/show
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #school.name %>
</p>
<%= link_to 'Edit', edit_school_path(#school) %> |
<%= link_to 'Back', schools_path %>
You can do this within either your school or teachers controller, you may want it in create, definitely in update. Assuming the school controller and that params includes a teachers name as :teacher_name.
def update
#school.teachers = Teacher.new(school_params[:teacher_name])
respond_to do |format|
... snip for brevity ...
end
end
I am assuming your database tables are already set up using [migrations].1
From the Teacher Side:
In your Teacher new page (your form) you'll need to have a selection box with the schools the Teachers can belong to, those Schools will have as values their IDs (from the Database). The Teacher model will have school_id as one of its attributes and once you got to your rails console and type something like School.first.teachers you'll get a list of all the teachers in that school.

RAILS: How to generate links for Grandchild Model using [#Grandparent, #Parent] notation (Grandparent shows as Nil)

I'm running across the following error when I try to show, edit, delete, or add a district:
undefined method `state_path' for #<#<Class:0x007f93a9e9df88>:0x007f93af11f8d8>
I'm expecting for it to generate a country_state_path link since I have link_to 'Back', [#country, #state] but for some reason it's only giving me state_path. If I use dot-notation instead doing #country.state I receive an nilClass error.
I'm using a Tree Structure for my models:
Country
State
District
If I enter country_state_path everything works fine. But I'd rather enter it using the model notation since that works in my State Model.
(Am I using the right terms? Please correct if not, I'm still new to Rails)
CODE
District Model
class District < ActiveRecord::Base
validates_uniqueness_of :name, scope: :state_id
before_destroy :check_for_schools
belongs_to :state
#has_many :schools, :order => 'name'
private
def check_for_schools
=begin
if schools.count > 0
self.errors[:base] << "Cannot delete district while schools exist."
return false
end
=end
end
end
District Controller
class DistrictsController < ApplicationController
# Allows JSON Queries
skip_before_filter :verify_authenticity_token
before_action :set_district, only: [:show, :edit, :update, :destroy]
before_filter :load_state
# GET /districts
# GET /districts.json
def index
#districts = #state.districts.all(:order => 'name ASC')
end
# GET /districts/1
# GET /districts/1.json
def show
end
# GET /districts/new
def new
#district = #state.districts.new
end
# GET /districts/1/edit
def edit
#state.districts.find(params[:id])
end
# POST /districts
# POST /districts.json
def create
#district = #state.districts.new(district_params)
respond_to do |format|
if #district.save
format.html { redirect_to [#country,#state,#district], notice: 'District was successfully created.' }
format.json { render action: 'show', status: :created, location: #district }
else
format.html { render action: 'new' }
format.json { render json: #district.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /districts/1
# PATCH/PUT /districts/1.json
def update
respond_to do |format|
if #district.update(district_params)
format.html { redirect_to [#state, #district], notice: 'District was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #district.errors, status: :unprocessable_entity }
end
end
end
# DELETE /districts/1
# DELETE /districts/1.json
def destroy
#district = #state.district.find(params[:id])
respond_to do |format|
if #district.destroy
format.html { redirect_to #state }
format.json { head :no_content }
else
format.html { redirect_to( #state, :notice => 'Unable to delete a state that has districts.') }
format.json { render json: #district.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_district
#district = District.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def district_params
params.require(:district).permit(:name, :state_id)
end
def load_state
#state = State.find(params[:state_id])
end
end
District "Show" View
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #district.name %>
</p>
<p>
<strong>State:</strong>
<%= #district.state_id %>
</p>
<%= link_to 'Edit', edit_country_state_district_path(#country, #state, #district) %> |
<%= link_to 'Back', [#country, #state] %>
The line that isn't working is the "link_to 'Back', [#country, #state].
You'll need to manually set #country in your show/edit/destroy methods, as #country is nil.
A note, though. Generally, it's best practice to only nest two deep. So:
Country
State
State
District
I know. I know. Don't shoot the messenger. Just passing the info along.
So I'd need to structure my routes like so:
NetworkManager::Application.routes.draw do
root to: "countries#index"
resources :countries do
resources
end
resources :states do
resources :districts
end
end
Instead of:
NetworkManager::Application.routes.draw do
root to: "countries#index"
resources :countries do
resources :states do
resources :districts
end
end
end
So, here's my end goal, maybe you have a better way to do this...
We setup schools across the country and each school has a variety of different network devices. The real purpose of this is to track what the network information is for each school, but I want to be able to organize it into
Countries -> States -> Districts -> Schools -> Networks -> Devices.
If I want to do that I'm guessing it's better to do
Countries
States
States
Districts
Districts
Schools
Schools
Networks
Networks
Devices
I want the person entering the information to be able to tell that this device is associated with this School A easily. And potentially even have the device be easily connected back to the district in case it has to be moved to a different school.

Resources