Activity
I'm working on a simple CRUD Asset Management app and I want to use Ransack. I think I have this setup properly in my view and controller but each time the index view is hit I get the exception:
undefined methodassets_path' for #<#:0x007fa5f353e9e0>
`
Here is my view:
index.html.erb
<div class="pull-right">
<%= search_form_for @q do |f| %>
<%= f.search_field :asset_name_cont, placeholder: 'Search...' %>
<% end %>
<table class="table table-striped">
<thead>
<tr>
<th>Asset Number</th>
<th>Asset Name</th>
<th>Serial Number</th>
<th>Model</th>
<th>Manufacturer</th>
<th>Asset Type</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% @assets.each do |a| %>
<tr>
<td><%= a.asset_number %></td>
<td><%= a.asset_name %></td>
<td><%= a.asset_serial %></td>
<td><%= a.asset_model %></td>
<td><%= a.asset_manuf %></td>
<td><%= a.asset_type.try(:name) %></td>
<td><%= link_to 'View', inventory_path(a), :class => 'btn btn-mini btn-info' %> <%= link_to 'Edit', edit_inventory_path(a), :class => 'btn btn-mini btn-warning' %></td>
</tr>
</tbody>
<% end %>
<%= will_paginate @assets %>
Here is my controller excerpt: inventory_controller.rb
def index
@q = Asset.ransack(params[:q])
@assets = @q.result.order("asset_number ASC").paginate(:page => params[:page], :per_page => 10)
end
And here is my model (with annotation of the fields)
asset.rb
id :integer not null, primary key
asset_number :string
asset_shortname :string
asset_name :string
asset_desc :text
asset_serial :string
asset_model :string
asset_manuf :string
asset_type_id :integer
created_at :datetime not null
updated_at :datetime not null
asset_location :string
class Asset < ActiveRecord::Base
extend FriendlyId
friendly_id :asset_name, use: :slugged
validates :asset_name, :asset_serial, :asset_type_id, :asset_model, :asset_manuf, :presence => true
belongs_to :asset_type
end
I think I have the controller wired up fine, I was having issues before with forms and routes by having a controller called assets which is an issue as a reserved name in Rails 4.x.x so I rebuilt the controller as inventory and call the Asset class from within.
My question is, I the search_form_for field to look at the Asset model's field for asset_name but when I write the view as I've laid out I constantly get that path error.
Is there a way to pass a different path into the Ransack search_field method so that I can get past what seems to be an issue with conventions?
If you need more information or if my question is not clear enough, please do not hesitate to edit or ask for more information. Thanks all!
I've made a bit of a mess with my timeclock functionality. Basically what I want to do is pass all of the records in a given search range (which I've already written a model method for and it's working), merge and persist the params into the controller and pass it to a to a to_csv method in the model.
Here's what my controller action looks like with the respond_to block.
def index
@clock_event = current_user.clock_event
@user = current_user
@clock_events = current_user.clock_events.complete.search(params[:search])
respond_to do |format|
format.html do
@clock_events = @clock_events.paginate(:per_page => params[:per_page] || 5, :page => params[:page]).order('created_at DESC')
end
format.csv { send_data ClockEvent.to_csv(@clock_events) }
end
This works fine and dandy, no problems. Now take a look at the model method.
def self.to_csv(records = [], options = {})
CSV.generate(options) do |csv|
csv << ["Employee", "Clock-In", "Clock-Out", "Station", "Comment", "Total Shift Hours", "Total Hours: #{TimeFormatter.format_time(records.sum(&:total_hours))}"]
records.each do |ce|
csv << [ce.user.try(:username), ce.formatted_clock_in, ce.formatted_clock_out, ce.station.try(:station_name), ce.comment, TimeFormatter.format_time(ce.total_hours)]
end
end
end
Since I was shoveling an array into the csv object I really wasn't sure on where to put the total sum of each clock event to calculate the value. So I made a dirty hack by interpolating the object and putting it into the csv header. Is there a better way to do this where I can have the total sum of records
display at the bottom of the CSV file? I'm sure this is simple but I'm just not getting it.
Posted in Code Challenge idea
Sounds great. We should come up with some challenges and get this party started. Chris you want to do the honors or do you want me to write some ridonkulous code :P
When the brainfog clears and the caffeine kicks in, it's go time :)
Ok, I think I figured this out on my own.
The params that were being passed from the form was not [:timecard]
but instead was [:clock_event]
So in my create action in the timecards_controller.rb
I changed the following to get the right params hash.
def create
parse_times!
@clock_event = ClockEvent.new(params[:clock_event])
if @clock_event.save
redirect_to timecard_path(@clock_event.user.id), notice: "Entry added for #{@clock_event.user.username}".html_safe
else
render :new, notice: "Time Card Entry failed to Save".html_safe
end
end
private
def parse_times!
params[:clock_event].parse_time_select! :clock_in if params[:clock_event].has_key? 'clock_in(5i)'
params[:clock_event].parse_time_select! :clock_out if params[:clock_event].has_key? 'clock_out(5i)'
end
In the form I needed to pass the explicit url and the method of post to get this to work since I'm working with an object outside of the Rails namespace convention
<%= form_for @clock_event, url: "/timecards", method: :post do |ce| %>
Voila... It's working!
Disregard guys...
I'm working on my TimeClock functionality for a legacy Rails 3.2.21 app and am running into problems with simple crud type forms.
I'm trying to create a new ClockEvent entry using a basic form in Rails. When I submit the form I raise an exception in the dev log:
undefined method
clock_events_path' for #<#Class:0x007feadcbbf250:0x007feadcbef298>`
Here is what my code looks like:
new.html.erb
<h4>New TimeCard Entry </h4>
<%= form_for (@clock_event) do |ce| %>
<%= ce.collection_select(:user_id, User.employee.order("username ASC"), :id, :username, {:include_blank => true}, {:class => 'select', required: true}) %>
<%= ce.label "Clock In" %>
<%= ce.date_select :clock_in, order: [:month, :day, :year] %></br>
<%= ce.time_select :clock_in, :combined => true, :minute_interval => 1, :start_hour => 00, :end_hour => 23 %>
<%= ce.label "Clock Out" %>
<%= ce.date_select :clock_out, order: [:month, :day, :year] %></br>
<%= ce.time_select :clock_out, :combined => true, :minute_interval => 1, :start_hour => 00, :end_hour => 23 %>
<%= ce.label "Station" %>
<%= ce.collection_select(:station_id, Station.order("station_name ASC"), :id, :station_name, {:include_blank => true}, {:class => 'select', required: true}) %>
<%= ce.button 'Create Entry', class: 'btn btn-info', data: {disable_with: "<i class='icon-spinner'></i>Creating..."} %>
<% end %>
timecards_controller
class TimecardsController < ApplicationController
def index
@users = User.employee.order("username ASC")
end
def new
@clock_event = ClockEvent.new
end
def create
parse_times!
@clock_event = ClockEvent.new(params[:timecard])
if @clock_event.save
redirect_to clock_event_path, notice: "Entry added for #{@clock_event.user.username}".html_safe
else
render :new, notice: "Time Card Entry failed to Save".html_safe
end
end
def show
@user = User.find(params[:id])
@clock_events = @user.clock_events.order("created_at ASC").paginate(:per_page => 10, :page => params[:page])
end
def edit
@user = User.find(params[:id])
@clock_events = @user.clock_events.order("created_at ASC").paginate(:per_page => 10, :page => params[:page])
end
def update
@clock_event = ClockEvent.find(params[:clock_event][:id])
if @clock_event.update_attributes(params[:clock_event])
redirect_to edit_timecard_path(@clock_event.user.id), notice: "Updated Successfully".html_safe
else
redirect_to :back, notice: "Woops.".html_safe
end
end
private
def parse_times!
params[:timecard].parse_time_select! :clock_in if params[:timecard].has_key? 'clock_in(5i)'
params[:timecard].parse_time_select! :clock_out if params[:timecard].has_key? 'clock_out(5i)'
end
end
routes.rb
resources :timecards
output of rake routes
timecards GET /timecards(.:format) timecards#index
POST /timecards(.:format) timecards#create
new_timecard GET /timecards/new(.:format) timecards#new
edit_timecard GET /timecards/:id/edit(.:format) timecards#edit
timecard GET /timecards/:id(.:format) timecards#show
PUT /timecards/:id(.:format) timecards#update
DELETE /timecards/:id(.:format) timecards#destroy
In my new.html.erb
I'm passing the @clock_event
object that's defined under the controller's new
method. But it keeps giving me the
undefined method
clock_events_path' for #<#Class:0x007feadcbbf250:0x007feadcbef298>` error.
Should I be manually passing a URL path and a method for this since the instance variable does not match the controller convention? And if so, what URL should I be passing?
This seems like I'm making some newb mistakes here but I've had an AirPair expert help me with something similar and we had to do some really ugly passing of URL paths with ID to get it to work.
I'm open to feedback, criticism, and slaps on the back of the head.
Posted in Idea for TimeClock Need Advice
Ok, I spoke to soon. I thought I had this all wired up and the complete
scope working. But the !where
doesn't work any longer. I had to write the scope as such:
scope :complete, -> { where("clock_out IS NOT NULL") }
Now it scopes properly. I thought I had this working this morning, I could have sworn it was but I just tested it again and it didn't work until I put in the SQL clause into the scope. Rails is not behaving today.
Posted in Idea for TimeClock Need Advice
scope :incomplete, -> { where(clock_out: nil) }
scope :complete, -> { where.not(clock_out: nil) }
Note I have these two scopes to parse out incomplete and complete punches. Incomplete works but complete gives a nomethoderror
. It appears that the syntax doesn't work at least in this version of Rails. So I rewrote the scope as follows
scope :complete, -> { !where(clock_out: nil) }
So now in my controller I instantiate like so:
def index
@clock_event = current_user.clock_event
@clock_events = current_user.clock_events.complete
end
In my view I show the total hours like so:
<%= TimeFormatter.format_time(@clock_events.sum(&:total_hours)) %>
This will give a sum of all complete time punches. Works like a champ and gets rid of that screwy number in the view when the array contains an incomplete punch. :)
(Yay for small victories). Now to move on to more useful features and kill my prototype app, merge it into my main app as a feature branch.
Posted in Idea for TimeClock Need Advice
That's a good solution, I was thinking something along those lines but felt at first it was a bit hackish. Would still need some alert or indicator of incomplete punch cycles in the view but I think the scope really makes sense. Thanks for the tip :)
Posted in Idea for TimeClock Need Advice
Well the more I think about it, editing the total is sort of a bad idea. Reason being, if you aren't editing the clock in/out fields you have a chance of skewing the total by editing it manually. Then you have all these time punches that don't jive with the total value.
I pretty much have it working the way I like it with calculating total on the fly with to_i
and then parsing in the view with my TimeFormatter class. My main issue right now is when displaying the total hours it shows that screwy negative number when calculating the sum. I need to figure out a way to hide it if there's an incomplete punch (see my pictures above) or somehow calculate all of the punches except the current punch cycle since it's not complete.
Any thoughts on that? I've made great progress with this, but now that it's functional, it's the little things that I need to get a handle on.
Posted in Idea for TimeClock Need Advice
Ping pong... Anyone able to help with this before I go to Stack? Chris? :)
Posted in Code Challenge idea
Chris and I were talking about starting a challenge/kata exercise for the community in Ruby/Rails. Based off of the idea of Underhanded-C, we could post a weekly, bi-weekly, or monthly challenge for all of you to solve. This would be a lot of fun I think and would prove useful as we get different answers on how to solve a Ruby/Rails problem. It would demonstrate everyone's different techniques and code style while providing a way for others to learn. Think of this as a mini-challenge.
I'd like to start threads soon but would like some ideas on different challenges/katas that we could do. Any thoughts on this guys and gals?
So I'm working on a old version of a legacy app Chris and I paired on, trying to refactor some functionality and am hitting a wall.
I currently have some basic paging functionality which creates a "page" (message), and then sends it out to each unit (vehicle) thusly. It's a very simple implementation and works well, but I'm trying to expand it so I can page units within a specific region instead of one by one or all. Here's what my models, views, and controllers look like so far.
unit.rb
class Unit < ActiveRecord::Base
belongs_to :region
end
paging.rb
class Paging < ActiveRecord::Base
attr_accessible :message, :unit_id, :region_id
belongs_to :unit
attr_accessor :region_id
end
region.rb
class Region < ActiveRecord::Base
has_many :units
end
pagings_controller.rb (excerpt)
def index
@pages = Paging.order('created_at DESC').paginate(:per_page => 5, :page => params[:page])
@page = Paging.new
end
def create
message = params[:paging][:message]
units = if params[:paging][:unit_id] == "all"
Unit.active
else
[Unit.find(params[:paging][:unit_id])]
end
units.each do |unit|
@page = Paging.new(params[:paging])
@page.unit_id = unit.id
if @page.save
PagingsMailer.paging(unit.incharge, unit, message).deliver
PagingsMailer.paging(unit.attendant, unit, message).deliver
send_paging_sms
end
end
@page = Paging.new
@pages = Paging.limit(5).order('id desc')
respond_to do |format|
format.html {redirect_to pagings_path, notice: "Page was successfully sent"}
format.js {render "index", notice: "Page was successfully sent"}
end
end
app/views/pagings/_form.html.erb
<%= form_for(@page) do |f| %>
<div class="control-group">
<div class="controls">
<%= f.label :message %>
<%= f.text_area(:message, size: "40x2", :maxlength => 254, placeholder: "Enter your message here", required: true) %>
<%= f.label 'Unit'%>
<%= f.select :unit_id, options_for_select(Unit.active.order(:unit_name).map{ |unit| [unit.unit_name, unit.id] } + [["All Units", "all"]]), {}, {:class => 'select'} %>
<%= f.select :region_id, options_for_select(Region.order(:area).map{ |region| [region.area, region.id]}, {:class => 'select'}) %>
</div>
</br>
<%= f.button 'Send Page', class: 'btn btn-info', data: {disable_with: "<i class='icon-spinner'></i>Sending..."} %>
</div>
<% end %>
I've already refactored the pagings controller create
method to make it cleaner and more DRY, but I'm having a hard time figuring out how to send pages to either a unit, units (all), or units by region.
I'm right in the middle of working on this code so things are not working properly and could use some guidance. As you can see, in the form, I'm mapping the Regions to get the :region_id
so that I can pass it into the params of the request to the controller. Since the paging model does not need to populate the region_id per say (not sure if I need this or not) I've set an attr_accessor
for :region_id
in the paging model.
So two problems I'm facing right now.
In the params request from the form the :region_id
does get passed into the request, but once it hits the controller, I'm unsure of how to deal with it. My initial thought was to assign it to a variable like so:
region = Region.find(params[:paging][:region_id])
This will allow me to grab the :region_id
and use it within the controller action. From there I should be able to do something like this:
region.units.active #pull all units for the specific region_id and scope off of active from the unit model
This is where I'm stuck. I'm unsure as to how to handle the region variable inside my existing create method to create a new page and page it out to each unit within that region without breaking the existing architecture.
Second, once I do figure out how to do this, I need to figure out in the form how to choose whether or not to select by :unit_id
or :region_id
so there form does not pass the params to both.
Sorry if this is a bit scattered, but I'd like to discuss how I might be able to do this. If my question is not clear, please let me know and I'll be happy to elaborate and/or add more sample code.
Cheers!
Posted in I'm lost and can't find the way out
So I think what you'd want to do is add a hidden form field for :uuid
like so.
<%= f.hidden_field :uuid %>
That way validations can run and errors will be raised.
Posted in I'm lost and can't find the way out
I think Chris touched on this with the hidden field of uuid
in your form. That will allow Rails to perform validations on the field and params sent which if there is an error, it will throw it up in the view, which is what you are looking for. If you can output your current version of the form I can show you how to get the errors to show up if you are still having problems. :)
Posted in Idea for TimeClock Need Advice
Anyone have any thoughts on this before I post to the dread StackOverflow? :)
Posted in Must Read / Must Watch
This was a good read, Chris. Thanks for sharing.
Posted in Ransack Scoping issues
Can you post your routes.rb
file and the output rake routes
?
Posted in I'm lost and can't find the way out
Also, there's a gem that can help with whitespaces in a a model's field. I've used it before with good success. Attribute_Normalizer. This won't will only handle leading/trailing whitespace with the strip or squish option but it works really well to sanitize your data. I use it in nearly every app I've written where I need to make sure there's no goofy data entry. After installation here's a quick snippet on how I use it in a model:
normalize_attribute :name, address, :with => :squish
Posted in I'm lost and can't find the way out
Chris beat me to the punch, foiled again :)