I am receiving a undefined method `name' for # error for my Rails project. I know that name is defined for events by double checking using my console, so I don't understand why it won't load. Here is some of my code:
Apps Show:
<h1><%= #app.title %></h1>
<h5>App URL: <%= #app.url %></h5>
<h5>App User_id: <%= #app.user_id %></h5>
<br>
<h2> Events </h2>
<% #events.each do |event| %>
<div>
<%= event.name %><span class="badge"><%= event.count %></span>
</div>
<% end %>
<br>
<%= link_to "Edit", edit_app_path(#app), class: 'btn btn-success' %>
Apps Controller:
class AppsController < ApplicationController
def create
#app = App.new(params.require(:app).permit(:title, :url))
#app.user_id = 1
if #app.save
flash[:notice] = "App was saved!"
redirect_to #app
else
flash[:error] = "There an error, oh noes!Please try again!"
render :new
end
end
def new
#app = App.new
end
def show
#app = App.find(params[:id])
#events = #app.events.group_by(&:name)
end
def index
#apps = App.all
end
def edit
#app = App.find(params[:id])
end
def update
#app = App.find(params[:id])
if #app.update_attributes(params.require(:app).permit(:title, :url))
flash[:notice] = "Application was updated."
redirect_to #app
else
flash[:error] = "There was an error saving the app. Please try again."
render :edit
end
end
def destroy
#app = App.find(params[:id])
if #app.destroy
flash[:notice] = "App was removed."
redirect_to #app
else
flash[:error] = "App couldn't be deleted. Try again."
redirect_to #app
end
respond_to do |format|
format.html
format.js
end
end
end
Events Seed:
create_table "events", force: :cascade do |t|
t.integer "app_id"
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
App Model:
class App < ActiveRecord::Base
belongs_to :user
has_many :events
end
Complete Error Log:
Completed 500 Internal Server Error in 19ms
ActionView::Template::Error (undefined method `name' for #<Array:0x007fcc53394af0>):
6: <h2> Events </h2>
7: <% #events.each do |event| %>
8: <div>
9: <%= event.name %><span class="badge"><%= event.count %></span>
10: </div>
11: <% end %>
12: <br>
app/views/apps/show.html.erb:9:in `block in _app_views_apps_show_html_erb__2949113196422864311_70257764571040'
app/views/apps/show.html.erb:7:in `each'
app/views/apps/show.html.erb:7:in `_app_views_apps_show_html_erb__2949113196422864311_70257764571040'
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_source.erb (7.1ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (4.1ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.9ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (71.2ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/web-console-2.1.3/lib/web_console/templates/_markup.html.erb (0.7ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/web-console-2.1.3/lib/web_console/templates/style.css.erb within layouts/inlined_string (0.7ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/web-console-2.1.3/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (0.5ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/web-console-2.1.3/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (0.3ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/web-console-2.1.3/lib/web_console/templates/console.js.erb within layouts/javascript (69.6ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/web-console-2.1.3/lib/web_console/templates/main.js.erb within layouts/javascript (0.4ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/web-console-2.1.3/lib/web_console/templates/error_page.js.erb within layouts/javascript (0.7ms)
Rendered /Users/ericpark/.rvm/gems/ruby-2.2.0/gems/web-console-2.1.3/lib/web_console/templates/index.html.erb (156.5ms)
#events is hash you have to iterate like
<% #events.each do |event| %>
<div>
<%= event[0] %><span class="badge"><%= event[1].count %></span>
</div>
<% end %>
In cases like this, simple debug printing will reveal the problem. Is name not defined on #events when you think it should be? Are you sure that #events is what you think it is?
Add p #events line to your controller, retry the request and read the log. A piece of advice for the future. :)
The problem starts here:
#events = #app.events.group_by(&:name)
I'm pretty sure that output of group_by is a hash, where keys are different names and values are arrays of events which all have the same name. (depends on what exactly the implementation of group_by is, of course)
<% #events.each do |event| %>
event here is not an instance of Event class, but a two element array, [name, [event1, event2, ...]]. You should iterate this nested array to get real events, which do have the method you want.
<% #events.each do |name, events| %>
<%= name %> <%= events.length %>
Related
I wanted to display my time variables to see when pass has started and when will it end but don't know how and couldn't find solution.
I tried something very simple but it doesn't work:
show.html.erb
<h1><%= #pass.name %></h1>
<p><%= #pass.valid_from %></p>
<p><%= #pass.valid_until %></p>
create_passes.rb migration
class CreatePasses < ActiveRecord::Migration[7.0]
def change
create_table :passes do |t|
t.time :valid_from
t.time :valid_until
t.boolean :is_time_limited
t.integer :entries_left
t.string :name
t.timestamps
end
end
end
passes_controller.rb
class PassesController < ApplicationController
def index
#passes = Pass.all
end
def show
#pass = Pass.find(params[:id])
end
def new
#pass = Pass.new
end
def create
#pass = Pass.new(pass_params)
if #pass.save
redirect_to #pass
else
render :new, status: :unprocessable_entity
end
end
def edit
#pass = Pass.find(params[:id])
end
def update
#pass = Pass.find(params[:id])
if #pass.update(pass_params)
redirect_to #pass
else
render :edit, status: :unprocessable_entity
end
end
def destroy
#pass = Pass.find(params[:id])
#pass.destroy
redirect_to root_path, status: :see_other
end
private
def pass_params
params.require(:pass).permit(:name, :is_time_limited, :valid_from, :valid_until, :entries_left)
end
end
new/edit pass form view
<%= form_with model: #pass do |form| %>
<div>
<%= form.label :name %><br>
<%= form.text_field :name %>
<% #pass.errors.full_messages_for(:name).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<div>
<%= form.label :valid_from %><br>
<%= form.date_field :valid_from %>
<% #pass.errors.full_messages_for(:name).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<div>
<%= form.label :valid_until %><br>
<%= form.date_field :valid_until %>
<% #pass.errors.full_messages_for(:name).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
rails server log
Started GET "/passes/2" for ::1 at 2022-08-10 18:18:18 +0200
Processing by PassesController#show as HTML
Parameters: {"id"=>"2"}
(0.1ms) SELECT sqlite_version(*)
↳ app/controllers/passes_controller.rb:7:in `show'
Pass Load (0.2ms) SELECT "passes".* FROM "passes" WHERE "passes"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
↳ app/controllers/passes_controller.rb:7:in `show'
Rendering layout layouts/application.html.erb
Rendering passes/show.html.erb within layouts/application
Rendered layouts/_navbar.html.erb (Duration: 1.0ms | Allocations: 724)
Rendered passes/show.html.erb within layouts/application (Duration: 2.8ms | Allocations: 1670)
Rendered layout layouts/application.html.erb (Duration: 6.9ms | Allocations: 4039)
Completed 200 OK in 31ms (Views: 7.5ms | ActiveRecord: 0.5ms | Allocations: 5333)
Also, is it better to use time or datatime type for dates and time?
Ok I believe I know why you are not getting any values.
You setup your DB to use a time field
t.time :valid_from
t.time :valid_until
But you are using a date_field in the view:
form.date_field :valid_from
You need to change this to:
form.time_field :valid_from
The difference between time or datetime is datetime includes a DATE and a TIME, where TIME ONLY has a time so it depends on what your use case is. You can also use just a date and then it would be
form.date_field :valid_from
If you need dates you will need to change your model and DB to use either t.date or t.datetime. If you don't have a lot of information in your DB you can do a rails db:rollback and modify your migration file would be the quickest and easiest way to fix it. IF you DO have data you will have to create a new migration to change the fields.
I'm Working in OneMonth Rails, I mistakenly deleted a user pin with an id of 6 inside of the console. Now I'm unable to create a new pin on local host. How can I fix the "SystemStackError in PinsController#index" error that I'm receiving?
index.html.erb:
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">
<h1>Listing Pins</h1>
<table>
<thead>
<tr>
<th>Image</th>
<th>Description</th>
<th>User</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #pins.each do |pin| %>
<tr>
<td><%= image_tag pin.image.url(:medium) %></td>
<td><%= pin.description %></td>
<td><%= pin.user.email if pin.user %></td>
<td><%= link_to 'Show', pin %></td>
<% if pin.user == current_user %>
<td><%= link_to 'Edit', edit_pin_path(pin) %></td>
<td><%= link_to 'Destroy', pin, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<br>
<% if user_signed_in? %>
<%= link_to 'New Pin', new_pin_path %>
<% end %>
Here is the code that I've written in the new action within my pins_controller.rb file.
def new
#pin = current_user.pins.build
end
Here is the server log:
Started GET "/pins" for ::1 at 2016-04-25 14:49:20 -0500
Processing by PinsController#index as HTML
[1m[36mPin Load (0.0ms)[0m [1mSELECT "pins".* FROM "pins"[0m
Rendered pins/index.html.erb within layouts/application (4.0ms)
Completed 500 Internal Server Error in 17ms (ActiveRecord: 0.0ms)
SystemStackError (stack level too deep):
actionpack (4.2.6) lib/action_dispatch/middleware/reloader.rb:79
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_source.erb (1.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (2.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (79.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/web-console-2.3.0/lib/web_console/templates/_markup.html.erb (1.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/web-console-2.3.0/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (0.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/web-console-2.3.0/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (1.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/web-console-2.3.0/lib/web_console/templates/style.css.erb within layouts/inlined_string (1.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/web-console-2.3.0/lib/web_console/templates/console.js.erb within layouts/javascript (84.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/web-console-2.3.0/lib/web_console/templates/main.js.erb within layouts/javascript (1.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/web-console-2.3.0/lib/web_console/templates/error_page.js.erb within layouts/javascript (1.0ms)
Rendered c:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/web-console-2.3.0/lib/web_console/templates/index.html.erb (173.0ms)
Here is an image of the error I'm receiving from your last comment
Below is my pins_controller.rb file:
class PinsController < ApplicationController
before_action :set_pin, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#pins = Pin.all
end
def show
end
def new
#pin = current_user.pins.build
end
def edit
end
def create
#pin = current_user.pins.build(pin_params)
if #pin.save
redirect_to #pin, notice: 'Pin was successfully created.'
else
render :new
end
end
def update
if #pin.update(pin_params)
redirect_to #pin, notice: 'Pin was successfully updated.'
else
render :'edit'
end
end
def destroy
#pin.destroy
redirect_to pins_url
end
private
# Use callbacks to share common setup or constraints between actions.
def set_pin
#pin = Pin.find(id: params[:id])
end
def current_user
#pins = current_user.pins.find_by(params[:id])
redirect_to pins_path, notice: "Not authorized to edit this pin" if #pin.nil?
end
# Never trust parameters from the scary internet, only allow the white list through.
def pin_params
params.require(:pin).permit(:description, :image)
end
end
Update your new method, Its supposed to be like this.
def new
#pin = Pin.new
end
def create
#pin = current_user.pins.build(YOUR PARAMS HERE)
end
I'm working on a small demo app to help myself understand how to implement cascading selects on Rails 4, but I've run into an interesting problem:
When I fill out a form and submit it to the database, the parameters seem to be passed, but the values are not being saved in the database because the SQL skips the field names and values, as demonstrated in this snippet from the console:
Started POST "/prop_sub_types" for ::1 at 2015-01-23 18:54:05 -0800
Processing by PropSubTypesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"7mGqF/MR+IKrKKdAKBYBI/E7pl7PCJasHDLN5T1/ohF/qEuXyhwsm8d87xDvfmcxk590hp/2XuenQBDaGhI+IA==", "prop_sub_type"=>{"name"=>"sub foo", "prop_type_id"=>"1"}, "commit"=>"Create Prop sub type"}
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "prop_sub_types" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2015-01-24 02:54:05.218673"], ["updated_at", "2015-01-24 02:54:05.218673"]]
(2.2ms) commit transaction
Redirected to http://localhost:3000/prop_sub_types/1
Completed 302 Found in 7ms (ActiveRecord: 2.6ms)
This is the relevant bit of schema.rb that demonstrates that the columns are there:
create_table "prop_sub_types", force: :cascade do |t|
t.string "name"
t.integer "prop_type_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Model:
class PropSubType < ActiveRecord::Base
attr_accessor :name, :prop_type_id
belongs_to :prop_type
has_many :appraisals
end
Controller (relevant portions for the sake of brevity -- I can post more if needed):
def create
#prop_sub_type = PropSubType.new(prop_sub_type_params)
respond_to do |format|
if #prop_sub_type.save
format.html { redirect_to #prop_sub_type, notice: 'Prop sub type was successfully created.' }
format.json { render :show, status: :created, location: #prop_sub_type }
else
format.html { render :new }
format.json { render json: #prop_sub_type.errors, status: :unprocessable_entity }
end
end
end
...
private
# Use callbacks to share common setup or constraints between actions.
def set_prop_sub_type
#prop_sub_type = PropSubType.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def prop_sub_type_params
params.require(:prop_sub_type).permit(:name, :prop_type_id)
end
app/views/prop_sub_types/_form.html.erb:
<%= form_for(#prop_sub_type) do |f| %>
<% if #prop_sub_type.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#prop_sub_type.errors.count, "error") %> prohibited this prop_sub_type from being saved:</h2>
<ul>
<% #prop_sub_type.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :prop_type_id %><br>
<%= f.number_field :prop_type_id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I'm adapting some Rails 3 code, so I thought I messed up the strong parameters portion, but the code actually looks correct to me and compares well with an unrelated, but working Rails 4 application.
What did I do wrong to make the INSERT ignore my parameters?
I believe it is because of your attr_accessor :name, :prop_type_id in model. Those accessors definitely are redundant and override the right ones: all fields for the DB table's fields are created as a part of initializing AR:Base class
Everything doesn't seem to be too hard but I've spent hours yet still can't get it working.
If I do Category.create(:name => "foo") in the rails console, a new category with its name gets created beautifully.
(0.2ms) begin transaction
SQL (0.3ms) INSERT INTO "categories" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", "2014-09-16 15:40:01.218700"], ["name", "foo"], ["updated_at", "2014-09-16 15:40:01.218700"]]
(14.5ms) commit transaction
=> #<Category id: 38, created_at: "2014-09-16 15:40:01", updated_at: "2014-09-16 15:40:01", name: "foo">
However, if I do it on the pages something goes wrong. My Category model has only one attribute which is "name", and I want all of them to be listed on my category index page.
<% #categories.each do |category| %>
<ul>
<li>
<b><%= category.name %></b><br />
<% category.products.each do |product| %>
<%= product.title %><br />
<% end %>
</li>
</ul>
<% end %>
<%= link_to "Create new category", categories_new_path %>
If I create a new category with its name in the console, it appears on the page with its name with no problem. But if I create it on the page, there's a category created with its name attribute being "nil". So please help me figure out where the problem is. I'm quite new to rails.
Here's my categories_controller.erb
class CategoriesController < ApplicationController
# load_and_authorize_resource
def new
#category = Category.new
end
def create
#category = Category.new(params[:name])
if #category.save
redirect_to categories_path
else
render 'new'
end
end
def index
#categories = Category.all
end
end
And here's my new.html.erb
<h1>New Category</h1>
<%= form_for(#category) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= link_to 'Back', categories_path %>
Here's what appears in the server after I hit the submit button.
Started POST "/categories?locale=en" for 127.0.0.1 at 2014-09-17 00:02:42 +0800
Processing by CategoriesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ZdXcC/uEMA/jhGoGhYvp4lSHHfi/tmlm3CovJcYizJ0=", "category"=>{"name"=>"fwefewfw"}, "commit"=>"Create Category", "locale"=>"en"}
(0.1ms) begin transaction
SQL (0.2ms) INSERT INTO "categories" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2014-09-16 16:02:42.806041"], ["updated_at", "2014-09-16 16:02:42.806041"]]
(21.2ms) commit transaction
Note that there's no "name" being inserted in the sql statement.
I sense I missed something that is very basic. Well forgive me for being a newbie and thank you for the help!!
Looking at your tags, i think you are using rails 4 so you need to permit your attributes first. You can do it by this:
class CategoriesController < ApplicationController
# load_and_authorize_resource
def create
#category = Category.new(category_params)
if #category.save
redirect_to categories_path
else
render 'new'
end
end
private
def category_params
params.require(:category).permit(:name)
end
end
For details checkout Strong Parameters in Rails
It should be:
#category = Category.new(params[:category])
If you're on Rails 4, you should use the strong params and add the following method to your controller:
def category_params
params.require(:category).permit(:name)
end
And then change the Category.new line to:
#category = Category.new(category_params)
That's the new "safe" way to accept user-generated data in Rails models, and works really well once you get used to it.
I'm trying to render a form with AJAX. The non-ajax version works fine, but the ajaxified version doesn't. The link to it is in the index.html.erb. The Webrick server shows:
Started GET "/categories/3/new_sub" for 127.0.0.1 at 2012-11-19 17:19:27 -0500
Processing by CategoriesController#new_sub as JS
Parameters: {"id"=>"3"}
Category Load (0.1ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" = ? LIMIT 1 [["id", "3"]]
Rendered categories/_form.html.erb (1.8ms)
Rendered categories/new_sub.js.erb (3.6ms)
Completed 200 OK in 8ms (Views: 6.3ms | ActiveRecord: 0.1ms)
Here's my Category controller:
# GET /categories
# GET /categories.json
def index
#categories = Category.roots
respond_to do |format|
format.html # index.html.erb
format.json { render json: #categories }
end
end
# GET /categories/1/new_sub.html
# GET /categories/1/new_sub.js
def new_sub
#parent = Category.find(params[:id])
#category = Category.new
respond_to do |format|
format.html
format.js
end
end
index.html.erb:
<h1>Listing categories</h1>
<%= recurse_categories(#categories) %>
<br />
<%= link_to 'New Category', new_category_path %>
recurse_categories helper:
def recurse_categories(cats)
s = "<ul>"
cats.each do |cat|
s << "<li id=\"#{cat.id}\">#{link_to cat.name, new_sub_category_path(cat), remote: true}</li>"
if cat.has_children?
s << recurse_categories(cat.children)
end
end
s << "</ul>"
s.html_safe
end
new_sub.js.erb:
$('ul').after(<%= render partial: "form", locals: { parent: #parent, category: #category } %>);
_form.html.erb:
<%= form_for(category) do |f| %>
<div class="field">
<%= f.text_field :name %>
<%= f.hidden_field :ancestry, value: "#{parent.ancestry + '/' + parent.id.to_s}" %>
<%= f.submit "Create subcategory" %>
</div>
<% end %>
Your "ul" tag is under category error's condition block. Are you sure you want to append your response in "error_explanation" div.
You can have an span tag and use it in new_sub.js.erb
<div class="field">
<span id="subcat"/>
<%= f.text_field :name %>
<%= f.hidden_field :ancestry, value: "#{parent.ancestry + '/' + parent.id.to_s}" %>
<%= f.submit "Create subcategory" %>
Fixed it! I just forgot quotation marks around the jquery selector and parameter, DUH!