Trying to do: I have an application that has 3 business categories: Business Development, Business Financial, And Business Admin.
I have an index view, localhost:3000/categories, which displays links to all of the above business categories.
They link to the new action, and the new view. Within that view, I have the following form code:
New.html.erb
<div align="center">
<h1>What are your important <%= #category.bizdev %> Action items?</h1>
<%= form_for #category do |f| %>
<p>
<p>Store Answer Below:</p>
<%= f.text_field :name, :size => 40, :style => 'height: 40px' %>
</p>
<p>
<%=f.submit 'Save action item' %>
</p>
<% end %> </div>
On the line: <h1>What are your important <%= #category.bizdev %> Action items?</h1>
I am trying to have the line list 1 of the 3 business categories (Business Development, Business Financial, Business Admin).
I've tried to create relationships between models: name, and category.
I cannot get the respective business category to display on the new view, for the form. Then, I need the form to submit the data to the respective category view (which I've been trying to do).
Categories controller:
class CategoriesController < ApplicationController
def index
#categories = Category.all
end
def new
#category = Category.new
#bizdev = Name.new
Name.#bizdev = "Business Development"
end
def create
#category = Category.new(category_params)
#category.save
redirect_to facilitates_path
end
def show
#category = Category.find(params[:id])
end
def destroy
end
private
def category_params
params.require(:category).permit(:answer)
end
end
Name Model
class Name < ActiveRecord::Base
belongs_to :category
end
CategoriesHelper
module CategoriesHelper
def bizdev
bizdev = Name.new
Name.bizdev = "Business Development"
end
end
Category Model
class Category < ActiveRecord::Base
has_many :names
end
Index View
<h1>Select A Business Category To Begin Identifying Action Items</h1>
<ol><li><%= link_to 'Business Admin', 'new' %></li><br><br>
<li><%= link_to 'Business Development/Marketing', 'new' %></li><br><br>
<li><%= link_to 'Financial', 'new' %></li>
</ol>
<%= link_to 'Store random action items', new_facilitate_path %><br><br>
<%= link_to 'See a list of already stored action items', facilitates_path %>
Routes.rb
Rails.application.routes.draw do
resources :facilitates
resources :categories
root 'categories#index'
get 'show' => 'facilitates#show'
get 'index' => 'categories#index'
get 'new' => 'categories#new'
get 'bizadmstor' => 'categories#bizadmstor'
get 'bizdevstor' => 'categories#bizdevstor'
get 'bizfinstor' => 'categories#bizfinstor'
get 'bizadmshow' => 'categories#bizadmshow'
get 'categories/show' => 'categories#show'
get 'categories/new' => 'categories#new'
This Name.#bizdev obviously wrong. I guess you are trying to do next: #category.names << #bizdev.
Helper also incorrect:
bizdev = Name.new
bizdev.name = "Business Development" # i guess you have name property of this model
In general - Name is not an Instance of the class, it's class itself. And you can define its attributes, you can do this only for some instance of a class, like bizdev in this example.
In your example, you don't need a class Name, you need a property name for the class Category. Or if you what that it should be a class, also it should have property name, to return it. This #category.bizdev will return a class, not some value. Should be #category.bizdev.name or #category.bizdev if bizdev is a property.
Figured it out myself - created, in Category model:
def name
"Business Development"
end
And then in view, called: #category.name
So - I had to create a method within my category model, called name, that simply writes "Business Development." Then, I called it via: #category.name in the new view.
Related
So I have the models contract and employee. And from an employee's show html I want to be able to add a contract for that particular employee.
Here is the line from my show html
<%= link_to 'Add Contract', new_contract_path(#employee) %>
and my create function in contracts controller
def create
puts "HERE IS"
puts params[:id]
puts "END"
#create contract here for employee
end
EDIT
After farhan's suggestions this is now what my code looks like
def new
#contract = Employee.find_by_id(params[:employee_id]).contracts.new
end
def create
#employee = Employee.find_by_id(params[:employee_id])
#contract = Employee.find_by_id(params[:employee_id]).contracts.build(contract_params)
...
end
my new.html
<h1>New Contract</h1>
<%= render 'form', contract: #contract%>
<%= link_to 'Back', employee_contracts_path(employee_id: #employee) %>
and my _form.html
<%= form_for(contract) do |f| %>
...
<% end %>
but if i got to the url empoyees/1/contracts/new rails says
routes
Run rake routes in your terminal and you will see that new_contract_path(#employee) it is looking for a form with action new after submitting that form, it goes to create action. Also, if you want nested routes then it should be
resources :employees do
resources :contracts
end
and you need to create a form named new.html.erb.
Update
After updating your routes.rb, your path helpers will change too,
in your view,
<%= link_to 'Add Contract', new_employee_contract_path(employee_id: #employee) %>
in your controller,
def create
#assuming Employee has_many contracts
contract = Employee.find_by_id(params[:employee_id]).contracts.build(contract_params)
if contract.save
#success case
else
#failure
end
end
def new
#contract = Employee.find_by_id(params[:employee_id]).contracts.new
end
private
def contract_params
#permit required params
end
How can I best implement this feature: As an admin, I can assign a Resident Manager to a Hall.
I have a User model with a namespace routing for the admin -I intend on having another namespace routing that would hold the functions of the RM-
I have a Hall model.
Since its a many-many relationship between the above to models, I have a Management join model which contains only user_id and hall_id columns.
I know implementing the above feature, entails creating a new record in the management table but I don't know how to do it. I didn't think using a form (management#new) would solve this because the admin should not know the user_ids/hall_ids...
BELOW IS WHAT I HAVE TRIED TO DO BUT I CAN'T GET IT RIGHT
When the admin gets to the user index page, s/he should see a link for Hall Assignment for each user. This link leads to the management show page for that particular user, which would show the list of halls assigned to that user and also the show all the other remaining halls that isn't assigned to the user. So, either clicking an ADD button or on the hall's name should add it to that user's assigned halls list which is on the same page.
Management#show page
<h2><%= #user.email %>'s assigned halls</h2>
<% #user.managements.each do |management| %>
<%= management.hall.name %>
<% end %>
<p> HALL LISTS </p>
<ul>
<% #halls.each do |hall| %>
<li><%= hall.name %> <%= button_to "Add" %> </li>
<% end %>
</ul>
Here's is my Management controller
class Admin::ManagementsController < ApplicationController
def index
#managements = Management.all
end
def show
#user = User.find(params[:id])
#halls = Hall.all
end
def create
#management = Management.create(managements_params)
redirect_to admin_management_path
end
private
def managements_params
params.
require(:management).
permit(user_id: params[:user_id], hall_id: params[:hall_id])
end
end
And here's a piece of what my routes file looks like:
namespace :admin do
resources :users, only: [:index, :update]
resources :halls, only: [:index, :new, :create]
resources :managements, only: [:index, :new, :create, :show] do
resources :halls, only: [:index]
end
end
Your "add" button is just a mini form (with mostly hidden fields). You can instead just make it an actual form (with the submit-button having the text "Add") and the id-values filled in from the item on the page... it just points to the same routes that you'd normally point the form that you'd find in the new template.
if you want more detail, then show us the code that you have written (rather than a verbal description of it).
Edit:
Ok, so you'd put a button on the page like this
<ul>
<% #halls.each do |hall| %>
<li><%= hall.name %> <%= button_to "Add", managements_path(management: {user_id: #user.id, hall_id: hall.id}, method: :put ) %> </li>
<% end %>
</ul>
Notice the managements_path - you might need to check that that routing is correct (check it against what is in rake routes). Note that you're passing in the user id and the hall id, and that you must set the method to "put" on the button.
First things first -
How can I implement a 'create' action without 'new' action
It's relatively simple to do - you will need a create action somewhere, but a new action is just a way to build the respective ActiveRecord object for your controller.
If you do this in another action, you just have to make sure you point the form to the correct create action (and that create action to redirect back to
--
New / Create
Here's how you could handle the new / create actions in different controllers, as an example for you:
#app/controllers/users_controller.rb
Class UsersController < ApplicationController
def index
#hall = Hall.new
end
end
#app/controllers/halls_controller.rb
Class HallsController < ApplicationController
def create
#hall = Hall.new hall_params
redirect_to users_path if #hall.save
end
private
def hall_params
params.require(:hall).(:hall, :attributes, :user_id)
end
end
This will allow you to show the following:
#app/views/users/index.html.erb
<% #users.each do |user| %>
<%= link_to user.name, user %>
<%= form_for #hall, url: hall_path do |f| %>
<%= f.hidden_field :user_id, value: user.id %>
<%= f.text_field :x %>
<%= f.submit %>
<% end %>
<% end %>
--
Fix
ADD button or on the hall's name should add it to that user's assigned halls list
For this, I don't think you'd need a create action in the "traditional" sense - it will be more about adding new halls to a user's current halls. This is much different than creating a new hall itself:
#config/routes.rb
namespace :admin do
resources :users do
post "hall/:id", to: :add_all #=> domain.com/admin/users/:user_id/hall/:id
end
end
#app/controllers/admin/users_controller.rb
Class UsersController < ApplicationController
def add_hall
#user = User.find params[:user_id]
#hall = Hall.find params[:id]
#user.halls << #hall
end
end
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :user_halls
has_many :halls, through: :user_halls
end
#app/models/hall.rb
Class Hall < ActiveRecord::Base
has_many :user_halls
has_many :users, through: :user_halls
end
#app/models/user_hall.rb
Class UserHall < ActiveRecord::Base
belongs_to :user
belongs_to :hall
end
This uses the ActiveRecord collection methods to make this work, to which you'll be able to provide the following:
#app/views/users/index.html.erb
<% #users.each do |user| %>
<%= link_to user.name, user %>
<%= button_to "Add Hall Test", user_add_hall_path(user, 1) %>
<% end %>
I am trying to get a better handle on Rail's nested resources, and made a test app with models School and Class. In my routes.rb file, I have:
resources :schools do
resources :classes
end
With the following models relationship for School and Class:
class School < ActiveRecord::Base
attr_accessible: name
has_many :classes
end
and
class Class < ActiveRecord::Base
attr_accessible: name, school_id
belongs_to :school
end
I am having difficulty getting the school_id associated with the posts created under an URL like /schools/1/posts/new. More precisely, I would like to define a helper method like current_school that could take the first half of the URI where it contains the school_id, to allow me to write functions in the controller like current_school.posts.all that will automatically pull all the posts associated with school_id = what is in the URL. Thanks!
*Edit
Here is what I have in ClassController:
class ClassesController < ApplicationController
def index
#classes = current_school.classes.all
end
def new
#class = current_school.classes.build
end
def create
#class = current_school.classes.build(params[:post])
if #class.save
redirect_to root_path #this will be further modified once I figure out what to do
else
redirect_to 'new'
end
end
private
def current_school
#current_school ||= School.find(params[:school_id])
end
end
And in the new.html.erb file:
<div class="span6 offset3">
<%= form_for([#school, #class]) do |f| %>
<%= f.label :name, "class title" %>
<%= f.text_field :name %>
<%= f.submit "Create class", class: "btn btn-large btn-primary" %>
<% end %>
</div>
When you nest your resources, you get several helper methods for free as explained here. The method you're looking for would be written as one of:
new_school_class_path(#school)
new_school_class_path(#school_id)
While your classes index page would be:
school_classes_path(#school)
school_classes_path(#school_id)
In your ClassesController, you would do something like:
def index
#classes = current_school.classes
end
def new
#class = current_school.classes.build
end
private
def current_school
#current_school ||= School.find(params[:school_id])
end
I have a model named Order and another model named Member and when I try to display fields from the Members model in my Orders view it doesn't even show when using the fields_for tag. Heres what my code looks like.
order model
class Order < ActiveRecord::Base
has_many :members
end
member model
class Member < ActiveRecord::Base
belongs_to :order
end
orders controller
class OrdersController < ApplicationController
def new
#order = Order.new
3.times { #order.members.build }
#title = "Order Form"
end
def create
#order = Order.new params[:order]
if #order.save
flash[:notice] = "Your order has been created"
redirect_to orders_path
else
#title = "Order Form"
render 'new'
end
end
end
The issue is in my orders view:
<% for member in #order.members %>
This displays 3 times but the information below doesn't
<% fields_for "...", member do |member_form| %>
<p>
Name: <%= member_form.text_field :name %>
</p>
<% end %>
<% end %>
For some odd reason the information in the fields for tag won't even display once. Am I missing something?
If you find out what I am doing wrong, can you please explain it to me because I am new to rails.
Thanks in advance!
The block given to a fields_for call on a collection will be repeated for each instance in the collection, essentially creating its own loop, so you don't really need to write your own explicit loop "for member in #order.members". Further, you can leverage nested_attributes functionality to enable saving of associated members directly with #order.save:
class Order < ActiveRecord::Base
has_many :members
accepts_nested_attributes_for :members
end
class Member < ActiveRecord::Base
belongs_to :order
end
In the view:
<%= form_for #order do |order_form| %>
...
<%= order_form.fields_for :members do |member_form| %>
Name: <%= member_form.text_field :name %>
<% end %>
<% end %>
And I think your controller create method should work as you have it.
See the API docs for fields_for, especially the One-to-many subsection.
I think you just need to get rid of the "...", in your call to fields_for, as fields for is expecting an object.
Try:
<% fields_for member do |member_form| %>
The models project and category are in a has_and_belongs_to_many relationship. The partial seen below is used on different views to show a dropdown-menu with all the available categories. The projects in the list below the dropdown-menu are shown according to the choice the user made in the dropdown-menu.
Besides other categories, there is a category named "Everything" that every project is member of. It's also the first entry in the category-db-table, because it got inserted in while loading the migrations into the database.
Right now there is no error, but regardless of which category I choose it reloads the page showing the "Everything" category.
Any idea what I need to change in the code mentioned below to make it work the way I want to? Thanks for your help!
Partial with dropdown-menu and project-list
<!-- category dropdown -->
<% form_for category_url(:id), :html => {:method => :get} do |f| %>
<label>Categories</label>
<%= f.collection_select(:category_ids , Category.find(:all), :id , :name) %>
<%= f.submit "Show" %>
<% end %>
<!-- project list -->
<ul class="projectlist">
<% #projects.each do |_project| %>
<li>
<%= link_to(_project.name, _project) %>
</li>
<% end %>
</ul>
Logoutput after choosing category with id 2 on the dropdown-menu
Processing ProjectsController#index (for 127.0.0.1 at 2009-02-20 17:26:10) [GET]
Parameters: {"commit"=>"Show", "http://localhost:3000/categories/id"=>{"category_ids"=>"2"}}
Category Model
class Category < ActiveRecord::Base
has_and_belongs_to_many :projects, :join_table => "categories_projects"
end
Categories Controller
class CategoriesController < ApplicationController
def show
#projects = Category.find(params[:id]).projects.find(:all)
respond_to do |format|
format.html # show.html.erb
end
end
end
Project Model
class Project < ActiveRecord::Base
has_and_belongs_to_many :categories, :join_table => "categories_projects"
end
Projects Controller
class ProjectsController < ApplicationController
def show
#projects = Project.find(:all)
#project = Project.find(params[:id])
respond_to do |format|
format.html # show.html.erb
end
end
def index
#projects = Project.find(:all)
respond_to do |format|
format.html # index.html.erb
end
end
end
part of 'rake routes' output
category GET /categories/:id {:controller=>"categories", :action=>"show"}
You're passing a parameter called :category_ids, but you're not accessing that anywhere.
form_for category_url(:id)
This will submit your form to the path /categories/1 or whatever id you're currently viewing. You're then using that :id for finding your category projects:
#projects = Category.find(params[:id]).projects.find(:all)
So you're just showing the same ones over again. Because it's a form, you're submitting a query with the :category_ids parameter:
POST /categories/1?category_ids=2
You could just change your Category.find to use the other parameter instead. But, normally to view category 2 you would just use the url /categories/2, where 2 is your :id parameter. You have two ids in that path, and you should decide how you want to resolve that.
One option is to use the categories_path for the form action, and change the collection_select :category_ids parameter to just :id:
/categories?id=2 # from the form
/categories/2 # from a link
But if you're just listing projects, I would move this logic into the projects controller (index action), so your URLs would look like:
/projects?category_id=2` # from the form
/categories/2/projects # from a link
Thanks Andrew, but I solved it myself this way:
I got rid of collection_select, changed to select, added the filter-action (with the according route in config/routes.rb) and now everything works as I expected.
...I'm trying to get an observer on the select-menu, that submits it's value to the filter-action as soon as the user changes the selection in the select-menu, but that's another story. ;-)
New partial with dropdown-menu and project-list
<% form_tag(filter_category_path(:id), :method => :post, :class => 'categories') do %>
<label>Categories</label>
<%= select_tag(:category, options_for_select(Category.all.map {|category| [category.name, category.id]}, #category.id)) %>
<%= submit_tag "Go" %>
<% end %>
<ul class="projects">
<% #projects.each do |_project| %>
<li>
<%= link_to(_project.name, _project) %>
</li>
<% end %>
</ul>
New categories controller
class CategoriesController < ApplicationController
def show
#category = Category.find(params[:id])
#projects = #category.projects.find(:all)
respond_to do |format|
format.html
end
end
def filter
#category = Category.find(params[:category])
#projects = #category.projects.find(:all)
respond_to do |format|
format.html
end
end
end