Getting input from view to scope an index - ruby-on-rails-3

So I am trying to add the ability to select a user in the view, and then return only the Lists that are associated with that user. I can do this for now hard coded in the controller.
def show
#some_lists = List.sort(:boolean => true, :user_id => 3)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #some_list }
end
end
But I want to be able to choose the user from the views
<% #some_lists.each do |list| %>
<tr>
<td><%= list.id_name %></td>
<td><%= list.day %></td>
<td><%= list.start_time %></td>
<td><%= list.end_time %></td>
</tr>
<% end %>
What is the best way to go about doing this, I also plan on adding the ability to sort by the list.start_time and list.end_time as well

You'll definitely want to do this with AJAX. For the specific thing you want to do (filtering/sorting a table) there's a javascript plugin I would recommend:
DataTables
(you'll want to check out the documentation on server-side processing)
There's even a really nice tutorial to using it with rails in RailsCast #340

Related

How to use index action of controller of a model that belongs to another model?

I'm coding a rails application to handle scheduling for university classes. Currently, I'm trying to make an index page to show all of the sections in the database, but I'm getting this error:
No route matches {:action=>"index", :controller=>"sections"}
However, when I look at my routes, I can see a controller action pair for section and index.
bin/rails routes
Prefix Verb URI Pattern Controller#Action
home_index GET /home/index(.:format) home#index
course_sections GET /courses/:course_id/sections(.:format) sections#index
POST /courses/:course_id/sections(.:format) sections#create
new_course_section GET /courses/:course_id/sections/new(.:format) sections#new
edit_course_section GET /courses/:course_id/sections/:id/edit(.:format) sections#edit
course_section GET /courses/:course_id/sections/:id(.:format) sections#show
PATCH /courses/:course_id/sections/:id(.:format) sections#update
PUT /courses/:course_id/sections/:id(.:format) sections#update
DELETE /courses/:course_id/sections/:id(.:format) sections#destroy
courses GET /courses(.:format) courses#index
POST /courses(.:format) courses#create
new_course GET /courses/new(.:format) courses#new
edit_course GET /courses/:id/edit(.:format) courses#edit
course GET /courses/:id(.:format) courses#show
PATCH /courses/:id(.:format) courses#update
PUT /courses/:id(.:format) courses#update
DELETE /courses/:id(.:format) courses#destroy
students GET /students(.:format) students#index
POST /students(.:format) students#create
new_student GET /students/new(.:format) students#new
edit_student GET /students/:id/edit(.:format) students#edit
student GET /students/:id(.:format) students#show
PATCH /students/:id(.:format) students#update
PUT /students/:id(.:format) students#update
DELETE /students/:id(.:format) students#destroy
root GET / home#index
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
Why does it not route correctly?
My section controller looks like this:
class SectionsController < ApplicationController
def index
#courses = Course.all
end
def create
#course = Course.find(params[:course_id])
#section = #course.sections.create(section_params)
end
def update
#course = Course.find(params[:course_id])
#section = #course.sections.find(params[:id])
#section.update(section_params)
end
def destroy
#course = Course.find(params[:course_id])
#section = #course.sections.find(params[:id])
#section.destroy
end
private
def section_params
params.require(:section).permit(:section_letter, :section_professor, :section_meetings, :section_capacity)
end
end
My index.html.erb view in the sections folder looks like this:
<h2>Sections</h2>
<table>
<tr>
<th>Number</th>
<th>Section</th>
<th>Name</th>
<th>Credit Hours</th>
<th>Professor</th>
<th>Meetings</th>
<th>Capacity</th>
</tr>
<% #courses.each do |course| %>
<% course.sections.each do |section| %>
<tr>
<td><%= course.course_num %></td>
<td><%= section.section_letter %></td>
<td><%= course.course_name %></td>
<td><%= course.course_credits %></td>
<td><%= section.section_professor %></td>
<td><%= section.section_meetings %></td>
<td><%= section.section_capacity %></td>
</tr>
<% end %>
<% end %>
</table>
And my routes file looks like:
Rails.application.routes.draw do
get 'home/index'
resources :courses do
resources :sections
end
resources :students
root 'home#index'
end
Any help is appreciated!
Its because the sections controller is a nested resource under the courses resource. There is a sections#index but it takes a :course_id parameter.
In other words there is no /sections path that directly maps to sections#index
If its a one-off endpoint you can declare this route
get 'sections' => 'sections#index', as: :sections
And you'd then need to update the #index method in the SectionsController and just pull all Sections like
#sections = Section.all

Combine API data with local data in Rails

I am working with the GoCardless API in my Rails 3 application. I have a subscription model which has a resource_id column which matches the id of the remote record.
I am trying to get extra information for a local subscription record from the API.
Subscription Index View
<% #subscriptions.each do |subscription| %>
<tr>
<td><%= subscription.resource_id %></td>
<td><%= subscription.resource_type %></td>
<td><%= subscription.signature %></td>
<td><%= subscription.state %></td>
<td><%= #gocardless.next_interval_start %></td>
<td><%= link_to 'Show', subscription %></td>
<td><%= link_to 'Edit', edit_subscription_path(subscription) %></td>
<td><%= link_to 'Destroy', subscription, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
Subscription Controller
def index
#subscriptions = Subscription.all
#gocardless = GoCardless::Merchant.find("XXXXXXXXXX").subscriptions
respond_to do |format|
format.html # index.html.erb
format.json { render json: #subscriptions }
end
end
As you can see I'm using the following line to retrieve the next interval start date
<%= #gocardless.next_interval_start %>
This doesn't work and returns nil. However, if I change it to the following all records show the value from the first record from the API.
<%= #gocardless.first.next_interval_start %>
According to the GoCardless API documentation you can lookup a subscription using the following:
GoCardless::Subscription.find("XXXXXXXXXX") # => #<GoCardless::Subscription ...>
So, my question. How do I pass the current subscription resource_id to the API so that I can view the next_internal_start value for each of the local subscription records?
Update
Using Adam's example below I get a 404 response from GoCardless. I think it's due to me not setting the merchant ID in the request. When I change the method to:
def gc_subscription
#gc_subscription ||= GoCardless::Merchant.find("MERCHANTID").subscriptions.find(self.resource_id)
end
I get undefined methodinterval' for #` for any attribute I try and request using the following code:
<% for subscription in #subscriptions %>
<%= subscription.gc_subscription.amount
<% end %>
When using the same code to get local content it works as expected:
<% for subscription in #subscriptions %>
<%= subscription.resource_id %>
<% end %>
I've checked that the value I am trying to retrieve is available in the API. https://sandbox.gocardless.com/docs/api_guide#resources-available
Update Two
As before calling the first result works using Adam's method:
<%= subscription.gc_subscription.first.amount %>
This returns 2.5 which is the value of the first subscription.
If I had a local Subscription model which linked to a remote data source I would have a method like this on my Subscription model which provided access to the remote object:
def gc_subscription
#gc_subscription ||= GoCardless::Subscription.find(self.resource_id)
end
Then you can access this method as necessary without any need for any GC logic in the view or controller. For example:
for subscription in #subscriptions
subscription.gc_subscription.some_method #=> "output"
end
Or, if you are only working with one subscription:
subscription = Subscription.find(id)
subscription #=> Your local Subscription instance
subscription.gc_subscription #=> GoCardless::Subscription instance
With it configured like that, you will be able to remove the #gocardless from your controller and replace your view with this:
<% #subscriptions.each do |subscription| %>
<tr>
<td><%= subscription.resource_id %></td>
<td><%= subscription.resource_type %></td>
<td><%= subscription.signature %></td>
<td><%= subscription.state %></td>
<td><%= subscription.gc_subscription.next_interval_start %></td>
<td><%= link_to 'Show', subscription %></td>
<td><%= link_to 'Edit', edit_subscription_path(subscription) %></td>
<td><%= link_to 'Destroy', subscription, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
I hope that helps.

output belongs_and_has_many value in show action

I have the following code but can't render color as expected. When I render item.color I get #<Color:0x007ffce487a648>for example. If I render item.color.map(&:name) I get undefined method map for #<Color:0x007ffce6616918>
<% #this_week_orders.each do |order| %>
<tr style="font-weight:bold;">
<td><%= link_to "Order #{order.id}", order_path(order) %></td>
<td><%= l order.date, :format => :long %></td>
<td><%= pluralize(order.items.count, "item") %></td>
<td><%= number_to_currency(order.total_price) %></td>
<tr>
<% for item in order.items %>
<tr>
<td><li><%= item.product.name %></li></td>
<td><%= item.color %></td>
</tr>
<% end %>
<% end %>
Order has_many :items
Item belongs_to :order
Item belongs_to :product
Item belongs_to :color
scope :this_week, lambda { where("date > ?", 7.days.ago) }
Order controller
def this_week
#this_week_orders = Order.this_week.all
respond_to do |format|
format.html # index.html.erb
end
end
#<Color:0x007ffce487a648> reperesents an object of class Color (not a collection of color objects, whereupon it would make sense to use map). If Color has a name attribute, just write <%= item.color.name %>.
map is for use on an Array. item.color only returns one object. Use:
<%= item.color.name %>
if Color is a class like it appears to be you need to set the color value:
Something like:
<%= item.color.name %>
or whatever your value for the color is.

Is it possible to use MetaSearch on checkboxes for strings?

I have an index page of Users that I want to filter with a search form using MetaSearch. However the values I want to search when I checkbox is clicked are stored as strings. For example, here's a form I want to apply MetaSearch to:
<% form_for(current_user.profile) do |f| %>
<table id="careerCriteria">
<tr>
<td class="normal"><%= current_user.profile.hometown %></td>
<td><%= check_box_tag :hometown %></td>
</tr>
<tr>
<td class="normal"><%= current_user.profile.current_city %></td>
<td><%= check_box_tag :current_city %></td>
</tr>
<tr>
<td class="normal"><%= current_user.profile.past_city %></td>
<td><%= check_box_tag :past_city %></td>
</tr>
</table>
<% end %>
My User model:
class User < ActiveRecord::Base
has_one :profile, :dependent => :destroy
end
I don't want to use a search button. I want the filter(s) to be applied when the checkbox (or checkboxes) are clicked. I'm new to programming so any help would be appreciated!
You'll need a little ajax & query to accomplish this.
Here's a good article to show you how to make the checkbox submit the form.
http://trevorturk.com/2010/08/24/easy-ajax-forms-with-rails-3-and-jquery/
What you'll want to do is create an action in the controller that handles your search. Here's an example of a search action...
def search
if params[:term].blank?
raise "You must provide search criteria."
end
params[:term] = "%#{params[:term]}%"
conditions = " Description LIKE :term"
#careers = Career.all(
:conditions => [conditions, params],
:offset => params[:offset],
:limit => params[:limit]
)
respond_with #careers
end
You'll also need to setup a route for this search for this action.
resources :careers do
get "search/:term/:offset/:limit.:format", :action => "search", :constraints => { :offset => /\d+/, :limit => /\d+/ }
end
Once you get the form submitting to this action you should be able to use jQuery to update the results.
Now keep in mind if you don't want to use Ajax & jQuery to load the results you can do so, you'll just take the remote action out of the form tag and it will refresh the whole page.

how to query in view ruby on rails

i have this in the controller
#ads = Ad.all(:joins => 'LEFT JOIN states ON ads.state_id = states.id')
but i have problem to query field of states table.
any idea?
<% #ads.each do |ad| %>
<tr>
<td><%= ad.title %></td> <- title is ad field.no problem
<td><%= ad.name %></td> <- name is states field.problem at here
</tr>
<% end %>
I don't think this will work unless you have associations set up. Unless performance is a concern, you may just want to use the association without joins
ad.rb
class Ad < ActiveRecord::Base
belongs_to :state
end
state.rb
class State < ActiveRecord::Base
has_many :ads
end
controller
#ads = Ad.all
view
<% #ads.each do |ad| %>
<tr>
<td><%= ad.title %></td>
<td>
<%= ad.state.name %>
</td>
</tr>
<% end %>
I think you need to put this: ads.state_id = states.id like this: #{ads.state_id = states.id}
The #{ } will evaluate the ruby code inside. Otherwise what you have is just text inside a string.
I'm not quite sure what your issue is, though, so I'm not totally sure that will fix it.