Fetch id of selected option in dropdown in controller - ruby-on-rails

I have a model named 'Assessment':
class Assessment < ApplicationRecord
has_many :assessment_students
has_many :students, through: :assessment_students
end
Join table is:
class AssessmentStudent < ApplicationRecord
belongs_to :student
belongs_to :assessment
end
There is another model:
class Classroom < ApplicationRecord
has_many :classroom_students
has_many :students, through: :classroom_students
has_many :assessments
end
In show,html.erb of classrooms, I have a dropdown which shows all assessments (generated from assessment table).
Code is:
<%= collection_select(:assessment :assessment_id, Assessment.all, :id, :assessment_name , :prompt => true) %>
Requirement of the project is: Based on the assessment chosen by the user in the show.html.erb page, we have to show all students details like name etc assigned to that particular assessment. I have stored this data in join table 'AssessmentStudent '. However, I am not sure how to pass id from the above collection_select to classroom controller. I have below code:
show.html.erb:
<%= collection_select(:assessment :assessment_id, Assessment.all, :id, :assessment_name , :prompt => true) %>
<div id="divResult">
<% #assessmentstudents1.each do |t| %>
<% t.assessment_students.each do |record| %>
<%= record.student_id %>
<% end %>
<% end %>
</div>
classroom controller:
def show
#assessmentstudents1 = Assessment.find(params[:assessment][:assessment_id]).preload(:assessment_students)
end
def classroom_params
params.require(:classroom).permit(:classroom_name, :classroom_year, :customer_id, :classroom_student, :student_ids => [])
params.require(:assessment).permit(:assessment_id)
end

