Strong parameers throwing "Unknown key"Error - ruby-on-rails

I am trying to get this model working with Strong Parameters but I can't seem to work out what I am doing wrong!?
ERROR:
Unknown key: name
Controller:
class PracticesController < ApplicationController
def practice_params
if params[:action] == 'create'
params.require(:practice).permit( :name, :billing_address, :physical_address, :phone_number, :fax_number, :emergency_contact, :emergency_phone, :email_addres, :active, :ABN, :time_zone)
elsif params[:action] == 'update'
params.require(:practice).permit( :name, :billing_address, :physical_address, :phone_number, :fax_number, :emergency_contact, :emergency_phone, :email_addres, :active, :ABN, :time_zone)
end
end
# GET /practices
# GET /practices.json
def index
#practices = Practice.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #practices }
end
end
# GET /practices/1
# GET /practices/1.json
def show
#practice = Practice.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #practice }
end
end
# GET /practices/new
# GET /practices/new.json
def new
#practice = Practice.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #practice }
end
end
# GET /practices/1/edit
def edit
#practice = Practice.find(params[:id])
end
# POST /practices
# POST /practices.json
def create
#practice = Practice.new(practice_params)
respond_to do |format|
if #practice.save
format.html { redirect_to #practice, notice: 'Practice was successfully created.' }
format.json { render json: #practice, status: :created, location: #practice }
else
format.html { render action: "new" }
format.json { render json: #practice.errors, status: :unprocessable_entity }
end
end
end
# PUT /practices/1
# PUT /practices/1.json
def update
#practice = Practice.find(practice_params)
respond_to do |format|
if #practice.update_attributes(practice_params)
format.html { redirect_to #practice, notice: 'Practice was successfully updated.' }
format.json { head :ok }
else
format.html { render action: "edit" }
format.json { render json: #practice.errors, status: :unprocessable_entity }
end
end
end
# DELETE /practices/1
# DELETE /practices/1.json
def destroy
#practice = Practice.find(params[:id])
#practice.destroy
respond_to do |format|
format.html { redirect_to practices_url }
format.json { head :ok }
end
end
end
Model:
class Practice < ActiveRecord::Base
#has_many :providers, :patients, :employees, :operatories, :clinics, :patients,
has_many :imagecategories
validates_inclusion_of :time_zone, in: ActiveSupport::TimeZone.zones_map(&:name)
def initial_setup
Operatory.create(:name => "Default Operatory", :active => true, :practice => self)
####### Create Practice Basic Accounts:
Revenue.create(:name => "General Revenue", :practice => self)
end
end
Schema (relevant part of):
create_table "practices", force: true do |t|
t.string "name"
t.text "billing_address"
t.text "physical_address"
t.string "phone_number"
t.string "fax_number"
t.string "emergency_contact"
t.string "emergency_phone"
t.string "email_address"
t.boolean "active"
t.string "ABN"
t.datetime "created_at"
t.datetime "updated_at"
t.string "time_zone"
end
Any help getting this sorted out would be much appreciated, maybe I am tired and just missing something obvious. But I copied most of the code from other controllers that are working correctly andthink I have made all the necessary adjustments. Any help would be much appreciated
PS its not just limited to the :name parameter, when I remove that one it simply starts complaining about:billing_address

In update action, change
#practice = Practice.find(practice_params)
to
#practice = Practice.find(params[:id])

Related

Validate unique array values in Rails

My Transaction model generates an array of unique ticket numbers based on quantity (an integer column) with the following controller logic:
#transaction.quantity.times.uniq { #transaction.ticket_numbers << rand(100000..999999) }
However, this only ensures that the numbers WITHIN the array are unique.
I need a database validation that checks ALL Transaction.ticket_numbers arrays to ensure that every value (ticket number) is unique across ALL arrays.
Here is my Transaction table within schema.rb:
create_table "transactions", force: :cascade do |t|
t.string "payee"
t.integer "quantity"
t.decimal "debt", precision: 8, scale: 2
t.string "email"
t.string "ministry"
t.integer "status"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "ticket_numbers", default: [], array: true
end
Transaction model from transaction.rb:
require 'csv'
class Transaction < ApplicationRecord
belongs_to :user
validates :email, :format => { :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/, :on => [:create, :update] }
validates :payee, presence: true
validates :quantity, numericality: { greater_than_or_equal_to: 1 }
validates :debt, numericality: { greater_than_or_equal_to: 0 }
def self.to_csv
attributes = %w{payee email ministry quantity debt status ticket_numbers}
CSV.generate(headers: true) do |csv|
csv << attributes
all.each do |transaction|
csv << attributes.map{ |attr| transaction.send(attr) }
end
end
end
end
Transaction controller:
class TransactionsController < ApplicationController
before_action :load_transaction, only: [:edit, :update, :destroy]
def create
#transaction = Transaction.new(transaction_params)
if #transaction.save
#transaction.quantity.times.uniq { #transaction.ticket_numbers << rand(100000..999999) }
end
#user = #transaction.user
#transactions = #user.transactions
respond_to do |format|
if #transaction.save && #transaction.status == 1
UserMailer.payment_confirmation(#transaction).deliver_later
format.html { redirect_to user_url(#user), notice:'Transaction added & ticket sent' }
format.json { render json: #user, status: :created, location: #user }
elsif #transaction.save && #transaction.status != 1
format.html { redirect_to user_url(#user), notice:'Transaction added' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render 'users/show' }
format.json { render json: #transaction.errors, status: :unprocessable_entity }
end
end
end
def edit
#user = current_user
end
def update
update_ticket_numbers
respond_to do |format|
if #transaction.update_attributes(transaction_params) && #transaction.status == 1
UserMailer.payment_confirmation(#transaction).deliver_later
format.html { redirect_to user_url(current_user), notice: 'Transaction info updated & confirmation email sent to payee' }
format.json { render json: current_user, status: :created, location: current_user }
elsif #transaction.update_attributes(transaction_params) && #transaction.status != 1
format.html { redirect_to user_url(current_user), notice: 'Transaction info updated' }
format.json { render json: current_user, status: :created, location: current_user }
else
format.html { render :edit }
format.json { render json: #transaction.errors, status: :unprocessable_entity }
end
end
end
def destroy
#transaction.destroy
redirect_to user_url(current_user), notice: 'Transaction deleted'
end
private
def load_transaction
#transaction = Transaction.find(params[:id])
end
def transaction_params
params.require(:transaction).permit(:payee, :email, :ministry, :debt,
:quantity, :status, :user_id, :ticket_numbers)
end
def update_ticket_numbers
if #transaction.update_attributes(transaction_params)
if #transaction.ticket_numbers.length < #transaction.quantity
i = #transaction.quantity - #transaction.ticket_numbers.length
i.times.uniq { #transaction.ticket_numbers << rand(100000..999999) }
elsif #transaction.ticket_numbers.length > #transaction.quantity
i = #transaction.ticket_numbers.length - #transaction.quantity
i.times { #transaction.ticket_numbers.pop }
end
end
end
end
You can add a custom ticket number validation to your model. You can read more about them here
class Transaction < ApplicationRecord
validate :ticket_number_uniqueness
def ticket_number_uniqueness
# First check all new ticket numbers are unique from each other
errors.add(:ticket_number, "is not unique") unless ticket_numbers == ticket_numbers.uniq
# Next check against other ticket numbers
ticket_numbers.each do |ticket|
if ::Transaction.where("ticket_numbers #> '{?}'", ticket).exists?
errors.add(:ticket_number, "is not unique")
end
end
end
end
Note: this is taking advantage of Postgres contains array method #>. You can learn more about array methods here

Article/post drafts in Rails

I am working on a wiki application in Rails that would be publicly editable. I have an articles controller and a drafts controller. When someone clicks 'edit' on an article, I would like to create a new draft with the contents of the original article, and then save that to the database table when the user clicks 'save'. Any ideas on how I might go about doing this? I've been stuck on it for a few days.
Currently, each article belongs_to a category, a subcategory, and has_many drafts.
Database schema:
ActiveRecord::Schema.define(version: 20160723153357) do
create_table "articles", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "title"
t.text "content"
t.integer "category_id"
t.integer "subcategory_id"
end
create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "drafts", force: :cascade do |t|
t.string "title"
t.text "content"
t.integer "category_id"
t.integer "subcategory_id"
t.integer "article_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "subcategories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_id"
end
end
Articles_controller:
class ArticlesController < ApplicationController
before_action :set_article, only: [:show, :edit, :update, :destroy]
# GET /articles
# GET /articles.json
def index
if params[:category].blank? && params[:subcategory].blank?
#articles = Article.all.order("created_at DESC")
elsif params[:subcategory].blank?
#category_id = Category.find_by(name: params[:category]).id
#articles = Article.where(category_id: #category_id).order("created_at DESC")
else
#subcategory_id = Subcategory.find_by(name: params[:subcategory]).id
#articles = Article.where(subcategory_id: #subcategory_id).order("created_at DESC")
end
end
# GET /articles/1
# GET /articles/1.json
def show
end
# GET /articles/new
def new
#article = Article.new
end
# GET /articles/1/edit
def edit
end
# POST /articles
# POST /articles.json
def create
#parameters = article_params
#parameters[:category] = Category.find_by(id: Subcategory.find_by(id: article_params[:subcategory_id]).category_id)
#article = Article.new(#parameters)
respond_to do |format|
if #article.save
format.html { redirect_to #article, notice: 'Article was successfully created.' }
format.json { render :show, status: :created, location: #article }
else
format.html { render :new }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /articles/1
# PATCH/PUT /articles/1.json
def update
respond_to do |format|
if #article.update(article_params)
format.html { redirect_to #article, notice: 'Article was successfully updated.' }
format.json { render :show, status: :ok, location: #article }
else
format.html { render :edit }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.json
def destroy
#article.destroy
respond_to do |format|
format.html { redirect_to articles_url, notice: 'Article was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_article
#article = Article.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def article_params
params.require(:article).permit(:title,:content,:subcategory_id)
end
end
Drafts_controller:
class DraftsController < ApplicationController
before_action :set_draft, only: [:show, :edit, :update, :destroy]
# GET /drafts
# GET /drafts.json
def index
#drafts = Draft.all
end
# GET /drafts/1
# GET /drafts/1.json
def show
end
# GET /drafts/new
def new
#draft = Draft.new
end
# GET /drafts/1/edit
def edit
end
# POST /drafts
# POST /drafts.json
def create
#parameters = draft_params
#parameters[:article_id] = params[:article_id]
#parameters[:subcategory_id] = 2
#parameters[:category_id] = 2
#draft = Draft.new(#parameters)
respond_to do |format|
if #draft.save
format.html { redirect_to #draft, notice: 'Draft was successfully created.' }
format.json { render :show, status: :created, location: #draft }
else
format.html { render :new }
format.json { render json: #draft.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /drafts/1
# PATCH/PUT /drafts/1.json
def update
respond_to do |format|
if #draft.update(draft_params)
format.html { redirect_to #draft, notice: 'Draft was successfully updated.' }
format.json { render :show, status: :ok, location: #draft }
else
format.html { render :edit }
format.json { render json: #draft.errors, status: :unprocessable_entity }
end
end
end
# DELETE /drafts/1
# DELETE /drafts/1.json
def destroy
#draft.destroy
respond_to do |format|
format.html { redirect_to drafts_url, notice: 'Draft was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_draft
#draft = Draft.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def draft_params
params.require(:draft).permit(:title, :content)
end
end
Article model:
class Article < ApplicationRecord
belongs_to :category
belongs_to :subcategory
has_many :drafts
end
Draft model:
class Draft < ApplicationRecord
belongs_to :category
belongs_to :subcategory
belongs_to :article
end
I think an approach I would probably follow would be to extract the content information to another table altogether. Here's a rough implementation I could come up with immediately:
class Article < ApplicationRecord
#column_names: ['type:string']
has_many :contents
has_one :current_content, -> { current.or(approved) }, class_name: 'Content'
delegate :title, :content, to: :current_content, allow_nil: true
end
class Content < ApplicationRecord
#column_names: ["article_id:int", "title:string", "content:text", "status:int"]
belongs_to :article
enum status: [:unapproved, :approved, :current]
end
class Draft < Article
#use STI here
end
#services/set_current_article_content.rb
class SetCurrentArticleContent
attr_reader :article, :content
def initialize(article, content)
#article = article
#content = content
end
def call
article.current_content.approved!
content.current!
end
end
#services/edit_wiki_content.rb
class EditWikiContent.rb
attr_reader :article, :content
def initialize(article, content)
#article = article
#content = content
end
def call
article.contents << content
content.save!
end
end
#services/publish_draft.rb
class PublishDraft
attr_reader :draft
def initialize(draft)
#draft = draft
end
def call
draft.becomes!(Article)
end
end
There are three services which would handle the updating and setting of the current content and also publishing the draft, you could add some additional logic in any of them. Also note the condition for the current_content in the article model, your logic might be different from the way I have implemented it.

Rails Association Bug

I am getting NoMethodError in SitesController#index undefined method `name' for nil:NilClass in my Salesman index view and cannot find the culprit.
I have a simple rails app with the following tables: Customer, Salesman and Invoice.
In the index view for the customer table I have the following call:
<% #customers.each do |customer| %>
<%= customer.name %></td>
<%= customer.address %>
<%= customer.salesman.name %>
<% end %>
This is the call that results in the undefined method ´name´ listed above. I made sure the salesman table has a salesman_id foreign key in the customer table. Also, I made the respective association in the models:
class Customer < ActiveRecord::Base
belongs_to :salesman
has_many :invoices
end
class Salesman < ActiveRecord::Base
has_many :customers
end
I tested the customer.salesman.name call in the console and it works flawlessly. The show view for the customer has an exact call like this one and it also works. The only way I can make the customer index pass is by replacing customer.salesman.name to customer.salesman_id returning only the id.
Thank you for your time here.
***schema.rb***
ActiveRecord::Schema.define(version: 20150325172212) do
create_table "customers", force: :cascade do |t|
t.string "name"
t.string "address"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "salesman_id"
end
create_table "invoices", force: :cascade do |t|
t.datetime "date"
t.string "fid"
t.integer "salesman_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "address"
end
create_table "salesmen", force: :cascade do |t|
t.datetime "name"
t.string "address""
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
***controllers***
**customer**
Class CustomersController < ApplicationController
before_action :set_customer, only: [:show, :edit, :update, :destroy]
# GET /customers
# GET /customers.json
def index
#customers = Customer.all
end
# GET /customers/1
# GET /customers/1.json
def show
end
# GET /customers/new
def new
#customer = Customer.new
end
# GET /customers/1/edit
def edit
end
# POST /customers
# POST /customers.json
def create
#customer = Customer.new(customer_params)
respond_to do |format|
if #customer.save
format.html { redirect_to #customer, notice: 'Customer was successfully created.' }
format.json { render :show, status: :created, location: #customer }
else
format.html { render :new }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /customers/1
# PATCH/PUT /customers/1.json
def update
respond_to do |format|
if #customer.update(customer_params)
format.html { redirect_to #customer, notice: 'Customer was successfully updated.' }
format.json { render :show, status: :ok, location: #customer }
else
format.html { render :edit }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
# DELETE /customers/1
# DELETE /customers/1.json
def destroy
#customer.destroy
respond_to do |format|
format.html { redirect_to customers_url, notice: 'Customer was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_cliente
#cliente = Cliente.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def customer_params
params.require(:customer).permit(:name, :address, :salesman_id)
end
end
***salesman***
class SalesmenController < ApplicationController
before_action :set_salesman, only: [:show, :edit, :update, :destroy]
# GET /salesmans
# GET /salesmans.json
def index
#salesmen = Salesman.all
end
# GET /salesmans/1
# GET /salesmans/1.json
def show
end
# GET /salesmans/new
def new
#salesman = Salesman.new
end
# GET /salesmans/1/edit
def edit
end
# POST /salesmans
# POST /salesmans.json
def create
#salesman = Salesman.new(salesman_params)
respond_to do |format|
if #salesman.save
format.html { redirect_to #salesman, notice: 'Salesman was successfully created.' }
format.json { render :show, status: :created, location: #salesman }
else
format.html { render :new }
format.json { render json: #salesman.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /salesmans/1
# PATCH/PUT /salesmans/1.json
def update
respond_to do |format|
if #salesman.update(salesman_params)
format.html { redirect_to #salesman, notice: 'Salesman was successfully updated.' }
format.json { render :show, status: :ok, location: #salesman }
else
format.html { render :edit }
format.json { render json: #salesman.errors, status: :unprocessable_entity }
end
end
end
# DELETE /salesmans/1
# DELETE /salesmans/1.json
def destroy
#salesman.destroy
respond_to do |format|
format.html { redirect_to salesmans_url, notice: 'Salesman was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_salesman
#salesman = Salesman.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def salesman_params
params.require(:salesman).permit(:name, :address)
end
**invoice**
class InvoicesController < ApplicationController
before_action :set_invoice, only: [:show, :edit, :update, :destroy]
# GET /invoices
# GET /invoices.json
def index
#invoices = Invoice.all
end
# GET /invoices/1
# GET /invoices/1.json
def show
#invoice = Invoice.find(params[:id])
#ordenes = #invoice.ordenes
end
# GET /invoices/new
def new
#invoice = Invoice.new
end
# GET /invoices/1/edit
def edit
end
# POST /invoices
# POST /invoices.json
def create
#invoice = Invoice.new(invoice_params)
respond_to do |format|
if #invoice.save
format.html { redirect_to #invoice, notice: 'Invoice was successfully created.' }
format.json { render :show, status: :created, location: #invoice }
else
format.html { render :new }
format.json { render json: #invoice.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /invoices/1
# PATCH/PUT /invoices/1.json
def update
respond_to do |format|
if #invoice.update(invoice_params)
format.html { redirect_to #invoice, notice: 'Invoice was successfully updated.' }
format.json { render :show, status: :ok, location: #invoice }
else
format.html { render :edit }
format.json { render json: #invoice.errors, status: :unprocessable_entity }
end
end
end
# DELETE /invoices/1
# DELETE /invoices/1.json
def destroy
#invoice.destroy
respond_to do |format|
format.html { redirect_to invoices_url, notice: 'Invoice was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_invoice
#invoice = Invoice.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def invoice_params
params.require(:invoice).permit(:date, :fid, :name, :address, :salesman_id)
end
end
-davefogo
Add the following to your views instead of what you currently have<%= customer.salesman.name if customer.salesman %>
This will ensure that you're not calling name when customer doesn't have a salesman.
Try this:
<% #customers.each do |customer| %>
<%= customer.name %>
<%= customer.address %>
<%= customer.salesman.try(:name) %>
<% end %>
Do this:
<% #customers.each do |customer| %>
<% Rails.logger.debug "\n\n#{#customers} has a nil customer in it\n\n" if customer.nil? %>
<% Rails.logger.debug "\n\nCustomer #{customer.id} has no salesman for [#{customer.salesman_id}]\n\n" if customer.salesman.nil? %>
<%= customer.name %>
<%= customer.address %>
<%= customer.salesman.name %>
<% end %>
...and then check your logs after hitting the index.

Rails Paperclip Carrierwave.. Errors

Hey I'm doing something strange. Using both Paperclip & Carrierwave to determine which i like better because I am new to rails but here is the issue.
When I create a post using Paperclip, the image gets routed to the directory but does not display/render in any view.
When I create a post using Carrierwave, the image never gets routed or renders and I get an error withing the postscontroller saying.
(undefined method `image_will_change!' for #Post:0x007fd039c02888)
app/controllers/posts_controller.rb:27:in `create'
I also get an error across the app when trying to edit any of the post that error is.
(undefined method 'image_changed?' for #Post:0x007fd03fc76fe8)
app/controllers/posts_controller.rb:44:in `block in update'
app/controllers/posts_controller.rb:43:in `update'
Heres my code:
(post.rb)
class Post < ActiveRecord::Base
attr_accessor :image
has_attached_file :content, :styles => { :medium => "300x300>", :thumb => "100x100>" }
mount_uploader :image, ImageUploader
end
(postscontroller.rb)
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy, :destroy_all]
def index
#posts = Post.all
end
def show
end
def new
#post = Post.new
end
def edit
end
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content, :no_image }
end
end
def destroy_all
#post.destroy_all
respond_to do |format|
format.html { redirect_to posts, notice: 'All Posts have bee successfully destroyed.'}
format.json { head :no_content, :no_image}
end
end
def demo
#post = Post.all
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:title, :description, :content, :image)
end
end
(imageuploader.rb)
class ImageUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"images"
end
(add_content_to_posts.rb)
class AddContentToPosts < ActiveRecord::Migration
def self.up
add_attachment :posts, :content
end
def self.down
remove_attachment :posts, :content
end
end
(add_image_to_posts.rb)
class AddImageToPosts < ActiveRecord::Migration
def change
add_column :posts, :images, :string
end
end
(Schema.rb)
create_table "posts", force: true do |t|
t.string "title"
t.string "description"
t.datetime "created_at"
t.datetime "updated_at"
t.string "content_file_name"
t.string "content_content_type"
t.integer "content_file_size"
t.datetime "content_updated_at"
t.string "images"
end

How to solve NoMethodError for this case?

So my rails app has a number of airport fares defined for each operator, as:
class AirportFare < ActiveRecord::Base
belongs_to :operator
end
class Operator < ActiveRecord::Base
has_many :airport_fares
end
My routes are defined as:
resources :operators do
resources :airport_fares
end
And following is my airport_fares_controller:
class AirportFaresController < ApplicationController
before_action :set_airport_fare, only: [:show, :edit, :update, :destroy]
before_action :set_operator
# GET /airport_fares
# GET /airport_fares.json
def index
#operator = Operator.find(params[:operator_id])
#airport_fares = Operator.find(params[:operator_id]).airport_fares
end
# GET /airport_fares/1
# GET /airport_fares/1.json
def show
end
# GET /airport_fares/new
def new
#airport_fare = Operator.find(params[:operator_id]).airport_fares.build
end
# GET /airport_fares/1/edit
def edit
end
# POST /airport_fares
# POST /airport_fares.json
def create
#airport_fare = Operator.find(params[:operator_id]).airport_fares.build(airport_fare_params)
respond_to do |format|
if #airport_fare.save
format.html { redirect_to #airport_fare, notice: 'Airport fare was successfully created.' }
format.json { render :show, status: :created, location: #airport_fare }
else
format.html { render :new }
format.json { render json: #airport_fare.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /airport_fares/1
# PATCH/PUT /airport_fares/1.json
def update
respond_to do |format|
if #airport_fare.update(airport_fare_params)
format.html { redirect_to #airport_fare, notice: 'Airport fare was successfully updated.' }
format.json { render :show, status: :ok, location: #airport_fare }
else
format.html { render :edit }
format.json { render json: #airport_fare.errors, status: :unprocessable_entity }
end
end
end
# DELETE /airport_fares/1
# DELETE /airport_fares/1.json
def destroy
#airport_fare.destroy
respond_to do |format|
format.html { redirect_to operator_airport_fares_path(operator_id: #operator.id), notice: 'Airport fare was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_operator
#operator = Operator.find(params[:operator_id])
end
def set_airport_fare
#airport_fare = AirportFare.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def airport_fare_params
params.require(:airport_fare).permit(:cabcat, :triptype, :triptime, :basedist, :basehr, :basechrg, :ratepkm, :waitingbtime, :waitingchrg, :notes, :operator_id)
end
end
My db schema says:
create_table "airport_fares", force: true do |t|
t.string "cabcat"
t.string "triptype"
t.string "triptime"
t.decimal "basedist", precision: 8, scale: 2
t.integer "basehr"
t.decimal "basechrg", precision: 8, scale: 2
t.decimal "ratepkm", precision: 8, scale: 2
t.integer "waitingbtime"
t.decimal "waitingchrg", precision: 8, scale: 2
t.text "notes"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "operator_id"
end
The problem is when I try this in my console: AirportFare.first.operator. This leads to the error:
NoMethodError: undefined method 'operator' for #<AirportFare>.
Where is the problem?
In new action you should do:
def new
#operator = Operator.find(params[:operator_id])
#airprot_fare = AirportFare.new
end
in your form:
<%= form_for [#operator, #airport_fare] do |f| %>
This should work.
It Should be operator.first.airport_fares. As you have has_many relationship on operators

Resources