when I attempt to run my code, I got the error above.
I try to transform the url products with FriendlyId gem . It works but when I try to see my product, I got this error :
NoMethodError in Products#show
undefined method `name' for nil:NilClass
Request
Parameters:
{"name"=>"tablette-chocolat-guanaja"}
Here's my models/product.rb :
has_many :order_items, dependent: :destroy
extend FriendlyId
friendly_id :name, use: :slugged
before_save :update_slug
def update_slug
self.slug = name.parameterize
end
def to_param
slug
end
my products_controller.rb :
before_action :set_product, only:[:show]
def show
#order_item = current_order.order_items.new
end
private
def set_product
#product = Product.find_by_slug(params[:id])
end
my view/show.html.erb :
<%= render "product_show", product: #product, order_item: #order_item %>
and _product_show.html.erb :
<p ><%= product.name %></p>
<%= form_for order_item, remote: true do |f| %>
<%= f.number_field :quantity, value: order_item.quantity.to_i, class: "form-control", min: 1, max: 99 %>
<%= f.hidden_field :product_id, value: product.id %>
<p><%= currency_euro product.price %></p></br>
<p><%= image_tag product.image %></p>
<p><%= image_tag product.image_pres1 %></p>
# etc.
Any idea ?
EDIT
Here's the full error message :
Started GET "/products/tablette-chocolat-guanaja" for 127.0.0.1 at 2015-12-20 16:52:06 +0100
Processing by ProductsController#show as HTML
Parameters: {"name"=>"tablette-chocolat-guanaja"}
Product Load (0.4ms) SELECT `products`.* FROM `products` WHERE `products`.`active` = 1 AND `products`.`slug` IS NULL LIMIT 1
Rendered products/_product_show.html.erb (1.8ms)
Rendered products/show.html.erb within layouts/application (2.7ms)
Completed 500 Internal Server Error in 9ms (ActiveRecord: 0.4ms)
EDIT2
My fault, I added "resources :products, param: :name" in product's routes, sorry...
first you don't need to update manually slug, gem will do it for you just execute this code
Product.all.each(&:save)
also this
def set_product
#product = Product.find_by_slug(params[:id])
end
you can replace
def set_product
#product = Product.friendly.find(params[:id])
end
Hope it helps
probably because the creation of this product was before install friendly_id. Did you try this?: Profile.find_each(&:save) to rails console to save slugs to your old products?
Related
Could you help me? I got an error Couldn't find User without an ID, I was thinking about make like a blog service, I wanted to implement nest attribute without accepts_nested_attributes_for, so I've been using
form object, but I couldn't send form object user's parameter,
controller
class BlogsController < ApplicationController
before_action :authenticate_user!
def index
#current = current_user
end
def new
#blogs = BlogForm.new
end
def create
#blogs = BlogForm.new(blog_params)
if #blogs.save
redirect_to user_blogs_path
else
end
end
def edit
end
def show
end
private
def blog_params
params.require(:blog_form).permit(:title , :content , :user_id)
end
end
form html
<%= form_with model: #blogs , url: user_blogs_path,local: true do |f| %>
<% f.label :title %>
<%= f.text_field :title %>
<% f.label :content %>
<%= f.text_area :content %>
<% f.label :user_id %>
<% f.hidden_field :user_id , value: current_user.id%>
<%= f.submit "create", class: "btn btn-primary" %>
<% end %>
blog_form
class BlogForm
include ActiveModel::Model
attr_accessor :title, :content, :user_id
def to_model
#user = User.find(user_id)
#blogs = #user.blogs.new(title: title , content: content , user_id: user_id)
end
def save
return false if invalid
to_model.save
end
end
blogs.rb
class Blog < ApplicationRecord
belongs_to :user
validates :title ,presence: true
validates :content ,presence: true
end
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :blogs
def email_required?
false
end
def email_changed?
false
end
def will_save_change_to_email?
false
end
end
log
ActionView::Template::Error (Couldn't find User without an ID):
1: <%= form_with model: #blogs , url: user_blogs_path,local: true do |f| %>
2:
3: <% f.label :title %>
4: <%= f.text_field :title %>
app/forms/blog_form.rb:6:in `to_model'
app/views/blogs/shared/_form.html.erb:1
app/views/blogs/new.html.erb:4
Started GET "/users/1/blogs/new" for 127.0.0.1 at 2020-01-19 16:29:03 +0900
Processing by BlogsController#new as HTML
Parameters: {"user_id"=>"1"}
Rendering blogs/new.html.erb within layouts/application
Rendered blogs/shared/_form.html.erb (Duration: 3.0ms | Allocations: 1143)
Rendered blogs/new.html.erb within layouts/application (Duration: 10.5ms | Allocations: 1228)
Completed 500 Internal Server Error in 16ms (ActiveRecord: 0.0ms | Allocations: 1715)
ActionView::Template::Error (Couldn't find User without an ID):
1: <%= form_with model: #blogs , url: user_blogs_path,local: true do |f| %>
2:
3: <% f.label :title %>
4: <%= f.text_field :title %>
app/forms/blog_form.rb:6:in `to_model'
app/views/blogs/shared/_form.html.erb:1
app/views/blogs/new.html.erb:4
after, I tried coreyward's way, but I couldn't,
rocessing by BlogsController#new as HTML
Parameters: {"user_id"=>"1"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
Rendering blogs/new.html.erb within layouts/application
Rendered blogs/shared/_form.html.erb (Duration: 6.9ms | Allocations: 1082)
Rendered blogs/new.html.erb within layouts/application (Duration: 9.4ms | Allocations: 1166)
Completed 500 Internal Server Error in 114ms (ActiveRecord: 2.3ms | Allocations: 11134)
ActionView::Template::Error (Couldn't find User without an ID):
1: <%= form_with model: #blogs , url: user_blogs_path(#user),local: true do |f| %>
2:
3: <% f.label :title %>
4: <%= f.text_field :title %>
app/forms/blog_form.rb:6:in `to_model'
app/views/blogs/shared/_form.html.erb:1
app/views/blogs/new.html.erb:4
The route helper user_blogs_path probably expects an argument for the user. Something like this:
user_blogs_path(#user)
Which goes in this line:
<%= form_with model: #blogs , url: user_blogs_path(#user),local: true do |f| %>
This is just a really strange and awkward way of doing a nested resource. This really has very little to do with nested attributes which used when you need to create or update two (or more) associated records in the same request.
# routes.rb
resources :users do
resources :blogs,
only: [:new, :show, :create],
shallow: true
end
class BlogsController
before_action :set_user, only: [:new, :create]
# GET /blogs/1
def show
#blog = Blog.find(params[:id])
end
# GET /users/1/blogs/new
def new
#blogs = #user.blog.new
end
# POST /users/1/blogs
def create
#blogs = #user.blog.new(blog_params)
if #blog.save
redirect_to #blog
else
render :new
end
end
private
def set_user
#user = User.find(params[:user_id])
end
def blog_params
params.require(:blog).permit(:title, :content)
end
end
<%= form_with model: [#user, #blog], local: true do |f| %>
<% f.label :title %>
<%= f.text_field :title %>
<% f.label :content %>
<%= f.text_area :content %>
<%= f.submit "create", class: "btn btn-primary" %>
<% end %>
I have a Document that has_many Section, and each section has_one Comment. I want to be able to create both sections and comments in the Document show view, but I'm having trouble getting comments to go through.
Here's the relevant code with the closest I've got:
class CommentsController < ApplicationController
def create
#section = Section.find(params[:id])
#section.comment.create(comment_params)
end
private
def comment_params
params.require(:comment).permit(:body)
end
end
The routing:
resources :documents, shallow: true do
resources :sections do
resources :comments
end
end
And the view with the form:
# app/views/documents/show.html.erb
<% #document.sections.each do |section| %>
<%= section.body %>
<% if section.comment %>
<p>
<%= section.comment %>
</p>
<% else %>
<%= form_with url: section_comments_path(section.id), scope: 'comment' do |form| %>
<%= form.text_field :body, placeholder: "Comment" %>
<%= form.submit %>
<% end %>
<% end %>
<% end %>
It all seems to check out for me, but when I try to post a comment, here's what I get:
Started POST "/sections/51/comments" for ::1 at 2019-05-24 23:29:06 +0000
Processing by CommentsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>[...], "comment"=>{"body"=>"asdas"}, "commit"=>"Save comment", "section_id"=>"51"}
Section Load (0.5ms) SELECT "sections".* FROM "sections" WHERE "sections"."id" = ? LIMIT ? [["id", 51], ["LIMIT", 1]]
comment Load (0.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."section_id" = ? LIMIT ? [["section_id", 51], ["LIMIT", 1]]
Completed 500 Internal Server Error in 11ms (ActiveRecord: 0.9ms)
NoMethodError (undefined method `create' for nil:NilClass):
app/controllers/comments_controller.rb:4:in `create'
Any ideas?
A has_one relationship returns the object itself. Therefore, #section.comment.create(comment_params) will not work because #section.comment is nil. Instead, try something like...
def create
#section = Section.find(params[:section_id])
#comment = Comment.create(comment_params)
#section.comment = #comment
...
end
Or, as stated in the Rails Guides...
When initializing a new has_one or belongs_to association you must use
the build_ prefix to build the association, rather than the
association.build method that would be used for has_many or
has_and_belongs_to_many associations. To create one, use the create_
prefix.
Which would look like this
def create
#section = Section.find(params[:section_id])
#section.create_comment(comment_params)
...
end
You likely need to change:
#section.comment.create(comment_params)
to:
#section.comments.create(comment_params)
If that doesn't work, try:
#section.comment.create!(comment_params)
and see what the exception says
I'm tryint to save information but seems to be hard.
Here my controller /app/controllers/finance_management/voucher_controller.rb
class FinanceManagement::VoucherController < ActionController::Base
def new
#voucher = Voucher.new
end
def create
Voucher.create(params[:voucher])
end
def voucher_params
params.require(:voucher).permit(:voucher_num)
end
end
Here is my model /app/models/voucher.rb
class Voucher < ActiveRecord::Base
end
Here is my view /app/finance_management/voucher/new.html.erb
<%= form_for :obj_voucher, :url => { :controller => "finance_management/voucher", :action => "create" } do |f| %>
Number<%= f.text_field :voucher_num %>
<%= f.submit :submit %>
<% end %>
Here my routes.rb
Rails.application.routes.draw do
namespace :finance_management do
resources :voucher
end
match ':controller(/:action(/:id(.:format)))', via: [:get, :post]
end
Here my logs
Started POST "/finance_management/voucher" for 127.0.0.1 at 2016-01-17 21:00:39 -0500
Processing by FinanceManagement::VoucherController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"222222=", "voucher"=>{"voucher_num"=>"1111"}, "commit"=>"submit"}
(0.1ms) BEGIN
SQL (1.5ms) INSERT INTO `vouchers` (`created_at`, `updated_at`) VALUES ('2016-01-18 02:00:39', '2016-01-18 02:00:39')
Mysql2::Error: Field 'voucher_num' doesn't have a default value: INSERT INTO `vouchers` (`created_at`, `updated_at`) VALUES ('2016-01-18 02:00:39', '2016-01-18 02:00:39')
(0.2ms) ROLLBACK
Completed 500 Internal Server Error in 5ms (ActiveRecord: 1.8ms)
ActiveRecord::StatementInvalid (Mysql2::Error: Field 'voucher_num' doesn't have a default value: INSERT INTO `vouchers` (`created_at`, `updated_at`) VALUES ('2016-01-18 02:00:39', '2016-01-18 02:00:39')):
I tried several ways but cannot save information but got errors:
<%= form_for :user, :url => {:controller=>"finance_management/voucher",:action=>'create'} do |f|%>
<%= form_for #user, :url => {:controller=>"finance_management/voucher",:action=>'create'} do |f|%>
Also changed this:
def create
#voucher= Voucher.create(params[:voucher_params])
end
def voucher_params
params.require(:voucher).permit(:voucher_num)
end
The field is not saving
Mysql2::Error: Field 'voucher_num' doesn't have a default value: INSERT INTO `vouchers` (`created_at`, `updated_at`) VALUES ('2016-01-18 02:00:39', '2016-01-18 02:00:39')
Try:
def create
Voucher.create(voucher_params)
end
ActionController params can't be used in ActiveModel mass assignment directly, you have to use strong parameters instead.
For benefit of the doubt, here's how the code should be structured:
#config/routes.rb
namespace :finance_management do
resources :vouchers
end
#app/controllers/financial_management/vouchers_controller.rb
class FinanceManagement::VouchersController < ActionController::Base
def new
#voucher = Voucher.new
end
def create
#voucher = Voucher.new voucher_params
#voucher.save
end
private
def voucher_params
params.require(:voucher).permit(:voucher_num)
end
end
#app/views/finance_management/vouchers/new.html.erb
<%= form_for [:financial_management, #voucher] do |f| %>
<%= f.text_field :voucher_num, placeholder: "Number" %>
<%= f.submit %>
<% end %>
I don't know why this is happening. Can anyone explain why I am getting wrong number of arguments for this search? I am just doing a search where you have two fields for the search subject and zip. But when i run the search I get the wrong number of argument error.
Model:
class Profile < ActiveRecord::Base
has_and_belongs_to_many :subjects
belongs_to :user
geocoded_by :zip
after_validation :geocode, :if => :zip_changed?
searchable do
text :subject_search
latlon(:location) { Sunspot::Util::Coordinates.new(self.latitude, self.longitude) }
string :search_near
end
def search_near
self.zip
end
def subject_search
subjects.map { |subject| subject.title }
end
end
Controller:
def index
#search = Profile.search do
fulltext params[:subject_search]
with(:location).in_radius(*Geocoder.coordinates(params[:search_near]), 10)
if params[:search_near].present?
end
#profiles = #search.results
end
View:
<%= form_tag profiles_path, method: :get do %>
<p>Enter Zip:</p>
<%= text_field_tag :search_near, params[:search_near] %>
<p>Enter Subject:</p>
<%= text_field_tag :subject_search, params[:subject_search] %>
<%= submit_tag "Search", name: nil %>
</p>
<% end %>
Started GET "/profiles?utf8=%E2%9C%93&search_near=33029&subject_search=English+1" for ::1 at 2015-06-26 15:53:28 -0400
Processing by ProfilesController#index as HTML
Parameters: {"utf8"=>"✓", "search_near"=>"33029", "subject_search"=>"English 1"}
Geocoding API not responding fast enough (use Geocoder.configure(:timeout => ...) to set limit).
Completed 500 Internal Server Error in 3010ms
ArgumentError (wrong number of arguments (1 for 3..4)):
app/controllers/profiles_controller.rb:8:in block in index'
app/controllers/profiles_controller.rb:6:inindex'
Rendered /Users/mikinad/.rvm/gems/ruby-2.1.1/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_source.erb (9.1ms)
Rendered /Users/mikinad/.rvm/gems/ruby-2.1.1/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_trace.html.erb (3.5ms)
Rendered /Users/mikinad/.rvm/gems/ruby-2.1.1/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_request_and_response.html.erb (1.3ms)
Rendered /Users/mikinad/.rvm/gems/ruby-2.1.1/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_web_console.html.erb (1.4ms)
Rendered /Users/mikinad/.rvm/gems/ruby-2.1.1/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/diagnostics.html.erb within rescues/layout (60.8ms)
I'm a long time lurker who's google-fu is failing him today. I've been learning to use Rails using a video series that was created before Rails 4 came out. As such, the lectures use the attr_accessibly mass assignments. I've been attempting to convert this to working strong parameters, but am having an issue actually saving info to my PostgreSQL database.
Basically, I should go to localhost:3000/new, add a title, body, and category, then submit. This goes off without a hitch, but my /posts (which lists all posts) shows the title as /posts/(whatever row number it's on), does not display the text, and only shows a date-time stamp when clicking on the post (url). Also, my database is only storing a post/row number.
Note: I am aware of things like ActiveAdmin, but would prefer to learn how to make/save posts manually before using such modules.
Here is the post controller:
class PostsController < ApplicationController
def index
#posts = Post.all
end
def show
#post = Post.find(params[:id])
end
def new
#post = Post.new
#category = Category.all
end
def create
#post = Post.create(post_params)
if #post.save
redirect_to posts_path, :notice => "Your post has been saved"
else
render "new"
end
end
def edit
end
def update
end
def destroy
end
private
def post_params
params.require(:post).permit(:title, :body, :category_id, :author_id)
end
end
Here is the html form:
<h1>Add New Post</h1>
<%= form_for #post do |f| %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %><br />
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %><br />
</p>
<p>
<%= f.select :category_id, Category.all.collect {|x| [x.name, x.id]}, {:include_blank=> "Select One"}%><br />
</p>
<p>
<%= f.submit "Add Post" %>
</p>
<% end %>
And finally, the posts.rb file:
class Post < ActiveRecord::Base
# Deprecated
# attr_accessible :title, :body, :category_id, :author_id
belongs_to :category
accepts_nested_attributes_for :category
end
I am no Ruby expert, so my first thought is that the .save method requires additional arguments when using strong_parameters. Adding (post_params) to the save method didn't seem to have an effect, and I haven't been able to determine my issue using the Ruby documentation. I'd prefer to do this the "right" way, as opposed to just using the protected_attributes gem to use a deprecated (seemingly less secure) method.
Thanks in advance for any assistance you may be able to offer. When I get rich, I'll buy you a Ferrari*.
*May or may not be a Hot Wheels replica.
Eidt 2: Here is what the server throws out when attempting to POST to my database. It mentions a mass assignment error, but I thought I wasn't using them (strong params instead). Pardon my newbiness:
Started POST "/posts" for 127.0.0.1 at 2015-03-11 18:28:13 -0700
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"9Ybchogw5u+sYbZOFYZtbJbXBkWC5EuCIZNUmAKyAQI=", "post"=> {"title"=>"blahblahblah", "body"=>"blahblahblah", "category_id"=>"1"}, "commit"=>"Add Post"}
WARNING: Can't mass-assign protected attributes for Post: title, body, category_id
app/controllers/posts_controller.rb:18:in `create'
[1m[36m (0.0ms)[0m [1mBEGIN[0m
[1m[35mSQL (1.0ms)[0m INSERT INTO "posts" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2015-03-12 01:28:13.990971"], ["updated_at", "2015-03-12 01:28:13.990971"]]
[1m[36m (2.0ms)[0m [1mCOMMIT[0m
[1m[35m (0.0ms)[0m BEGIN
[1m[36m (0.0ms)[0m [1mCOMMIT[0m
Redirected to http://localhost:3000/posts
Completed 302 Found in 10ms (ActiveRecord: 3.0ms)
And the index view. This is a training exercise, so it's just text, no styling:
<h1>Blog Posts</h1>
<% #posts.each do |post| %>
<h3><%= link_to post.title, post %></h3>
<p><%= post.body %></p>
<% end %>
uncomment your request/permit line in post_params and actually add the param names into it
def post_params
params.require(:post).permit(:title, :body, :category_id, :author_id)
end
That is why you are getting no data in your posts - because you aren't getting any data out of params anymore.
If the permit/require line is causing a different bug for you - we will help you fix that, but commenting out the security measure is not the way to solve it.