I would first recommend to make a change to the controller structure of your application. Because the responsibility of the show action of your ClassroomsController should be to display the details of the classroom. When you want to show the details of an Assessment, that should be handled by an AssessmentsController.
First of all, I'm gonna assume that your Assessment model has a belongs_to :classroom association. Then I would suggest creating the following structure.
config/routes.rb
resources :classrooms
resources :assessments
app/views/classrooms/show.html.erb
<% #classroom.assessments.each do |assessment| %>
<%= link_to assessment_name, assessment_path(assessment) %>
<% end %>
app/controllers/assessments_controller.rb
class AssessmentsController < ApplicationController
def show
#assessment = Assessment.find(:id)
end
end
app/views/assessments/show.html.erb
<h1>Students for <%= #assessment.assessment_name %></h1>
<% #assessment.students.each do |student| %>
<p><%= student.student_name %></p>
<% end %>
<h2>In classroom:</h2>
<p><%= #assessment.classroom.classroom_name %></p>
So to explain what is happening here, we have configured the routes to allow the server to respond to the url /assessments/:id which will lead to the AssessmentsController#show action being called.
That action is being called when the user clicks on any of the links that we have setup in the classrooms/show template. Note that I used individual links for now instead of a select dropdown, because it is easier to setup and understand how it works. And like the previous answer suggested, using a select tag requires a little bit of JavaScript to get working.
And lastly, when the assessments/show template is being rendered, it will list out all of the students related to that particular assignment. And I also included which classroom it is assigned to (if my assumption of belongs_to was correct).
On a side note, if your question tag of ruby-on-rails-3 is correct, then the usage of params.permit and params.require is invalid, because that is something that was introduced in Rails 4 (unless I'm mistaken). And in any case, you only have to use permit when database updates take place, which means the create and update actions, not index, show, etc, because it is a way of restricting which changes are allowed.

Tag select does nothing by itself. So there are two possible options.
The first is wrapping select in form tag then submitting the form will lead to request. The second is writing a handler using JavaScript which will listen to select changes.

Related

How to dispaly a login student written message in ruby on rails

I want to display login student name and message.
after login student can write messages and send related to courses.the messages he send is displayed above in same page with his/her name and message
I got name, but message field fetches all messages that are in database. How to display a particular student name and message?
Here is my code
controller.erb
class CourseQueriesController <ApplicationController
def index
#course_queries = CourseQuery.all
#course_query = CourseQuery.new
end
def create
#course_query = CourseQuery.new(student_id: current_student.id, coach_id: "2", message: params[:course_query][:message])
if #course_query.save
redirect_to course_queries_path, notice: 'Query was successfully send.'
else
render :new
end
end
end
course_queries/index.html.erb
<% #course_queries.each do |queries| %>
<p><b><%= current_student.name %></b></p>
<%= queries.message %>
<% end %>
<%= simple_form_for (#course_query) do |f| %>
<%= f.input :message %>
<%= f.button :submit , "Send or press enter"%>
<% end %>
how to display a particular student name and message
You need to have the relevant associations established in your models, like what Pavan wrote.
I'll give you some more information on why this is important...
ActiveRecord
One of the main reasons Rails works so well is the way it helps you create & manage objects. In OOP, objects form everything from your init commands to your user input responses, Ruby being a prime exponent of this structure.
Rails is built on Ruby, and therefore is object orientated too. It uses ActiveRecord, the MVC structure & classes to give you a platform from which you can populate and manipulate objects:
Thus, you shouldn't be treating your application's interactions as a way to edit a database, or "display a login message" - it should be a way to invoke & manipulate objects.
Objects - in the case of Rails - are built in the models. The model data can then be used in the controllers and views.
This seems to be lacking in your code. If you can remedy it, your code will become a lot simpler and more powerful...
Associations
I'd do something like this:
#app/models/student.rb
class Student < ActiveRecord::Base
has_many :queries
has_many :coarse_queries, through: :queries
end
#app/models/course.rb
class Course < ActiveRecord::Base
has_and_belongs_to_many :coaches
has_many :queries
has_many :student_queries, through: :queries
end
#app/models/coach.rb
class Coach < ActiveRecord::Base
has_and_belongs_to_many :courses
has_many :queries
end
#app/models/query.rb
class Message < ActiveRecord::Base
belongs_to :course
belongs_to :student
belongs_to :coach (maybe)
end
This structure will allow a student to send queries to specific courses, selecting the coach as necessary. Importantly, this sets up your associations so that you don't have to invoke multiple classes each time you want to populate the various objects.
#app/controllers/course_queries_controller.rb
class CourseQueriesController <ApplicationController
def index
#queries = Query.all
#query = current_student.queries.new
end
def create
#query = current_student.queries.new query_params
if #query.save
redirect_to course_queries_path, notice: 'Query was successfully send.'
else
render :new
end
end
private
def query_params
params.require(:query).permit(:message).merge(coach_id: "2")
end
end
#app/views/queries/index.html.erb
<% #queries.each do |query| %>
<p><b><%= query.student.name %></b></p>
<%= query.message %>
<% end %>
<%= simple_form_for #query do |f| %>
<%= f.input :message %>
<%= f.button :submit , "Send or press enter"%>
<% end %>
You should add has_many :course_queries to the Student model
#student.rb
class Student < ActiveRecord::Base
has_many :course_queries
...
end
And in the controller in index method change #course_queries = CourseQuery.all to #course_queries = current_student.course_queries
Now <%= queries.message %> will only display the course_query's message of the current_student

Build form inside show action for outside model

I am trying to build a form inside the show action of a controller. Here is my setup.
Category Model
class Category < ActiveRecord::Base
# Associations
has_many :feeds
has_many :subscriptions
# Nested attributes
accepts_nested_attributes_for :subscriptions
end
Subscription Model
class Subscription < ActiveRecord::Base
# Associations
belongs_to :profile
belongs_to :category
belongs_to :feed
end
Using a Subscription namespace:
# Subscriptions
namespace :subscriptions do
resources :categories
end
Inside the show action for a category (http://URL.com/subscriptions/categories/1), I want to build the subscriptions model form and list the available feeds for that category. I want the form to submit the checked off feeds to the Subscription model.
CategoriesController
def show
#feeds = Feed.where("category_id = ?", #category)
end
Trying to build the form in the Show action of the Categories view:
<%= simple_form_for [:subscriptions, #category] do |f| %>
<%= f.association :feeds, collection: #feeds, value_method: :id, as: :check_boxes %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Right now it is rendering the appropriate information, but it is rendering as an edit form, not a create form. How do I fix this?
What else do I need to add to my routes / controller to actually get the information to save to the Subscription model?
Thanks.
first thing i am not sure where you initialize the #category object in show action and in view. if you want to render a new page than it should be map to new action of the controller and you path with will be
http://URL.com/subscriptions/categories/new
the path you are using
http://URL.com/subscriptions/categories/1
will always map to the show action according to rails convention though you can override that for you accordingly but that is not a good practice. also in new action initialize the instance by
#category = Category.new
now on submit it will automatically goes to the create action. if your #category is already persisted in the database for example
#category = Category.find(1)
now if this object goes to the simple_form_for it will send the data to update action .

Nested_form has_one association

I have 2 models dog and litter_field:
class Dog < ActiveRecord::Base
belongs_to :user
has_one :litter_field
accepts_nested_attributes_for :litter_field
attr_accessible :litter_field_attributes
end
class LitterField < ActiveRecord::Base
belongs_to :dog
attr_accessible :breed_type
end
In my controller I have:
class DogsController < ApplicationController
def edit
#dog = Dog.find(params[:id])
#dog.build_litter_field
end
And in my view I have:
<%= simple_form_for #dog do |f| %>
<%= f.fields_for :litter_field do |l| %>
<div>
<%= l.label :breed_type %>
<%= l.input_field :breed_type %>
</div>
<%= f.button :submit, "Save" %>
<% end %>
I've looked at the documentation and from what I can tell this should work, however this page is not on the main edit page which I'm assuming is where the problem lies. Should I be adding what's in the edit action to a new action which displays the litter_field edit form?
EDIT:
What I am trying to do is split the edit form into separate pages, I've done this by adding additional actions that render extra pages so a user would go to dogs/settings/litter for example to see the litter_field nested form. I've tried adding #dog.build_litter_field to the litter action which displays the fields but when I try and save the form I am getting the error:
Failed to remove the existing associated litter_field. The record failed to save when after its foreign key was set to nil.
EDIT 2:
Fixed the above with adding:
has_one :litter_field, :dependent => :destroy
accepts_nested_attributes_for :litter_field, update_only: true
To dog.rb, the only problem I have now is it won't display the saved value on edit.
If you call #dog.build_litter_field in the edit action, it will build a new LitterField overtop of whatever had been saved previously. I would suggest trying something like this to see if it solves the problem you are currently seeing:
def edit
#dog = Dog.find(params[:id])
#dog.build_litter_field if #dog.litter_field.nil?
end
It can also help to checkout the debugger gem. You can use that to step through controller actions and see what the objects look like after each statement.

adding hobby to a user

I'm trying to write a rails application. I'm a ruby-on-rails newbie.
I have a User model and a Hobby model.
class User < ActiveRecord::Base
has_many :hobbies
end
class Hobby < ActiveRecord::Base
belongs_to :user
end
During the new user registration, I have used a text box where I enter a value for hobby. Then, when I press a button 'Add hobby', a method in UsersController add_hobby is to be called where I intend to append the value entered for hobby by user to the user i.e
#user.hobbies << hobby
However, my problem is that the user object has not been saved yet, so there is no way to access a particular user object. How do I get around this problem ?
You can build nested form as such in your templates:
<%= form_for #user do |user_form| %>
<%= user_form.text_field :name %>
<% for hobby in #user.hobbies %>
<%= user_form.fields_for hobby, :index => hobby do |hobby_form|%>
<%= hobby_form.text_field :name %>
<% end %>
<% end %>
<% end %>
Then add accepts_nested_attributes_for in your User model
class User < ActiveRecord::Base
has_many :hobbies
accepts_nested_attributes_for :hobbies, :allow_destroy => true
end
As per my understanding, Its better to save the hobbies after user has been created. Afterall its not logical to save user's hobbies even without having a user created.
If you are allowing multiple hobbies for a user, have a javascript array in client side. when user added a hobby add it to the javascript array and update the page. (You can do it with some DHTML / Javascript). When you are saving the user pass the hobby array and in the controller you can split and save the hobbies.
cheers
sameera

Rails link from one model to another based on db field?

I have a company model and a person model with the following relationships:
class Company < ActiveRecord::Base
has_many :kases
has_many :people
def to_s; companyname; end
end
class Person < ActiveRecord::Base
has_many :kases # foreign key in join table
belongs_to :company
end
In the create action for the person, I have a select box with a list of the companies, which assigns a company_id to that person's record:
<%= f.select :company_id, Company.all.collect {|m| [m.companyname, m.id]} %>
In the show view for the person I can list the company name as follows:
<%=h #person.company.companyname %>
What I am trying to work out, is how do I make that a link to the company record?
I have tried:
<%= link_to #person.company.companyname %>
but that just outputs the company name inside a href tag but links to the current page.
Thanks,
Danny
You need pass in second argument the path where you want go
<%= link_to #person.company.companyname, #person.company %>
or with the full version :
<%= link_to #person.company.companyname, company_url(#person.company) %>
The thing is, link_to cannot guess where you want it to lead to, if you give it only the text of the link :)
In order to have the link lead to the company page, you need to add a path:
<%= link_to #person.company.companyname, company_path(#person.company) %>
This assumes you have proper restful routes for your company
map.resources :companies
and the page you're heading to is companies/show.html.erb.

Resources