I'm currently learning ruby, and i have an application where a user enters:
:name
:menu
:rsvp
They are all entered as a reply
I want to be able to get a count of how many people are currently added and display this on the index page. How would i go about getting a count to go over how many items are added to the database thus far?
Reply.rb
class Reply < ActiveRecord::Base
attr_accessible :menu, :name, :rsvp, :user_id
belongs_to :user
end
User.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me,
:first_name, :last_name, :profile_name
# attr_accessible :title, :body
has_many :replies
def full_name
first_name + " " + last_name
end
end
Replies Controller
class RepliesController < ApplicationController
# GET /replies
# GET /replies.json
def index
#replies = Reply.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #replies }
end
end
# GET /replies/1
# GET /replies/1.json
def show
#reply = Reply.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #reply }
end
end
# GET /replies/new
# GET /replies/new.json
def new
#reply = Reply.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #reply }
end
end
# GET /replies/1/edit
def edit
#reply = Reply.find(params[:id])
end
# POST /replies
# POST /replies.json
def create
#reply = Reply.new(params[:reply])
respond_to do |format|
if #reply.save
format.html { redirect_to #reply, notice: 'Reply was successfully created.' }
format.json { render json: #reply, status: :created, location: #reply }
else
format.html { render action: "new" }
format.json { render json: #reply.errors, status: :unprocessable_entity }
end
end
end
# PUT /replies/1
# PUT /replies/1.json
def update
#reply = Reply.find(params[:id])
respond_to do |format|
if #reply.update_attributes(params[:reply])
format.html { redirect_to #reply, notice: 'Reply was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #reply.errors, status: :unprocessable_entity }
end
end
end
# DELETE /replies/1
# DELETE /replies/1.json
def destroy
#reply = Reply.find(params[:id])
#reply.destroy
respond_to do |format|
format.html { redirect_to replies_url }
format.json { head :no_content }
end
end
end
I hope this information is helpful.
To get the User count:
User.count
In your controller, it's best to put this in an instance variable:
#user_count = User.count
To show it on a typical ERR view:
<%= #user_count %>
All the typical ActiveRecord models, controllers, and views work like this.
Related
How do I go about making this code block dry?
I understand that dry means dont repeat yourself but I don't see any obvious opportunity for refactoring.
Index, show, edit, and create seem like basic/necessary methods. They appear to be pretty dry to me.
The methods after I am not sure about.
I haven't tried anything other than googling so far.
class UsersController < ApplicationController
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
Slack.notify_channel
end
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
Slack.notify_channel
end
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
Slack.notify_channel
end
private
def user_params
params.require(:user).permit(:username, :email)
end
end
There is no rails backend attached to this code snippet. I am assuming it is just theoretical - wanting us to refactor the code to make it shorter.
IMHO you can do something like that.
class UsersController < ApplicationController
include ExceptionHandling
before_action :load_user, only: [:show, :edit, :update, :destroy]
after_action :slack_notify_channel, only: [:create, :update, :destroy]
def index
#users = User.all
end
def new
#user = User.new
end
def create
#user = User.create!(user_params)
respond_to do |format|
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
end
end
def update
#user.update!(user_params)
respond_to do |format|
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
end
end
def destroy
#user.destroy!
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def load_user
#user = User.find(params[:id])
end
def slack_notify_channel
Slack.notify_channel
end
def user_params
params.require(:user).permit(:username, :email)
end
end
I would recommend you to create a concern to manage exceptions and render each specific error by exception. Then you can avoid having two ways in each action to render a good and bad case.
I have to guess a bit about what's in your ApplicationController and User classes. But the obviously repeated code is #user = User.find(params[:id]). Your show and edit methods both just run this line. So, they do exactly the same thing, which they oughtn't to do. One method for one thing.
Also, once you resolve show and edit into a single method, your create, update and destroy methods should call it instead of repeating the line.
Next, I wouldn't use new as a method name, since it is already used by BasicObject::new. I tested a few things and it gets pretty unclear:
class Test
attr_reader :test
def initialize
#test = 'test'
end
end
class Test2
attr_reader :test2
def new
p 'test2new'
#test2 = Test.new
end
end
testx = Test2.new
p testx.new.test
p testx.test2.test
=> "test2new"
=> "test"
=> "test"
It takes extra effort to see when you're calling your own new method and when you're calling BasicObject::new. So, I'd change that to new_user or something, if you even need it at all — I don't see why you need both it and your create method. (If you don't need it, get rid of it.)
Finally, #user = User.find(params[:id]) doesn't imply either showing or editing, so understanding what you're trying to do and coming up with a name that reflects it (e.g. set_user_id) is something that ought to be done as well.
Im trying to create a new Category based on the title of the 'grow' that im creating (for a garden management tool'
But Im getting the following error:
'param is missing or the value is empty: category'
[edit] this is how the code is fixed. As per the suggestion in the comments:
remove the #grow = Grow.new(grow_params.merge(category: Category.create(cat_params)))
and replace with #grow = Grow.new(grow_params)
and in the Grow model add
after_create do
Category.create(name: self.title)
end
and its fixed.
class GrowsController < ApplicationController
before_action :set_grow, only: [:show, :edit, :update, :destroy]
def index
#grows = Grow.all
end
def show
end
def new
#grow = Grow.new
end
def edit
end
def create
#grow = Grow.new(grow_params.merge(category: Category.create(cat_params)))
respond_to do |format|
if #grow.save
format.html { redirect_to #grow, notice: 'Grow was successfully created.' }
format.json { render :show, status: :created, location: #grow }
else
format.html { render :new }
format.json { render json: #grow.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /grows/1
# PATCH/PUT /grows/1.json
def update
respond_to do |format|
if #grow.update(grow_params)
format.html { redirect_to #grow, notice: 'Grow was successfully updated.' }
format.json { render :show, status: :ok, location: #grow }
else
format.html { render :edit }
format.json { render json: #grow.errors, status: :unprocessable_entity }
end
end
end
# DELETE /grows/1
# DELETE /grows/1.json
def destroy
#grow.destroy
respond_to do |format|
format.html { redirect_to grows_url, notice: 'Grow was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_grow
#grow = Grow.find(params[:id])
end
def cat_params
params.require(:category).permit(:name)
end
def grow_params
params.require(:grow).permit(:title, :notes, :category_id)
end
end
I simply want to pass in the grow.title to new category name
However im not sure how to implement it.
In your create method leave the statement to be
#grow = Grow.new(grow_params)
and in your Grow model, write an after_create callback
within which you create your Category like Category.create(name: self.title)
Im building out an app in Rails 4 Ruby 2
Background:
I have a parent scaffold named "Calls" I then have a child scaffold named "Respondings". What I am attempting to achieve here is to have the ability to update items in the "Respondings" table from the "Calls" show.html.erb by way of a custom button click. (Shown below)
My routes look like so:
resources :calls do
resources :respondings, except: [:index], controller: 'calls/respondings' do
member do
patch :unit_responding_update
end
end
resources :pings, except: [:index], controller: 'calls/pings'
resources :agencies, except: [:index], controller: 'calls/agencies'
resources :incidents, except: [:index], controller: 'calls/incidents'
resources :complainants, except: [:index], controller: 'calls/complainants'
end
end
The patch: unit_respondings_update is what custom method that will update the table when pressed.
The Custom Def Rake output Here:
unit_responding_update_call_responding PATCH /calls/:call_id/respondings/:id/unit_responding_update(.:format) calls/respondings#unit_responding_update
My problem is that i have tried to place this in both the calls_controller.rb and the calls/respondings_controller.rb both to no avail. Listed below are the two controllers in their entirety. the other BIG Problem i am having is generating the path in the button to have this read and perform the function.
Parent Controller "Calls_controller"
class CallsController < ApplicationController
before_action :set_call, only: [:show, :edit, :update, :destroy]
# GET /calls
# GET /calls.json
def index
#calls = Call.all
#active_calls = #calls.select{ |x| x.status == 'ACTIVE' }
#pending_calls = #calls.select{ |x| x.status == 'PENDING'}
#clear_calls = #calls.select{ |x| x.status == 'CLEAR'}
end
# GET /calls/1
# GET /calls/1.json
def show
#call = Call.find(params[:id])
## Responding Nested
#respondings = #call.respondings
## Ping Nested
#pings = #call.pings
## Agency Nested
#agencies = #call.agencies
## Incidents Nested
#incidents = #call.incidents
## Complainants Nested
#complainants = #call.complainants
end
# GET /calls/new
def new
#call = Call.new
end
# GET /calls/1/edit
def edit
end
# POST /calls
# POST /calls.json
def create
#call = Call.new(call_params)
#call.status = "PENDING"
respond_to do |format|
if #call.save
format.html { redirect_to #call, notice: 'Call was successfully created.' }
format.json { render :show, status: :created, location: #call }
else
format.html { render :new }
format.json { render json: #call.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /calls/1
# PATCH/PUT /calls/1.json
def update
respond_to do |format|
if #call.update(call_params)
format.html { redirect_to #call, notice: 'Call was successfully updated.' }
format.json { render :show, status: :ok, location: #call }
else
format.html { render :edit }
format.json { render json: #call.errors, status: :unprocessable_entity }
end
end
end
# DELETE /calls/1
# DELETE /calls/1.json
def destroy
#call.destroy
respond_to do |format|
format.html { redirect_to calls_url, notice: 'Call was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_call
#call = Call.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def call_params
params.require(:call).permit(:site_id, :call_number, :call_type, :call_type_other, :call_details, :user_id, :status)
end
end
Child Controller "calls/respondings_controller": Currently Where the Custom Method is found:
class Calls::RespondingsController < ApplicationController
#before_action :set_responding, only: [:show, :edit, :update, :destroy]
# GET /respondings
# GET /respondings.json
def index
#respondings = Responding.all
end
# GET /respondings/1
# GET /respondings/1.json
def show
end
# GET /respondings/new
def new
#call = Call.find(params[:call_id])
#responding = Responding.new
end
# GET /respondings/1/edit
def edit
end
# POST /respondings
# POST /respondings.json
def create
#call = Call.find(params[:call_id])
#responding = Responding.new(responding_params)
#responding.call = #call
respond_to do |format|
if #responding.save
format.html { redirect_to #call, notice: 'Responding was successfully created.' }
format.json { render :show, status: :created, location: #call }
else
format.html { render :new }
format.json { render json: #call.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /respondings/1
# PATCH/PUT /respondings/1.json
def update
respond_to do |format|
if #responding.update(responding_params)
format.html { redirect_to #responding, notice: 'Responding was successfully updated.' }
format.json { render :show, status: :ok, location: #responding }
else
format.html { render :edit }
format.json { render json: #responding.errors, status: :unprocessable_entity }
end
end
end
# DELETE /respondings/1
# DELETE /respondings/1.json
def destroy
#call = Call.find(params[:call_id])
#responding = Responding.find(params[:id])
if #responding.destroy
flash[:notice] = "Successfully removed unit from call."
redirect_to #call
else
flash[:error] = "There was an error removing this responder from this call."
end
end
#Custom Controller Calls
def unit_responding_update
#call = Call.find(params[:call_id])
#responding = Responding.find(params[:id])
#responding.responding_tme = DateTime.now
#responding.responding = "true"
#responding.on_scene = "false"
#responding.clear = "false"
#responding.status = "RESPONDING"
#responding.save!
respond_to do |format|
if #responding.save
format.html { redirect_to #call, notice: "Responding time successfully updated. Your status - RESPONDING" }
else
format.html { render action: 'edit' }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_responding
#responding = Responding.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def responding_params
params.require(:responding).permit(:call_id, :user_id, :responding_tme, :on_scene_tme, :clear_tme, :responding, :on_scene, :clear, :status)
end
end
If you need more information please don't hesitate to ask! i am at a standstill until this is resolved! ( or for access to my Git where this is stored for full context)
Thanks in advance to everyone!
EDIT # 1: -- Adds Calls / Respondings Model Relations
Model Relations For Call
class Call < ActiveRecord::Base
has_many :respondings, dependent: :destroy
end
Model Relations for Responding
class Responding < ActiveRecord::Base
has_many :incidents
belongs_to :call
end
So the Fix to this problem was soley in the routes file.. it turns out I was missing and end.. After changing my routes file to the following, it solved the initial problem altogether.
resources :calls do
resources :respondings, except: [:index], controller: 'calls/respondings' do
member do
patch :unit_responding_update
end
end
resources :pings, except: [:index], controller: 'calls/pings'
resources :agencies, except: [:index], controller: 'calls/agencies'
resources :incidents, except: [:index], controller: 'calls/incidents'
resources :complainants, except: [:index], controller: 'calls/complainants'
end
end
Once the routes were fixed I used the following link:
<%= link_to "Responding", unit_responding_update_call_responding_path(call_id: #call.id, id: #respondings.first.id), method: :patch %>
I am working on a Rails 4 App, one of my modules is a general patrol report in which a user creates a report based on his / her shift shift start / stop. after the report is created they have the option to go back into the report view and add a patrol report.
Every thing is working up to the gen_rep_ent form submission.
The specific error I get is:
undefined method `general_report=' for #<GenRepEnt:0x007f871d9ea150>
followed by:
def create
#general_report = GeneralReport.find(params[:general_report_id])
#gen_rep_ent = GenRepEnt.new(gen_rep_ent_params)
#gen_rep_ent.general_report = #gen_rep_ent <-- Problem Line
respond_to do |format|
if #gen_rep_ent.save
format.html { redirect_to #general_report, notice: 'General Report Entry was successfully created.' }
format.json { render :show, status: :created, location: #general_report}
else
format.html { render :new }
format.json { render json: #general_report.errors, status: :unprocessable_entity }
end
end
end
It is the 3rd line that is causing the issue here.
My general_report model has the following relationship:
has_many :gen_rep_ents, dependent: :destroy
My Routes File looks Like:
Rails.application.routes.draw do
resources :mobile_alarm_reports
resources :mobile_incident_reports
resources :static_incident_reports
resources :general_reports do
resources :gen_rep_ents, except: [:index], controller: 'general_reports/gen_rep_ents'
end
resources :visitor_parkings
resources :residents
resources :sites
devise_for :users, controllers: { registrations: "registrations" }
# Adds Static Pages
root 'home#index'
get 'home/about'
get 'home/contact'
get 'home/pricing'
My show file looks like:
<% #gen_rep_ents.each do |gen_rep_ent| %>
<table>
<thead>
<tr>
<th>Time</th>
<th>Report</th>
</tr>
</thead>
<tbody>
<tr>
<td><%= gen_rep_ent.time %></td>
<td><%= gen_rep_ent.report %></td>
</tr>
</tbody>
<% end %>
</table>
gen_rep_ents_controller.rb: <-- The nested Item
class GeneralReports::GenRepEntsController < ApplicationController
before_action :set_gen_rep_ent, only: [:show, :edit, :update, :destroy]
# GET /gen_rep_ents
# GET /gen_rep_ents.json
def index
#gen_rep_ents = GenRepEnt.all
end
# GET /gen_rep_ents/1
# GET /gen_rep_ents/1.json
def show
end
# GET /gen_rep_ents/new
def new
#general_report = GeneralReport.find(params[:general_report_id])
#gen_rep_ent = GenRepEnt.new
end
# GET /gen_rep_ents/1/edit
def edit
end
# POST /gen_rep_ents
# POST /gen_rep_ents.json
def create
#general_report = GeneralReport.find(params[:general_report_id])
#gen_rep_ent = GenRepEnt.new(gen_rep_ent_params)
#gen_rep_ent.general_report = #gen_rep_ent
respond_to do |format|
if #gen_rep_ent.save
format.html { redirect_to #general_report, notice: 'General Report Entry was successfully created.' }
format.json { render :show, status: :created, location: #general_report}
else
format.html { render :new }
format.json { render json: #general_report.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /gen_rep_ents/1
# PATCH/PUT /gen_rep_ents/1.json
def update
respond_to do |format|
if #gen_rep_ent.update(gen_rep_ent_params)
format.html { redirect_to #gen_rep_ent, notice: 'General Report Entry was successfully updated.' }
format.json { render :show, status: :ok, location: #gen_rep_ent }
else
format.html { render :edit }
format.json { render json: #gen_rep_ent.errors, status: :unprocessable_entity }
end
end
end
# DELETE /gen_rep_ents/1
# DELETE /gen_rep_ents/1.json
def destroy
#gen_rep_ent.destroy
respond_to do |format|
format.html { redirect_to gen_rep_ents_url, notice: 'General Report Entry was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_gen_rep_ent
#gen_rep_ent = GenRepEnt.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def gen_rep_ent_params
params.require(:gen_rep_ent).permit(:time, :report, :general_report)
end
end
The general_reports_controller: <-- Parent Item
class GeneralReportsController < ApplicationController
before_action :set_general_report, only: [:show, :edit, :update, :destroy]
# GET /general_reports
# GET /general_reports.json
def index
#general_reports = GeneralReport.all
end
# GET /general_reports/1
# GET /general_reports/1.json
def show
#general_report = GeneralReport.find(params[:id])
#gen_rep_ents = #general_report.gen_rep_ents
end
# GET /general_reports/new
def new
#general_report = GeneralReport.new
end
# GET /general_reports/1/edit
def edit
end
# POST /general_reports
# POST /general_reports.json
def create
#general_report = GeneralReport.new(general_report_params)
respond_to do |format|
if #general_report.save
format.html { redirect_to #general_report, notice: 'General report was successfully created.' }
format.json { render :show, status: :created, location: #general_report }
else
format.html { render :new }
format.json { render json: #general_report.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /general_reports/1
# PATCH/PUT /general_reports/1.json
def update
respond_to do |format|
if #general_report.update(general_report_params)
format.html { redirect_to #general_report, notice: 'General report was successfully updated.' }
format.json { render :show, status: :ok, location: #general_report }
else
format.html { render :edit }
format.json { render json: #general_report.errors, status: :unprocessable_entity }
end
end
end
# DELETE /general_reports/1
# DELETE /general_reports/1.json
def destroy
#general_report.destroy
respond_to do |format|
format.html { redirect_to general_reports_url, notice: 'General report was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_general_report
#general_report = GeneralReport.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def general_report_params
params.require(:general_report).permit(:user_id, :site_id, :date, :shift_start, :shift_end, :gp_number)
end
end
I am not too sure where I'm going wrong with this as I have reviewed the tutorial over and over, and it all matches from what I can see.
EDIT # 1
my GenRepEnt model looks like:
class GenRepEnt < ActiveRecord::Base
belongs_to :general_report
end
EDIT # 2
After performing the migration and adding belongs_to :general_report to the model I get the following error:
ActiveRecord::AssociationTypeMismatch in
GeneralReports::GenRepEntsController#create
Looks like you are trying to set general_report on an instance of a GenRepEnt class but that method doesn't exist. This is likely because the association was not set up in the GenRepEnt model.
In the model gen_rep_ent.rb add the following association:
belongs_to :general_report
After you declare this association Rails will define a few methods on each instance of GenRepEnt including:
general_report
general_report=
You will also need to generate a migration that will add a new column, general_report_id, to the gen_rep_ents table.
In your terminal run rails g migration AddGeneralReportRefToGenRepEnts general_report:references
This should generate a migration that looks something like this:
class AddGeneralReportRefToGenRepEnts < ActiveRecord::Migration
def change
add_reference :gen_rep_ents, :general_report, index: true, foreign_key: true
end
end
Next, run the migration using rake db:migrate and restart your app.
Read more about the belongs_to association here.
I've just generated my User scaffold and I'm now getting an error with 'Password can't be blank' even though I've filled out all the fields. I'm confused because my rake tests are passing, so not sure where the error is?
User Model:
class User < ActiveRecord::Base
validates :name, presence: true, uniqueness: true
has_secure_password
end
And my user controller:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
#users = User.order(:name)
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to users_url, notice: "User #{#user.name} was successfully created." }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to users_url, notice: "User #{#user.name} was successfully updated." }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :password_digest)
end
end
If you need more code submitted, just let me know. I'm working with Rails 4.
Would be nice to see the server logs when you submit the form, something tells me you don't require the right parameters, from your form there should be: password and password_confirmation but in controller you require password_digest for some reason:
def user_params
params.require(:user).permit(:name, :password_digest)
end
it should be:
def user_params
params.require(:user).permit(:name, :password, :password_confirmation)
end
and password_digest should be updated not via params.