I am a bit new to Ruby and am writing a program from scratch... I'm getting an error and I can't figure out where it is coming from. I've spent over an hour and i'm sure it's something stupidly simple. I have other similar pages that work fine, but there's some issue with the instance variable. It's almost an identical problem as the link provided.
Here's my error:
Showing C:/Users/kevin/Desktop/ruby_test/sites/simple_cms/app/views/sections/_form.html.erb where line #4 raised:
undefined method `collect' for nil:NilClass
Extracted source (around line #4):
1 <table summary="Section form fields">
2 <tr>
3 <th><%= f.label(:page_id, "Page") %></th>
4 <td><%= f.select(:page_id, #pages.collect {|p| [p.name, p.id]}) %>
5 </td>
6 </tr>
7 <tr>
Trace of template inclusion: app/views/sections/edit.html.erb
Rails.root: C:/Users/kevin/Desktop/ruby_test/sites/simple_cms
Here's my forms page:
<table summary="Section form fields">
<tr>
<th><%= f.label(:page_id, "Page") %></th>
<td><%= f.select(:page_id, #pages.collect {|p| [p.name, p.id]}) %>
</td>
</tr>
<tr>
<th><%= f.label(:name) %></th>
<td><%= f.text_field(:name) %></td>
</tr>
<tr>
<th><%= f.label(:position) %></th>
<td><%= f.select(:position, 1..#section_count) %></td>
</tr>
<tr>
<th><%= f.label(:visible) %></th>
<td><%= f.check_box(:visible) %></td>
</tr>
<tr>
<th><%= f.label(:content_type) %></th>
<td>
<%= f.radio_button(:content_type, 'text') %> Text
<%= f.radio_button(:content_type, 'HTML') %> HTML
</td>
</tr>
<tr>
<th><%= f.label(:content) %></th>
<td><%= f.text_area(:content, :size => '40x10') %></td>
</tr>
</table>
Here's my controller:
class SectionsController < ApplicationController
layout "admin"
def index
#sections = Section.sorted
end
def show
#section = Section.find(params[:id])
end
def new
#section = Section.new({:name => "Default"})
#pages = Page.order('position ASC')
#section_count = Section.count + 1
end
def create
#section = Section.new(section_params)
if #section.save
flash[:notice] = "Section created successfully."
redirect_to(:action => 'index')
else
#pages = Page.order('position ASC')
#section_count = Section.count
render('new')
end
end
def edit
#section = Section.find(params[:id])
end
def update
#section = Section.find(params[:id])
if #section.update_attributes(section_params)
flash[:notice] = "Section updated successfully."
redirect_to(:action => 'show', :id => #section.id)
else
#pages = Page.order('position ASC')
#section_count = Section.count
render('edit')
end
end
def delete
#section = Section.find(params[:id])
end
def destroy
section = Section.find(params[:id]).destroy
flash[:notice] = "Section destroyed successfully."
redirect_to(:action => 'index')
end
private
def section_params
params.require(:section).permit(:page_id, :name, :position, :visible, :content_type, :content)
end
end
Here's the view page (edit):
<% #page_title = "Edit Section" %>
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="sections edit">
<h2>Update Section</h2>
<%= form_for(:section, :url => {:action => 'update', :id => #section.id}) do |f| %>
<%= render(:partial => "form", :locals => {:f => f}) %>
<div class="form-buttons">
<%= submit_tag("Update Section") %>
</div>
<% end %>
</div>
You should define #pages and #section_count variables in appropriate controller action:
def edit
#section = Section.find(params[:id])
#pages = Page.order('position ASC')
#section_count = Section.count
end
You also have a mistake in create action. When it doesn't create a record, #section_count should be Section.count + 1 as in new action.
Your controller could be also refractor to this
Related
Actually I want to display all data of Magazine model on the admin side page But i got the following error while tried to fetch all data on the admin side(i.e.http://localhost:3000/homes/magazineissue).I also want to display some value belongs to User model through user's id.
Error:
NoMethodError in HomesController#magazineissue
undefined method `user_id' for #<Array:0x2780b98>
Rails.root: C:/Site/library_management1
Application Trace | Framework Trace | Full Trace
app/controllers/homes_controller.rb:100:in `magazineissue'
My codes are as follows.
views/homes/magazineissue.html.erb:
<% if admin_signed_in? %>
<div class="bar">
Logged in as <strong><%= current_admin.email %></strong>.
<%= link_to 'Edit profile', edit_admin_registration_path, :class => 'navbar-link' %> |
<%= link_to "Logout", destroy_admin_session_path, method: :delete, :class => 'navbar-link' %>
</div>
<% else %>
<%= link_to "Sign up", new_admin_registration_path, :class => 'navbar-link' %> |
<%= link_to "Login", new_admin_session_path, :class => 'navbar-link' %>
<% end %>
<div class="big-container">
<div class="admin-image">
<div class="bpaddingdiv1"><img src="/assets/admin.png" border="0" name="admin" /></div>
</div>
<div class="borderlightgreen"></div>
<div class="admin-name">
<div class="tpaddingdiv2 textaligncenterdiv"><img src="/assets/adminpanel.png" border="0" name="admin" /></div>
</div>
<div class="leftside">
<div id="leftsidebtn">
<ul>
<li>Manage Books</li>
<li><a href="/homes/userissues" >User Issues</a></li>
<li><a href="/homes/magazineissue" >Magazine Issues</a></li>
</ul>
</div>
</div>
<div class="middlebox">
<center>
<table>
<thead>
<tr>
<th>First Name</th>
<th>Email Id</th>
<th>Magazine Name</th>
<th>Magazine Title</th>
<th>Purchased on</th>
<th>CD/DVD</th>
</tr>
</thead>
<tbody>
<% #magazines.each do |magazine| %>
<tr>
<td><%= #users.first_name %></td>
<td><%= #users.email %></td>
<td><%= magazine.mag_name %></td>
<td><%= magazine.mag_title %></td>
<td><%= magazine.purchased_on %></td>
<td><%= magazine.cd_dvd %></td>
</tr>
<% end %>
</tbody>
</table>
</center>
</div>
</div>
views/controller/homes_controller.rb:
class HomesController < ApplicationController
before_filter :authenticate_admin!,only: [:admin]
def index
end
def admin
end
def managebooks
#books=Book.new
if params[:id]
#books=Book.find(params[:id])
#book=Book.all
end
end
def savebooks
#books=Book.new(params[:books])
if #books.save
flash[:notice]="Data has submitted successfully"
flash[:color]="valid"
redirect_to :action => 'managebooks',:id => #books.id
else
flash[:notice]="Data couldnot submitted successfully"
flash[:color]="invalid"
render 'managebooks'
end
end
def remove
#books=Book.find(params[:id])
#books.destroy
end
def books
end
def showbooks
#books=Book.all
end
def searchbooks
#books=Book.all
end
def member
#users=User.new
end
def registration
#users=User.new
end
def savedata
#users=User.new(params[:users])
if #users.save
flash[:notice]="Data has submitted successfully"
flash[:color]="valid"
redirect_to :action => 'member'
else
flash[:notice]="Data could not submitted successfully"
flash[:color]="invalid"
render 'registration'
end
end
def issuebooks
#issues=Issue.new
end
def savedissuebooks
#issues=Issue.new(params[:issues])
if #issues.save
flash[:notice]="information has saved successfully"
flash[:color]="valid"
redirect_to :action => 'member'
else
flash[:notice]="Data couldnot saved"
flash[:color]="invalid"
render 'issuebooks'
end
end
def availablebooks
#books=Book.all
end
def userissues
#issues=Issue.all
end
def magazine
#magazines=Magazine.new
end
def savemagazines
#users=User.find(params[:id])
#magazines=Magazine.new(params[:magazines])
#magazines.user_id=#users.id
if #magazines.save
flash[:notice]="Data submitted successfully"
flash[:color]="valid"
redirect_to :action => "member"
else
flash[:notice]="Data could not saved"
flash[:color]="invalid"
render 'magazines'
end
end
def magazineissue
#magazines=Magazine.all
#users=User.find(#magazines.user_id)
end
end
db/migrate/20150317084229_create_magazines.rb
class CreateMagazines < ActiveRecord::Migration
def change
create_table :magazines do |t|
t.string :mag_name
t.boolean :cd_dvd
t.decimal :cost, :precision => 8, :scale => 2
t.date :purchased_on
t.string :mag_title
t.integer :user_id
t.timestamps
end
end
end
model/magazine.rb
class Magazine < ActiveRecord::Base
attr_accessible :cd_dvd, :cost, :mag_name, :mag_title, :purchased_on
belongs_to :user
end
model/user.rb
class User < ActiveRecord::Base
attr_accessible :address, :email, :first_name, :last_name, :password, :password_hash, :password_salt, :tel_no ,:password_confirmation
attr_accessor :password
before_save :encrypt_password
EMAIL_REGEX = /\A[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
validates :first_name, :presence => true, :length => {:in => 3..10}
validates :last_name , :presence => true , :length => {:in => 3..10}
validates :tel_no , :presence => true , :length => {:in => 1..10}
validates :password, :confirmation => true
validates_length_of :password, :in => 6..20, :on => :create
def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
has_many :issue
has_many :book
has_many :magazine
end
Please help me to resolve this error.
As you have defined:
#magazines = Magazine.all
It results an Array that contains all the magazines.
Now in your HomeController you are doing:
#magazines.user_id
Which throws:
undefined method `user_id' for #<Array:0x2780b98>
because as mentioned above #magazines is an Array.
Solution to this can be to select a particular Magazine object from the returned #magazines Array and proceed.
A quick example can be:
#users=User.find #magazines.first.user_id
# However this is just for sake of example.
# You may want to select an object from the Array more wisely.
The problem is in controller in line you already mentioned - let's take a look:
def magazineissue
#magazines=Magazine.all
#users=User.find(#magazines.user_id)
end
In here you are fetching an Array of Magazines - the Array doesn't have an id method. What I guess you would like to do is something like:
def magazineissue
#magazines=Magazine.all
#users=User.find(#magazines.map(&:user_id))
end
To fetch Users by ALL Magazines.
Let me know if it helped!
UPDATE
From the comments we had it looks like you're trying to achieve something like:
def magazineissue
#magazines=Magazine.includes(:user).all
end
And in your view, change the <table> to:
<table>
<thead>
<tr>
<th>First Name</th>
<th>Email Id</th>
<th>Magazine Name</th>
<th>Magazine Title</th>
<th>Purchased on</th>
<th>CD/DVD</th>
</tr>
</thead>
<tbody>
<% #magazines.each do |magazine| %>
<tr>
<td><%= magazine.user.first_name %></td>
<td><%= magazine.user.email %></td>
<td><%= magazine.mag_name %></td>
<td><%= magazine.mag_title %></td>
<td><%= magazine.purchased_on %></td>
<td><%= magazine.cd_dvd %></td>
</tr>
<% end %>
</tbody>
</table>
Good luck!
I am making a search to my index.html.erb and it gives me an error.
This is my index.html.erb:
<% provide(:title, 'All configurations') %>
<h1>All configurations</h1>
<%= form_tag conf_show_all_path, :method => 'get' do %>
<%= hidden_field_tag :direction, params[:direction] %>
<%= hidden_field_tag :sort, params[:sort] %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<table class="pretty" border="1" cellpadding="10">
<tr>
<th><%= sortable("machine_name", "M.Name") %></th>
<th><%= sortable("machine_brand", "M.Brand") %></th>
<th><%= sortable("machine_model", "M.Model") %></th>
<th><%= sortable("control_unit_brand", "C.Unit Brand") %></th>
<th><%= sortable("control_unit_model", "C.Unit Model") %></th>
<th><%= sortable("tool_axis_x", "Axis X") %></th>
<th><%= sortable("tool_axis_y", "Axis Y") %></th>
<th><%= sortable("tool_axis_z", "Axis Z") %></th>
<th><%= sortable("rotary_axis_number", "R.Axis") %></th>
<th><%= sortable("linear_axis_number", "L.Axis") %></th>
<th><%= sortable "description" %></th>
<th><%= sortable("name", "Developer") %></th>
<th><%= sortable "updated_at" %></th>
</tr>
<% for conf in #confs %>
<tr class="<%= cycle('oddrow', 'evenrow') -%>">
<td><%= link_to conf.machine_name, conf %></td>
<td><%= conf.machine_brand %></td>
<td><%= conf.machine_model %></td>
<td><%= conf.control_unit_brand %></td>
<td><%= conf.control_unit_model %></td>
<td><%= conf.tool_axis_x %></td>
<td><%= conf.tool_axis_y %></td>
<td><%= conf.tool_axis_z %></td>
<td><%= conf.rotary_axis_number %></td>
<td><%= conf.linear_axis_number %></td>
<td><%= conf.description %></td>
<td><%= conf.developer.name unless conf.developer_id.blank? %></td>
<td><%= conf.updated_at %></td>
</tr>
<% end %>
</table>
<%= will_paginate #confs %>
This is search in conf.rb:
def self.search(search)
if search
q = "%#{search}%"
where('machine_name LIKE ? OR
machine_brand LIKE ? OR
machine_model LIKE ? OR
control_unit_brand LIKE ? OR
control_unit_model LIKE ? OR
tool_axis_x LIKE ? OR
tool_axis_y LIKE ? OR
tool_axis_z LIKE ? OR
rotary_axis_number LIKE ? OR
linear_axis_number LIKE ? OR
description LIKE ? OR
developer_id LIKE ? OR
updated_at LIKE ? OR',
q,q,q,q,q,q,q,q,q,q,q,q,q)
else
scoped
end
end
This is sortable method in application_helper.rb:
def sortable(column, title = nil)
title ||= column.titleize
css_class = (column == sort_column) ? "current #{sort_direction}" : nil
direction = (column == sort_column && sort_direction == "asc") ? "desc" : "asc"
link_to title, params.merge(:sort => column, :direction => direction, :page => nil), {:class => css_class}
end
Finally, this is the error:
ActiveRecord::StatementInvalid in Confs#index
SQLite3::SQLException: no such column: name: SELECT "confs".* FROM "confs" ORDER BY name asc LIMIT 10 OFFSET 0
Extracted source (around line #30)
Line 30 is this:
What is the problem and how can I fix it?
ok, search in conf.rb should updated_at LIKE ?' instead of updated_at LIKE ? OR' this was one syntax error. About question, I changed sort_column in confs_controller.rb from ...params[:sort] : "name" to ...params[:sort] : "machine_name"
I am making a sorting function in order to sort a list of users. This sorting function designed to sort according to attributes (columns). User model has a column company_id but I don't want to sort by number, I want to sort by name of the company. BTW,
company :has_many users
and
user :belongs_to company
This is my index.html.erb:
<table class="pretty" border="1" cellpadding="10">
<tr>
<th></th>
<th><%= sortable "name" %></th>
<th><%= sortable "email" %></th>
<th><%= sortable "company_id" %></th>
<th>DELETE</th>
</tr>
<% for user in #users %>
<tr class="<%= cycle('oddrow', 'evenrow') -%>">
<td><%= gravatar_for user %></td>
<td><%= link_to user.name, user %></td>
<td><%= user.email %></td>
<td><%= user.company.name unless user.company_id.blank? %></td>
<td><% if current_user.admin? || ( ( current_user.developer? && !current_user?(user) ) && (user.boss_id == current_user.id) ) %>
|| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %></td>
</tr>
<% end %>
</table>
<%= will_paginate #users %>
This is sortable function from application_helper.rb:
def sortable(column, title = nil)
title ||= column.titleize
css_class = (column == sort_column) ? "current #{sort_direction}" : nil
direction = (column == sort_column && sort_direction == "asc") ? "desc" : "asc"
link_to title, params.merge(:sort => column, :direction => direction, :page => nil), {:class => css_class}
end
And this is users_controller.rb:
helper_method :sort_column, :sort_direction
def index
#users = User.where(:developer => false, :admin => false).search(params[:search]).order(sort_column + ' ' + sort_direction).paginate(:per_page => 10, :page => params[:page])
end
private
def sort_column
User.column_names.include?(params[:sort]) ? params[:sort] : "name"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
So, how can I modify this in order to sort by Company.name rather than User.company_id?
I solved this by changing <%= sortable "company_id" %> to <%= sortable("name", "Company") %> and changing
User.column_names.include?(params[:sort]) ? params[:sort] : "name"
to
(( User.column_names.include?(params[:sort]) ) || ( Company.column_names.include?(params[:sort]) )) ? params[:sort] : "name"
Syntax in mongodb:
db.orders.aggregate(
{$unwind: "$lines"},
{$group :
{_id: {sku: "$lines.sku", desc: "$lines.description"},
qty : {$sum : 1}}},{ $sort : { qty : -1}}
)
I want to to show the result of the above query on Rails.
I'm using Mongoid with Rails 4 and my Gemfile:
gem 'mongoid', github: 'mongoid/mongoid'
As I understand, the only way to write the query above is to install gem for moped driver.
So, my 1st question is how that line should be declared in the Gemfile for Rails 4 and Ruby 2.0 ?
I assume the query in moped would look like:
Order.collection.aggregate(
{"$unwind" => "$lines"},
{"$group" => {"_id" => {"sku" => "$lines.sku", desc => "$lines.description"},
qty => {"$sum" => 1}}},
{ "$sort" => { "qty" => -1}})
I would like to show results of this query, by clicking a button on the index page without passing parameters.
The 2nd question is that I can't figure out how to change controller and index view page to put a button that will call this query.
UPDATE
index method part of the controller as below:
def index
#orders = if params[:search]
Order.search(params[:search]).queryable.asc(:_id).paginate(:page => params[:page], :per_page => 20)
elsif params[:search_from] && params[:search_to]
Order.search_date(params[:search_from], params[:search_to]).queryable.asc(:_id).paginate(:page => params[:page], :per_page => 20)
else
Order.shipping_today(Date.today, Date.today).queryable.asc(:_id).paginate(:page => params[:page], :per_page => 20)
end
index.html.erb:
<h1>Date: <%= Date.today %></h1>
<%= form_tag orders_path, :method => 'get' do %>
<p>Order date range:<br>
<%= text_field_tag :search_from, params[:search_from] %> - <%= text_field_tag :search_to, params[:search_to] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<%= form_tag orders_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
<%= link_to "Reset", orders_path %>
</p>
<% end %>
<%= form_tag orders_path, :method => 'get' do %>
<p>
<%= submit_tag "Statistics", :name => nil %>
</p>
<% end %>
<div class="digg_pagination">
<div class="page_info">
<%= page_entries_info #orders %>
</div>
<%= will_paginate #orders, :container => false %>
</div>
<br />
<table border = 1 >
<thead>
<tr>
<th>Shipping date</th>
<th>Order #</th>
<th>Ship to name</th>
<th>Tracking #</th>
<th>Shipped</th>
<th>Action</th>
<th></th>
</tr>
</thead>
<tbody>
<% #orders.each do |order| %>
<tr>
<td><%= order.shipping_date %></td>
<td><%= link_to order.order_number, order_path(order) %></td>
<td><%= order.ship_to_fname %></td>
<td><%= order.track_num %></td>
<td><%= order.ship_date %></td>
<td><%= link_to 'Edit', edit_order_path(order) %></td>
<td><%= link_to 'New', new_order_path(order) %></td>
<td><%= link_to 'Destroy', order, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br />
<%= link_to 'New Order', new_order_path %>
The line in Gemfile that you wrote gem 'mongoid', github: 'mongoid/mongoid' should be enough for that query to work.
After aggregate commant you'll get an array with the result of the aggregation.
You can assign it to the instance variable in the controller and iterate on it in view.
For example:
# LinesController
def index
#lines = Order.collection.aggregate(
{"$unwind" => "$lines"},
{"$group" => {"_id" => {"sku" => "$lines.sku", desc => "$lines.description"},
qty => {"$sum" => 1}}},
{ "$sort" => { "qty" => -1}})
end
# lines/index.html.erb
<ul>
<% #lines.each do |line| %>
<li>
<b><%= line['_id']['sku'] %></b>
<%= line['qty'] %>
</li>
<% end %>
</ul>
I've reproduced the code from RailsCasts episode 240. I have no idea why with this code the Ajax requests don't work. The search function works with the normal method (reload page) sadly not through Ajax. The sort function works not at all.
I've included following JavaScript libraries:
application.js
jQuery JavaScript Library v1.6.2
jQuery UI 1.8.15
jQuery.rails.js
jQuery TinySort v1.1.0
If you need more information please let me know. I hope really you can help me to solve the problems.
users_controller.rb
def index
#users = User.search(params[:search]).order(sort_column + " " + sort_direction)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #users }
end
end
def sort_column
User.column_names.include?(params[:sort]) ? params[:sort] : "lastname"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
index.html.erb
<h1>Listing users</h1>
<%= form_tag users_path, :method => 'get', :id => "users_search" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<div id="users">
<%= render 'users' %>
</div>
<% end %>
_users.html.erb
<%= hidden_field_tag :direction, params[:direction] %>
<%= hidden_field_tag :sort, params[:sort] %>
<table class="pretty">
<tr>
<th><%= sortable "Last name" %></th>
<th><%= sortable "First name" %></th>
</tr>
<% for user in #users %>
<tr>
<td><%= user.lastname %></td>
<td><%= user.firstname %></td>
</tr>
<% end %>
</table>
index.js.erb
$("#users").html("<%= escape_javascript(render("users")) %>");
users_helper.rb
def sortable(column, title = nil)
title ||= column.titleize
css_class = column == sort_column ? "current #{sort_direction}" : nil
direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"
link_to title, params.merge(:sort => column, :direction => direction, :page => nil), {:class => css_class}
end
application.js
$(function() {
$("#users th a").live("click", function() {
$.getScript(this.href);
return false;
});
$("#users_search input").keyup(function() {
$.get($("#users_search").attr("action"), $("#users_search").serialize(), null, "script");
return false;
});
});
Thank you for your help!
For the above code to work, you have to delete the following lines of code.
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #users }
end
Now it works. :-)