Add styling to format.html outputted from Rails controller - ruby-on-rails

reports.rb
def method
if self.name == "Maintenance History"
'maintenance_history'
elsif self.name == "Outstanding Maintenance"
'outstanding_maintenance'
elsif self.name == "Idle Time Report"
'idle_time_report'
end
end
def maintenance_history
maintenance_history.where(....)
end
def outstanding_maintenance
outstanding_maintenance.where(....)
end
def idle_time_report
idle_time_report.where(....)
end
reports_controller
def show
#report = Report.find(params[:id])
respond_to do |format|
format.html # show.html.erb
show.html.haml
= render #report.method, :report => #report
I would like to format the html table in my view with the following tag %table.table.datatable#datatable
This:
%table.table.datatable#datatable
= render #report.method, :report => #report
does not work...

If I understand your issue correctly, it's that the different tables require different styles depending on the report. Just as you're using the name of the report in the controller to determine the scope, you could use some attribute of the report in the view to add a class or other identifying attribute to the HTML.
As a simple example, you could create a helper for your view exactly like your method controller method, like:
# some helper for the reports
module ReportsHelper
# the `method` method from your controller, migrated to a helper
def report_table_class(report)
if report.name == "Maintenance History"
'maintenance_history'
elsif report.name == "Outstanding Maintenance"
'outstanding_maintenance'
elsif report.name == "Idle Time Report"
'idle_time_report'
end
end
end
Then in your view, you could use that to demarcate the table or a parent element, which you could use as a target for your style selector:
%table#datatable{:class => ['table', 'datatable', report_table_class(#report)]}
And finally in your CSS:
table.maintenance_history {
// style accordingly
}
table.idle_time_report {
// style accordingly
}

Related

Update value with first_or_create in rails

I have a table 'Likes' with columns business_id, user_id and liked(0,1) and a function 'change_like_status'.
Now on every function call, If the value is 1 then set it to 0 (or vice versa) and if record doesn't exists then create one with value 1.
The first_or_create method is working just fine but how can i toggle value of column 'liked' while using this method?
Here is my function:
def change_like_status
if current_user.present?
status = Like.where("business_id = ? AND user_id = ?",params['id'],current_user.id).first_or_create(:business_id => params['id'],:user_id => current_user.id,:liked => '1')
abort status.inspect
else
return render :json => {:status => false,:msg=>"You need to sign in before performing this action."}
end
end
In you controller, make the changes
def change_like_status
if current_user
status = Like.create_or_change_status(params[:id], current_user.id)
else
return render json: { status: false, msg: "You need to sign in before performing this action." }
end
end
In your model like.rb file, add a method
def self.create_or_change_status(business_id, user_id)
status = where(business_id: business_id, user_id: user_id).first
if status.nil?
status = create({business_id: business_id, user_id: user_id, liked: 1})
else
status.update_attributes(liked: !status.liked)
end
status
end
def change_like_status
if current_user
current_user.likes.find_by(business_id: params[:id]).switch_status!
else
return render json: { status: false, msg: "You need to sign in before performing this action." }
end
end
class Like
def switch_status!
self.update_column :liked, !liked
end
end
other approach should be something like that
class Like
def switch_status!
self.update_column :liked, !liked
end
end
class User
def likes id
likes_for_business id
end
def likes_for_business(id)
likes.find_by(business_id: id) || likes.create(:business_id: id, liked: true)
end
end
# controller
current_user.likes(params[:id]).switch_status!

How can I redirect after an action is performed in my controller?

I have a form set up to take in date time value. This value will then be sent as a parameter into my controller method "bookingdate" where it will be compared with other dates in the bookings to ensure there is no double booking, using a do loop.
However when I submit the date form, rather than redirect to the next form where a user selects other details it throws me an error or redirects incorrectly.
Here is my controller
def bookingdate
#bookings = Booking.all
#bookings.each do |b|
if b.startdatetime == params[:startdatetime]
#musicians = Musician.where (["id != ?", b.musician_id])
end
end
render :action => 'new'
end
Here is my routes
match '/bookdate', :to => 'bookings#bookingdate'
Add redirect_to helper and pass route to where progress
def bookingdate
#bookings = Booking.all
#bookings.each do |b|
if b.startdatetime == params[:startdatetime]
#musicians = Musician.where (["id != ?", b.musician_id])
end
end
redirect_to path_where_you_want_to_redirect
end
I guess you want to perform some checks, if user has correct filled form
def bookingdate
#bookings = Booking.all
#bookings.each do |b|
if b.startdatetime == params[:startdatetime]
#musicians = Musician.where (["id != ?", b.musician_id])
end
end
if condition_successful
redirect_to path_where_you_want_to_redirect
else
render :bookingdate
end
end

