I think my error is kind of silly, but it's keeping me stuck. I'm following the Agile Web Development with Rails 4 and developing the app Depot from it. I'm getting a
undefined method `add_product' for #<Cart:0x007f2ee4cfb8f8>
error. My code is as follows,
class LineItemsController < ApplicationController
def create
find_cart
product = Product.find(params[:product_id])
byebug
#line_item = #cart.add_product(product.id) // line with error
#line_item.product = product
respond_to do |format|
if #line_item.save
format.html {redirect_to #line_item.cart,
notice: 'Line Item was succesfully created'}
format.json {render json: #line_item,
status: :created, location: #line_item}
else
format.html {render action: "new"}
format.json {render json: #line_item.errors,
status: "Unprocessable Entry"}
end
end
end
end
Cart.rb
class Cart < ActiveRecord::Base
has_many :line_items, dependent: :destroy
def add_products(product_id)
current_item = line_items.find_by_product_id(product_id)
if current_item
current_item.qunatity += 1
else
current_item = line_items.build(product_id: product_id)
end
current_item
end
end
Also, I want to know, how can a method from different model be directly called into a separate controller ?
The object cart has value, I have debugged to make sure, as well as the error line also has the object present.
Thanks for your help.
I found the mistake, it was a typo I made in Cart.rb. I had named the method add_product's' and was calling add_product in the controller.
Related
I have a controller​ action which requires to find data from existing database. I am still learning rails and recently came to know about active record queries.
But I am not sure how to use it to fetch record from database in a controller action.
Can anybody please explain this with some example?
Thanks in advance
I found the answer. We can use active record queries to fetch the record from the database in the controller. Example is as follow:
Consider a database 'Dress' which has color attribute. Now I want to fetch all the 'dresses' which have orange color. So the query will be as:
#dresses = Dress.where(color: 'orange')
This will fetch all the record of dresses which have color = orange.
Yes you can used active record query inside controller. But better to put active record query logic inside model only. Because rails follow MVC Architecture
MVC stands for Model, View and Controller. MVC separates application into three components - Model, View and Controller.
Model: Model represents shape of the data and business logic. It maintains the data of the application. Model objects retrieve and store model state in a database. Model is a data and business logic.
View: View is a user interface. View display data using model to the user and also enables them to modify the data.
Controller: Controller handles the user request. Typically, user interact with View, which in-turn raises appropriate URL request, this request will be handled by a controller. The controller renders the appropriate view with the model data as a response.
Example:-
class RoomsController < ApplicationController
before_action :set_room, only: [:show, :edit, :update, :destroy]
# GET /rooms
# GET /rooms.json
def index
#rooms = Room.all
end
# GET /rooms/1
# GET /rooms/1.json
def show
end
# GET /rooms/new
def new
#room = Room.new
end
# GET /rooms/1/edit
def edit
end
# POST /rooms
# POST /rooms.json
def create
#room = Room.new(room_params)
respond_to do |format|
if #room.save
format.html { redirect_to #room, notice: 'Room was successfully created.' }
format.json { render :show, status: :created, location: #room }
else
format.html { render :new }
format.json { render json: #room.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /rooms/1
# PATCH/PUT /rooms/1.json
def update
respond_to do |format|
if #room.update(room_params)
format.html { redirect_to #room, notice: 'Room was successfully updated.' }
format.json { render :show, status: :ok, location: #room }
else
format.html { render :edit }
format.json { render json: #room.errors, status: :unprocessable_entity }
end
end
end
# DELETE /rooms/1
# DELETE /rooms/1.json
def destroy
#room.destroy
respond_to do |format|
format.html { redirect_to rooms_url, notice: 'Room was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_room
#room = Room.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def room_params
params.require(:room).permit(:name, :type, :user_id)
end
end
What did I miss?
ERROR: undefined local variable or method `feedback' for #<#<Class:0x007f66dc8dca30>:0x007f66dc8cee80>
Migration:
class CreateFeedbacks < ActiveRecord::Migration
def change
create_table :feedbacks do |t|
t.references :user
t.text :body
t.timestamps
end
end
end
Model:
class Feedback < ActiveRecord::Base
attr_accessible :body, :user
belongs_to :user
end
Controller:
class FeedbacksController < ApplicationController
before_action :authenticate_user!
def index
#feedback = Feedback.all
end
def new
#feedback = Feedback.new
end
def create
#user = User.find(params[:user])
#feedback = #user.feedbacks.create(params[:feedback])
respond_to do |format|
if #feedback.save
format.html { redirect_to #user, notice 'Comment was successfully created.' }
format.json { render json: #feedback, status: :created, location: #feedback }
else
format.html { render action: "new" }
format.json { render json: #feedback.errors, status: :unprocessable_entily }
end
end
end
User model:
has_many :feedback
Routes:
resources :feedbacks
resources :users do
resources :feedbacks
end
Firstly, it helps a lot to style your question and code correctly as well as mark your files (routes.rb, controllers, models correctly). Else it would be very difficult for readers to understand your question and spot issues with your code. You can refer to https://meta.stackoverflow.com/editing-help for the styleguide/ markdown.
Secondly, it looks like your routes.rb are incorrect - but again, this could be due to your formatting. Based on your question, it looks like your routes are:
resources :feedbacks
resources :users do
resources :feedbacks
end
end
When it should be:
resources: users do
resources: feedbacks
end
Thirdly, your seem to have a typo in your model (feedback instead of feedbacks. That is:
class User < ActiveRecord::Base
has_many :feedbacks
end
class Feedback < ActiveRecord::Base
belongs_to :user
end
Lastly, do add specifics and what exactly you ran that caused the error. E.g. did you run something in console, what page did you load?
Problem solved thanks to #skipchris (https://twitter.com/skipchris) Using debugger we found a spelling mistake. The error report didn't make much sense but i learned plenty investigating the problem!
I've spent last night and this morning trying to find a solution but i'm new to rails. From what i've read so far it think the problem is to do with association. I created a Pin without a User (association error?) and so there is an error with routing i.e something to do with Devise?
When i try to create a new Pin i get this error in browser on my local server-
NoMethodError in PinsController#create
pp/controllers/pins_controller.rb:48:in block in create'
app/controllers/pins_controller.rb:47:increate'
pins_controller.rb
def create
#pin = current_user.pins.new(params[:pin])
respond_to do |format|
if #pin.save
format.html { redirect_to #pin, notice: 'Pin was successfully created.' }
format.json { render json: #pin, status: :created, location: #pin }
else
format.html { render action: "new" }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
User Model (user.rb)
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, #:recoverable,
:rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation,
:remember_me, :name
has_many :pins
end
Yeah, I would definitely make a user model since you are trying to access current_user.pins in the methods. also do you have
resources :pins
or something similar in your routes?
I'm trying to learn Rails by creating a very simple application which just creates a website where someone can create a list of authors and books with an association that the book is written by an author. I was hoping this would be simple and DRY, but I've been having an unexpected amount of trouble with it.
First looking at my models, I've set up the association and made every data point required (author.name, book.title, and book.author). I do not want to add :author or :author_id to the attr_accessible lists because I want to use the appropriate Rails conventions.
app/models/author.rb:
class Author < ActiveRecord::Base
attr_accessible :name
validates_presence_of :name
has_many :books
end
app/models/book.rb:
class Book < ActiveRecord::Base
attr_accessible :title
validates_presence_of :title
belongs_to :author
validates_associated :author
end
The books controller and view I think is exactly from the scaffolding and very uninteresting. What is interesting is the books controller. Looking at the new method, all I did was add a collector which gets the array of author names with ids to pass to the view. (Honestly, I think I would prefer to not pass the id at all.)
app/controllers/books_controller.rb
# GET /books/new
# GET /books/new.json
def new
#book = Book.new
#authors = Author.all.collect {|a| [a.name, a.id]}
respond_to do |format|
format.html # new.html.erb
format.json { render json: #book }
end
end
Now over to the views, I used the default new.html.haml, but made changes to _form.html.haml. I added a select field using the values in #authors.
app/views/books/_form.html.haml
= form_for #book do |f|
- if #book.errors.any?
#error_explanation
%h2= "#{pluralize(#book.errors.count, "error")} prohibited this book from being saved:"
%ul
- #book.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :name
= f.text_field :name
.field
= f.label :author
= f.select(:author, #authors, {:include_blank => ""})
.actions
= f.submit 'Save'
Lastly, back to my controller for the create method. I try to save the basic parameters and create an author association from the selected author.
app/controllers/books_controller.rb
# POST /books
# POST /books.json
def create
#book = Book.new(params[:book])
#book.author = Author.find_by_id(params[:author])
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'Book was successfully created.' }
format.json { render json: #book, status: :created, location: #book }
else
format.html { render action: "new" }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
When I click 'Save' I get the following error:
Can't mass-assign protected attributes: author
I understand that this is because the value I selected was put in params[:book] instead of params[:author]. So I have two questions.
1) How do I fix my select statement to have it send in params[:author] instead of params[:book]?
2) Is there an even better way to do this that completely hides the id association?
"Can't mass-assign protected attributes: author" means that your attribute isn't listed as attr_accessible in your model
I think I've mostly figured it out, and as I suspected, I didn't need to change my model code at all.
I changed my controllers new method definition of #authors to only return author names with the following:
#authors = Author.pluck(:name)
This accomplished my goal of hiding the id though it's probably a tad slower when I need to search by name instead of id in the controller create method (below).
Next, I fixed my views to set params[:author] instead of params[:book][:author].
= label :author, :name, 'Author'
= select_tag(:author, options_for_select(#authors), {:include_blank => ""})
Finally, I changed the new methods creation of the #book:
#book = Author.find_by_name(params[:author]).books.create(params[:book])
I'm fairly happy with this. The only thing I don't really like is that the label creates an "author_name" label instead of simply "author".
I made the following models:
class Request < ActiveRecord::Base
end
class UrgentRequest < Request
has_one:note
end
class Note < ActiveRecord::Base
attr_accessible :request_id,....
belongs_to :urgent_request, :foreign_key=>'request_id', :class_name=>'Request'
end
In my controller I've set up an action to create an UrgentRequest object:
def new_scheduled_request
#request = UrgentRequest.new
#request.build_note #<-- getting error here
respond_to do |format|
format.html # new.html.erb
format.json { render json: #request }
end
end
I'm getting the following error:
ActiveRecord::UnknownAttributeError in RequestsController#new_urgent_request
unknown attribute: urgent_request_id
The line number is where I'm invoking the build_note call. The form on the page is supposed to be a nested form. What's going on here and how can I fix it?
Uh never mind I found out the issue. Apparently I had to explicitly mention in the UrgentRequests model in the has_one:note association the foreign key and class name parameters. Works fine now!