I'm working through Agile Web Dev w/ Rails book (4th ed) and I'm totally stuck...
I'm running Rails 3.2.3 on Mac OSX.
Im on task D-3: Adding a Button.... it started with the test:functionals not working at the end of the chapter... it gave me an error saying:
Can't Mass assign protected attributes: product
I followed the advice given here: http://forums.pragprog.com/forums/148/topics/10565
and changed my line of code in the Line_Items_Controller to
#line_item = #cart.line_items.build
#line_item.product = product
Here is what my current Line_Items_Controller create method looks like:
# POST /line_items
def create
#cart = current_cart
product = Product.find(params[:product_id])
#line_item = #cart.line_items.build
#line_item.product = product
respond_to do |format|
if #line_item.save
format.html { redirect_to(#line_item.cart,
:notice => 'Line item was successfully created.') }
format.xml { render :xml => #line_item,
:status => :created, :location => #line_item }
else
format.html { render :action => "new" }
format.xml { render :xml => #line_item.errors,
:status => :unprocessable_entity }
end
end
end
Now I am getting this weird message:
NoMethodError in LineItemsController#create undefined method `product=' for <LineItem:0x000001024f7fb0>
Here is my LineItem model
class LineItem < ActiveRecord::Base
attr_accessible :cart_id, :product_id, :product
end
Im not really sure what to do at this point, since I'm a total Rails (& Ruby) newb.
Can anyone point me in the right direction?
Changing the original line of code
#line_item = #cart.line_items.build(product: product) to #line_item = #cart.line_items.build(:product_id => product.id) in line_items_controller.rb solved this problem for me.
In my case there is :product_id in LineItem attr_accessible:
attr_accessible :cart_id, :product_id
So i changed :product => product in build's attributes to :product_id => product.id and it works.
#line_item = #cart.line_items.build(:product_id => product.id)
if you want the example from the book to work exactly the way they typed it up, go to models/line_item.rb and add attr_accessible to look like this;
attr_accessible :cart_id, :product_id, :product
n'joy.
Your line item model doesn't have an ActiveRecord association for Product. I'm not sure what you're building but I assume you'll want:
#lineitem
belongs_to :produce
#product
has_many :line_items
You'll also need to add product_id to your line items table.
Related
I'm posting here because i can't find anyone with this error. I'm using Rails 4.0.2 and when i try to save my form (it uses a collection_check_box) it gives me this message:
NoMethodError (undefined method `name' for nil:NilClass):
app/controllers/projeto_controller.rb:34:in `block in create'
app/controllers/projeto_controller.rb:33:in `create'
I'm a little lost here because i don't have any attributes named name.
Here my controllers and models.
class Projeto < ActiveRecord::Base
belongs_to :usuario
has_many :projeto_temas
has_many :temas, through: :projeto_temas
accepts_nested_attributes_for :temas
validates_presence_of :titulo, :orgao_financiador, :periodo_inicio, :periodo_fim
end
class ProjetoController < ApplicationController
# GET /projeto/new
def new
#projeto = Projeto.new
render :layout => 'application_cadastro'
end
# POST /projeto
# POST /projeto.json
def create
#projeto = Projeto.new(projeto_params)
respond_to do |format|
if #projeto.save
format.html { redirect_to #projeto, notice: 'Projeto was successfully created.' }
format.json { render action: 'show', status: :created, location: #projeto }
else
format.html { render action: 'new' }
format.json { render json: #projeto.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /projeto/1
# PATCH/PUT /projeto/1.json
def update
respond_to do |format|
if #projeto.update(projeto_params)
format.html { redirect_to #projeto, notice: 'Projeto was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #projeto.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_projeto
#projeto = Projeto.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def projeto_params
params.require(:projeto).permit(:titulo, :usuario_id, :orgao_financiador, :periodo_inicio, :periodo_fim, :resumo, :temas_ids => [])
end
end
And the Temas model.
class Temas < ActiveRecord::Base
has_many :relacionamento_temas_pai, class_name: RelacaoTemas, foreign_key: :temas_pai_id
belongs_to :relacionamento_temas_filho, class_name: RelacaoTemas, foreign_key: :temas_filho_id
has_and_belongs_to_many :projeto
accepts_nested_attributes_for :relacionamento_temas_pai
validates :nome, presence: true
end
The part of the view with the ckeck_box
<div class="presquisadores-preview-action">
<div class="temas-projetos-checkbox">
<%= f.collection_check_boxes :temas_ids, Temas.all, :id, :nome %>
</div>
</div>
It has one attribute with the name nome which is portuguese for name, so it shouldn't affect anything.
Thanks in advance for the help, in really lost, and don't know what to do.
--EDIT
So... after a lot of research i didn't find the problem. Actually i was looking into some rails documentation and saw some issues with that version of the activerecord so i updated to rails 4.2.0 and the problem is now gone.
I still don't know what caused it, but now my form saves normally.
Thanks for all the help folks
This is an issue with Rails 4.0.2. I faced the same issue and when I updated to Rails 4.0.13 (the last in the 4.0.x series), the issue resolved itself.
From the github issues, I can only glean that this is because of some database bugs that Rails did not prepare for.
So I've been holding off putting a question on here because I don't want to bother the community with stupid questions, but I'm going to ask for help now anyway.
I'm quite new to Ruby on Rails, and as you've probably read from the title, I'm having trouble with my subform. More specifically, with assigning the parent object to a client object. I'm building a system for my work in where employees can register repairs (mobile phones) and keep track of them. I'm building the client object with #repair = Repair.new, which works fine, but when I try to set the Client with #repair = Client.new, the :client_id on the repair stays null.
Here's my repair.rb: (some fields are in Dutch, please ignore that)
class Repair < ActiveRecord::Base
attr_accessible :imei, :klantnaam, :telefoon, :intake, :branch_id, :id, :client_id
attr_accessible :merk, :type, :batterij, :lader, :headset, :batterijklep, :carkit, :schade_toestel, :schade_scherm, :bon, :datum_bon, :klacht, :prijsindicatie
belongs_to :branch
belongs_to :client
accepts_nested_attributes_for :client
end
client.rb:
class Client < ActiveRecord::Base
attr_accessible :email, :firstname, :lastname, :number, :phone, :postalcode
has_many :repairs
end
repairs_controller.rb: (I've left the irrelevant methods out, I was getting tired of the 4 spaces :P)
class RepairsController < ApplicationController
# GET /repairs/new
# GET /repairs/new.json
def new
#repair = Repair.new
#repair.client = Client.new
if request.remote_ip == "xx.xx.xx.xx"
#repair.branch = Branch.where(:name => "Xxxxxxx").first
end
#repair.intake = Time.now
respond_to do |format|
format.html # new.html.erb
format.json { render json: #repair }
end
end
# POST /repairs
# POST /repairs.json
def create
#repair = Repair.new(params[:repair])
respond_to do |format|
if #repair.save
format.html { redirect_to #repair, notice: 'Repair was successfully created.' }
format.json { render json: #repair, status: :created, location: #repair }
else
format.html { render action: "new" }
format.json { render json: #repair.errors, status: :unprocessable_entity }
end
end
end
end
And this is the JSON I get from /repair/new.json:
{"batterij":null,"batterijklep":null,"bon":null,"branch_id":null,"carkit":null,"client_id":null,"created_at":null,"datum_bon":null,"headset":null,"id":null,"imei":null,"intake":"2013-02-01T23:29:10Z","klacht":null,"klantnaam":null,"lader":null,"merk":null,"pickup":null,"prijsindicatie":null,"schade_scherm":null,"schade_toestel":null,"telefoon":null,"updated_at":null}
By the way, the branch assignment works flawlessly... (It's null now because I'm not on the IP I specified in the new method)
Please help me out... :-(
Robin
Solved it!!
The code above all works flawlessly, the problem was a <% instead of <%= in my view, which made my subform not show up. Duhh.
i'v been researching trying to find the answer for this, but am struggeling to work it out. i have a booking_no text_field which i want to be automatically set when a user make a new booking through booking/new. i would like it to be an autonumber which just counts up by 1 evertime starting with 100.
I know it is probably easiest to do this in the model but i'm not sure how.
my booking.rb:
(i havent set the validates yet)
class Booking < ActiveRecord::Base
attr_accessible :booking_no, :car_id, :date, :user_id
belongs_to :car
belongs_to :user
end
EDIT for comment:
#error ArgumentsError in booking_controller#create
wrong number of arguments (1 for 0)
my booking_controller#create
def create
#booking = Booking.new(params[:booking])
respond_to do |format|
if #booking.save
format.html { redirect_to #booking, :notice => 'Booking was successfully created.' }
format.json { render :json => #booking, :status => :created, :location => #booking }
else
format.html { render :action => "new" }
format.json { render :json => #booking.errors, :status => :unprocessable_entity }
end
end
end
It's probably best if you set the booking_no as auto-increment field in the Database table itself..
Otherwise to manage it in your model, you can proceed something like:
before_create :increment_booking_no
def increment_booking_no
self.booking_no = (self.class.last.nil?) ? "0" : ((self.class.last.booking_no.to_i) + 1).to_s
end
I have nested resources as follows:
employer.rb
class Employer < ActiveRecord::Base
has_many :listings
end
listing.rb
class Listing < ActiveRecord::Base
belongs_to :employer
end
I built both using basic scaffold generator.
Everything seems to work except when I create a new listing for employer. The route is
new_employer_listing GET
/company/:employer_id/listings/new(.:format)
{:action=>"new", :controller=>"listings"}
When I navigate to the new listing url (company/employer_id/listings/new)
I get:
NoMethodError in ListingsController#new
undefined method `listing' for #<Employer:0x102dd5e48>
Here is the listings_controller code for #new
def new
#employer = Employer.find_by_username(params[:employer_id])
#listing = #employer.listing.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #listing }
end
end
Again, everything else works (show, edit, etc) -- I just can't get a new listing page to come up... Any help would be awesome.
Thanks!
//EDIT BELOW
def create
#employer = Employer.find_by_username(params[:employer_id])
#listing = #employer.listings.new(params[:listing])
respond_to do |format|
if #listing.save
format.html { redirect_to(#listing, :notice => 'Listing was successfully created.') }
format.xml { render :xml => #listing, :status => :created, :location => #listing }
else
format.html { render :action => "new" }
format.xml { render :xml => #listing.errors, :status => :unprocessable_entity }
end
end
end
ERROR:
No route matches {:action=>"show", :controller=>"listings", :id=>#<Listing id: 20, job_title: "asd", location: nil, status: nil, industry: nil, years: nil, degree_type: nil, degree_field: nil, employer_id: 1, employers_id: nil, user_id: nil>}
In the Employer model you have added the has_many :listings association. But in your controller you call #employer.Listing.new. The thing that does not match here is Listing and listings.
You should instead do it like this:
#listing = #employer.listings.new(params[:listing)
Sidenotes:
Don't forget to call save on the #listing, otherwise it will not get saved.
I prefer to use build instead of new, that way the listing is available in the Employer association directly. Both methods valid though depending on how you use them.
The employer has_many listings, so you have to call #employer.listings, with an s.
I'm building a concert ticket sales application with Rails 3.0.4, working primarily with the Agile Web Development tutorial (http://pragprog.com/titles/rails3/agile-web-development-with-rails) and trying to incorporate Ryan Bate's order purchase method (http://railscasts.com/episodes/146-paypal-express-checkout). Everything works with the following in orders_controller.rb:
def create
#order = Order.new(params[:order])
#order.add_line_items_from_cart(current_cart)
#order.ip_address = request.remote_ip
respond_to do |format|
if #order.save
Notifier.order_received(#order).deliver
format.html { redirect_to(calendar_url, :notice => 'Thank you for your order.') }
format.xml { render :xml => #order, :status => :created, :location => #order }
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
else
format.html { render :action => "new" }
format.xml { render :xml => #order.errors, :status => :unprocessable_entity }
end
end
But when I add "&& #order.purchase" to the conditional clause, with the order.rb model as follows:
class Order < ActiveRecord::Base
#...
belongs_to :cart
#...
def price_in_cents
(cart.total_price*100).round
end
def purchase
response = GATEWAY.purchase(price_in_cents, credit_card, purchase_options)
cart.update_attribute(:purchased_at, Time.now) if response.success?
response.success?
end
#...
end
I receive an "undefined method `total_price' for nil:NilClass" error. I can get around this by adding
#order = current_cart.build_order(params[:order])
to the orders "create" method, but this messes up the "order_received" notification by somehow preventing the pertinent order information (in this case "#order.line_items") from rendering in the e-mail text.
The "cart" object is being set to nil somewhere along the way, but removing
Cart.destroy(session[:cart_id])
from the order "create" method does not fix the problem.
Anyone got a clue for this noob?
It doesn't look like the Cart object is ever actually specified in the belongs_to relation, you need to either do #order.cart = current_cart, or current_cart.order = Order.new, or something along those lines.