Ruby on Rails filter array using three fields

I am trying to search through my model using 3 columns. Also if the column is empty, it is valid. This is how I am doing it
def getactivityfortoday
#temp = params[:temp]
logger.debug "params temp:#{#temp.inspect}"
#sky = params[:sky]
#day = params[:day]
#todaysactivities = []
#activities=[]
#finaldata = []
#activities = Weatherclockactivity.all
#attemptactivities = []
#attemptactivities = #user.attempts
for activity in #activities do
logger.debug "activity: #{activity.attributes.inspect}"
if #temp.to_i < activity.temperatureMax.to_i && #temp.to_i > activity.temperatuureMin.to_i
if #sky == activity.sky || activity.sky == ""
if #day == activity.day
#todaysactivities << activity
end
end
end
end
for activity in #todaysactivities
for attempt in #attemptactivities
if attempt == activity
finaldata << {activity: activity, attempt: "yes"}
else
finaldata << {activity: activity, attempt: "no"}
end
end
end
respond_to do |format|
format.html { render action: "new" }
format.json { render json: #finaldata }
end
The response I get is an empty array but I should be getting 3 rows as a response.
spelling mistake here
activity.temperatuureMin.to_i
And
finaldata << {activity: activity, attempt: "yes"}
should be
#finaldata << {activity: activity, attempt: "yes"}
Also you could be more concise
def getactivityfortoday
#temp = params[:temp]
logger.debug "params temp:#{#temp.inspect}"
#sky = params[:sky]
#day = params[:day]
#activities = Weatherclockactivity.all
#attemptactivities = #user.attempts
#finaldata = #activities.map do |activity|
if (activity.temperatureMin.to_i + 1...activity.temperatureMax.to_i).include?(#temp.to_i) && ( #sky == activity.sky || activity.sky == "") && #day
#attemptactivities.include?(activity) ? {activity: activity, attempt: "yes"} : {activity: activity, attempt: "no"}
end
end.compact
respond_to do |format|
format.html { render action: "new" }
format.json { render json: #finaldata }
end
end
How about something like this?
I tried to make it a balance of readability and conciseness. First we filter for the desired activities. Then we structure the output. This should be easier to debug.
def getactivityfortoday
#temp = params[:temp].to_i
#sky = params[:sky]
#day = params[:day]
#activities = Weatherclockactivity.all
#attemptactivities = #user.attempts
selected_activities = #activities.select do |activity|
# Make sure it's the right temperaure
return false unless (activity.temperatureMin.to_i + 1 ... activity.temperatureMax.to_i).include? #temp
# Make sure the sky matches, or the sky is blank
return false unless (#sky.blank? || #sky.activity == activity.sky)
# Make sure the day matches
return false unless #day == activity.day
# Otherwise, it's good!
return true
end
selected_attempted_activities = selected_activities.map do|activity|
ret = {activity: activity}
ret[:attempt] = #attemptactivities.include?(activity) ? "yes" : "no"
ret
end
respond_to do |format|
format.html { render action: "new" }
format.json { render json: selected_attempted_activities }
end
end
There are a few typos in your original (for instance, #finaldata not finaldata). Make sure that you spell instance variables (things starting with #, like #sky) correctly, since if you try to access an undefined instance variable, it'll silently default to nil.
The best and flexible way is to use ActiveModel::Model
It allows you to use many more useful methods.
it will seems like:
app/models/activity_report.rb
Class ActivityReport
include ActiveModel::Model
attr_accessor :day, :activity # and etc.
validates :day, presence: true
def day
#day.to_s # for example
end
def day=(value)
#day = value - 1.month # for example every date which user set will set on one month ago
end
# and etc
end
app/controllers/posts_controller.rb
...
def index
#activity = ActivityReport.new(params[:activity])
end
def create
#activity.create!
end
...
app/views/posts/index.html.haml
= form_for #activity do |f|
= f.day
For more information you could take a look at:
http://edgeapi.rubyonrails.org/classes/ActiveModel/Model.html
http://railscasts.com/episodes/219-active-model (old)
http://railscasts.com/episodes/416-form-objects (newer, but a little complex)

rails update method not calling class methods

I have a class method that I need to call on a controller update method called auto_assign!
It essentially finds the artist with the lowest amount of requests and assigns that artist id to the object.
It works perfectly on the create method, but it does not get called on the update method, and I am not sure why.
Controller
def update
#virtual_request = VirtualRequest.find(params[:id])
#virtual_request.auto_assign! # this never gets called
if #virtual_request.update_attributes(virtual_params)
flash[:success] = "Virtual request updated"
redirect_to virtual_request_path(#virtual_request)
else
render 'edit'
end
end
def create
#virtual_request = VirtualRequest.new(virtual_params)
#virtual_request.auto_assign! # works fine here!
if #virtual_request.save
flash[:success] = "Virtual has been created and assigned to # {#virtual_request.artist.name}"
redirect_to virtual_requests_path
else
render 'new'
end
end
Class VirtualRequest
def auto_assign!
if self.artist_id == 0
artists = Artist.in_queue?.collect {|p| [ p.id, p.virtual_requests.count ] }
self.artist_id = artists.sort { |a,b| a[1] <=> b[1] }.first[0]
end
end
HTML sending parameters
<select id="virtual_request_artist_id" name="virtual_request[artist_id]">
<option selected="selected" value="0">auto-assign</option>
<option value="2">Artist 1</option>
<option value="5">Artist 2</option>
</select>
it is supposed to auto-assign when the value in the params is 0
UPDATE: solved
Controller
def update
#virtual_request = VirtualRequest.find(params[:id])
if #virtual_request.update_attributes(virtual_params)
#virtual_request.auto_assign!
flash[:success] = "Virtual request updated"
redirect_to virtual_request_path(#virtual_request)
else
render 'edit'
end
end
Class
def auto_assign!
if self.artist_id == 0
artists = Artist.in_queue?.collect {|p| [ p.id, p.virtual_requests.count ] }
self.artist_id = artists.sort { |a,b| a[1] <=> b[1] }.first[0]
self.save
end
end
A couple of things are wrong:
First you need to call the #virtual_request.auto_assign! within the conditional because artist_id would not have been set otherwise.
Secondly don't forget to save the updated instance when you make the changes in the auto_assign method so:
def update
#virtual_request = VirtualRequest.find(params[:id])
if #virtual_request.update(virtual_params)
#virtual_request.auto_assign!
#virtual_request.save
flash[:success] = "Virtual request updated"
redirect_to virtual_request_path(#virtual_request)
else
render 'edit'
end
end
something on these lines but I'm sure others will suggest a more efficient solution
alternatively for your method (you won't need the save in your Controller with this approach).
def auto_assign!
if self.artist_id == 0
artists = Artist.in_queue?.collect {|p| [ p.id, p.virtual_requests.count ] }
artist_id = artists.sort { |a,b| a[1] <=> b[1] }.first[0]
self.update_attribute(:artist_id,artist_id)
end
end
a few things to play with anyway!

Url helper is not available when rendering a partial from a class

I have a helper class that renders a partial to store the content in the database.
It works fine but when the view contains a url provided by the url helper
<%= link_to "Show project", projects_url, class: "button" %>
it throws the following exception
undefined local variable or method projects_url for #
The code to render in my helper named NotificationRender is
def render(options)
viewer = ActionView::Base.new()
viewer.view_paths = ActionController::Base.view_paths
viewer.extend ApplicationHelper
viewer.render options
end
I include this helper in a class Notification
class Notification < ActiveRecord::Base
include NotificationRender
.....
def self.create_for(user, event, params)
template = "notifications/_email_project"
list_params = {:template => template,:locals => params}
notification = Notification.new
notification.message = notification.render(list_params) #here I render the partial
notification.subject = I18n.t "subject.#{event}"
notification.to = user.email
notification.save
end
end

Resources