undefined method `plantposts' for nil:NilClass - ruby

This is my first app since finishing the tutorial at railstutorial.org and everything was going well until this. In my app each user can create plants and each plant can have many plantposts. I have put a form to create new plantposts on the plants/id (show) page which I cannot get working. I suspect it may have to do with the routes file.
Here are my controllers:
class PlantpostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
##plantpost = Plantpost.new(plantpost_params)
##plant = Plant.find(params[:plant_id])
#plantpost = #plant.plantposts.build(plantpost_params) #this seems to be the main problem line.
if #plantpost.save
flash[:success] = "Plantpost created!"
redirect_to plant_path(#plantpost.plant_id)
else
flash[:danger] = "No Plantpost created!"
#plantpost_feed_items = []
redirect_to plant_path(id: params[:plant_id] )
end
end
def destroy
#plantpost.destroy
flash[:success] = "Plantpost deleted"
redirect_to request.referrer || root_url
end
private
def plantpost_params
params.require(:plantpost).permit(:content, :picture, :user_id, :plant_id)
end
def correct_user
#plantpost = current_user.plantposts.find_by(id: params[:id])
redirect_to root_url if #plantpost.nil?
end
end
My Plants Controller
class PlantsController < ApplicationController
before_action :logged_in_user, only: [:index, :create, :edit, :update,
:destroy, :show]
before_action :correct_user, only: [:destroy, :update ]
def new
#plant = Plant.new
end
def index
#plant_feed_items = current_user.plants.paginate(page: params[:page], :per_page => 10)
#plants = current_user.plants.all
#plant = Plant.new
end
def show
#plant = Plant.find(params[:id])
#plantpost_feed_items = #plant.plantpost_feed.paginate(page: params[:page], :per_page => 10)
#plantposts = #plant.plantposts.paginate(page: params[:page])
#plantpost = Plantpost.new
end
private
def plant_params
params.require(:plant).permit( :notes, :plantname,:source, :planted, :harvested, :yield, :yieldunits)
end
def correct_user
#plant = current_user.plants.find_by(id: params[:id])
redirect_to root_url if #plant.nil?
end
def plantpost_params
params.require(:plantpost).permit(:content, :picture, :user_id, :plant_id)
end
The relevant parts of the model relationships
class User < ActiveRecord::Base
has_many :plants, dependent: :destroy
has_many :plantposts, through: :plants, dependent: :destroy
class Plant < ActiveRecord::Base
has_many :plantposts, dependent: :destroy
belongs_to :user
class Plantpost < ActiveRecord::Base
belongs_to :plant
belongs_to :user
And the routes file
Rails.application.routes.draw do
get 'password_resets/new'
get 'password_resets/edit'
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users do
member do
get :following, :followers
end
end
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :microposts, only: [:create, :destroy]
resources :relationships, only: [:create, :destroy]
resources :plantposts, only: [:create, :destroy]
resources :plants
#post 'plants' => 'plantposts#create'
end
As you can see from all the hashtags I have been trying a lot of combinations hoping to stumble across the right one.
I have also written an integration test in which this line " post plant_path(#plant.id), plantpost: { content: "" }" gets this response
ERROR["test_plantpost_interface", PlantpostInterfaceTest, 1.515159549]
test_plantpost_interface#PlantpostInterfaceTest (1.52s)
ActionController::RoutingError: ActionController::RoutingError: No route matches [POST] >"/plants/980190962"
test/integration/plantposts_interface_test.rb:16:in block in
<class:PlantpostInterfaceTest>'
test/integration/plantposts_interface_test.rb:16:inblock in '

It seems like what you want to do is nest the resources.
In your routes file, change
resources :plantposts, only: [:create, :destroy]
resources :plants
to
resources :plants do
resources :plantposts, only: [:create, :destroy]
end

This turned out to be a syntax problem. The working create code is:
def create
#plant = Plant.find_by(id: params[:plant_id] )
#plantpost = #plant.plantposts.build({:plant_id => params[:plant_id], :user_id => current_user.id, :content => params[:plantpost][:content], :picture => params[:plantpost][:picture]})
if #plantpost.save
flash[:success] = "Plantpost created!"
redirect_to plant_path :id => #plant.id
else
#plantpost_feed_items = []
render 'plants/show', :id => #plant.id
end
end
I'm sure there is a cleaner way to do it but I'm moving on.

Related

Rails - Unknown Attribute - Unable to add a new field to a form on create/update

Hello I am new to Rails.
Here is my controller/projects_controller.rb code
def create
#project = current_user.projects.new(project_params)
##project.website = params[:website]
respond_to do |format|
if #project.save
Member.create!(
user_id: current_user.id,
project_id: #project.id,
project_manager: true,
status: "ready")
format.html { redirect_to #project, notice: 'Project was successfully created.' }
format.json { render :show, status: :created, location: #project }
else
format.html { render :new }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
def update
##project.website = params[:website]
respond_to do |format|
# if (#project.active_was == true) &&
# disabled = true
# end
if #project.update(project_params)
# if disabled && (#project.active == false)
# flash[:modal] = true
# end
#project.website = params[:website]
format.html { redirect_to #project, notice: 'Project was successfully updated.' }
format.json { render :show, status: :ok, location: #project }
else
format.html { render :edit }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
def project_params
params.require(:project).permit(
:university_id,
:project_name,
:location,
:tagline,
:photos,
:industry,
:category,
:description,
:category_id,
:expertise_string,
:website,
:active,
:slug,
:project_groups_attributes => [:id, :active, :university_id, :user_group_id]
)
end
Here is the code for my model/project.rb
class Project < ActiveRecord::Base
# has_and_belongs_to_many :users
has_many :members, :dependent => :destroy
has_many :users, :through => :members
has_one :survey
has_many :project_groups, foreign_key: "project_id", dependent: :destroy
has_many :groups, :through => :project_groups, :source => :university
accepts_nested_attributes_for :project_groups, :allow_destroy => true
has_many :project_expertises, foreign_key: "project_id",
dependent: :destroy
has_many :expertises, :through => :project_expertises, :source => :expertise
belongs_to :category
belongs_to :website
Here is my db/migrate/[timestamp]_create_projects.rb code
class CreateProjects < ActiveRecord::Migration
def change
create_table :projects do |t|
t.integer :university_id
t.string :project_name
t.string :tagline
t.string :photos
t.string :industry
t.integer :category
t.text :description
t.text :website
t.timestamps
end
end
end
Why can I not add the 'website' field to this? Is there something more that I have to do?
As per your comment there is not any Website model available so there is not any meaning of putting association:
Simply remove this line from your project model
belongs_to :website
In Project model you've specified relation belongs_to :website. In migration schema instead of:
t.text :website
must be something like that:
t.references :website, index: true, foreign_key: true
When you generate model instead of
rails g ... website:text use rails g ... website:references.
ActiveRecord can't find foreign key to associate Project with Website.

Unpermitted parameters - Rails 4.1.1, Ruby 2.1.2

I cannot seem to get to the bottom of where I am going wrong. My "order.rb" fields populate ok, but I can't get the "order_row" table values to populate. I just keep getting the following error in terminal(not worried about date for now, should be ok with that)...
Unpermitted parameters: date(i), order_row
Customer model(customer.rb)...
class Customer < ActiveRecord::Base
has_many :orders, dependent: :destroy
end
Order model(order.rb)...
class Order < ActiveRecord::Base
belongs_to :customer
has_many :order_rows, dependent: :destroy
accepts_nested_attributes_for :order_rows
end
Order_Row model(order_row.rb)
class OrderRow < ActiveRecord::Base
belongs_to :order
end
(orders_controller.rb)....
def new
#order = Order.new
end
def create
#order = Order.new(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to(#order, :notice => 'Order was successfully created.') }
else
format.html { render :action => "new" }
end
end
end
private
def order_params
params.require(:order).permit(:customer_id, :date, :total,
:order_row_attributes => [:description, :quantity, :price, :order_id])
end
Form code on new.html.haml
= semantic_form_for #order do |f|
= f.input :customer_id, :as => :select, :collection => Hash[Customer.all.map{|c| [c.company,c.id]}]
= f.input :date
= f.fields_for :order_row do |ff|
= ff.input :description
= ff.input :quantity
= ff.input :price
= ff.hidden_field :order_id
= f.input :total
= f.action :submit, :as => :button
The problem is this line order_row_attributes.It should be order_rows_attributes. And with the date not being permitted,try changing the date attribute to some name like order_date.
This should work
private
def order_params
params.require(:order).permit(:customer_id, :order_date, :total,
:order_rows_attributes => [:description, :quantity, :price, :order_id])
end
I got it working by changing the new method to....
def new
#order = Order.new
#order.order_rows.build
end
So combination of this and Pavans answer did the trick.

Friendly_Id record not found

I get a record not found exception using friendly_id 5.0 stable with Rails 4.0
Error:
Migration:
class AddSlugToUsers < ActiveRecord::Migration
def change
add_column :users, :slug, :string
add_index :users, :slug
end
end
Controller:
class UsersController < ApplicationController
load_and_authorize_resource
before_filter :authenticate_user!
def index
authorize! :index, #user, :message => 'Not authorized as an administrator.'
#users = User.all
end
def show
##user = User.find(params[:id])
#user = User.friendly.find(params[:id])
end
def update
authorize! :update, #user, :message => 'Not authorized as an administrator.'
#user = User.find(params[:id])
if #user.update_attributes(params[:user], :as => :admin)
redirect_to users_path, :notice => "User updated."
else
redirect_to users_path, :alert => "Unable to update user."
end
end
def destroy
authorize! :destroy, #user, :message => 'Not authorized as an administrator.'
user = User.find(params[:id])
unless user == current_user
user.destroy
redirect_to users_path, :notice => "User deleted."
else
redirect_to users_path, :notice => "Can't delete yourself."
end
end
end
The Data:
INSERT INTO
users(id,email,encrypted_password,reset_password_token,reset_password_sent_at,remember_created_at,
sign_in_count,current_sign_in_at,last_sign_in_at,current_sign_in_ip,last_sign_in_ip,
created_at,updated_at,first_name,last_name,alias,bio,slug)
VALUES
(10,'me1#example.com','$2a$10$MYHASG','',null,null,0,null,null,'','',
Invalid Date,Invalid Date,'greek','god','tool','','tool');
It works if I put the ID into the url
http://0.0.0.0:3000/users/10
but does not work when using the slug
http://0.0.0.0:3000/users/tool
The quickest fix is to use the old 4-style finders as described in the readme by using the :finders addon.
Then you'll have friendly-id access via the "normal" find() method.
Example:
friendly_id :foo, use: [:slugged, :finders] # you can now do MyClass.find('bar')

Relationships in sqllite database no foreign key added

I want to create relationship from Post to User model. So I create:
class Post < ActiveRecord::Base
attr_accessible :text, :title, :image, :user_id
has_many :comments
belongs_to :user
mount_uploader :image, ImageUploader
end
and in User.rb:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
has_many :posts
end
Then I add file to database migration:
class AddUserIdToPost < ActiveRecord::Migration
def change
add_column :posts, :user_id, :integer
end
end
And made migration via rake db:migration.
When I add new post the value of user_id (in dataBase) is empty, but column exists.
Part of Post_Controller:
def create
#post = Post.new(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
What should I do with #post = Post.new(params[:post])? I think that everything is fine...
attr_accessible :text, :title, :image, :user_id
or, instead of attr_accessible, just do this:
attr_protected

How to pass user_id to nested_resource model?

I have a small project setup with devise and cancan. There are User, Project, Responsible and Task Models. Project has nested Tasks. Each Project is assigned to one or multiple users. The task model has a name, user_id and project_id. Authentication and Authorization is working like expected.
When adding a new Task (only an input for name) the project_id gets automatically passed to model/table (i think this is because of routing) but not the user_id.
Do i have to pass the user_id in a hidden_field or is it somehow possible to set this in a before filter?
Can somebody give a hint on howto set user_id in taskcontroller?
Thanks
# Routes
resources :projects do
resources :tasks
end
#Models
class User < ActiveRecord::Base
has_many :responsibilities, :dependent => :destroy
has_many :projects, :through => :responsibilities
has_many :tasks, :dependent => :destroy
...
class Project < ActiveRecord::Base
has_many :tasks, :dependent => :destroy
...
class Task < ActiveRecord::Base
belongs_to :project
belongs_to :user
...
# Tasks Controller with all Task.find/new/update/...
# methods removed like explained in cancan manual
class TasksController < ApplicationController
load_and_authorize_resource :project
load_and_authorize_resource :task, :through => :project
...
def create
respond_to do |format|
if #task.save
format.html { redirect_to [#project, #task], notice: 'created.' }
else
format.html { render action: "new" }
end
end
# Task Form View
<%= semantic_form_for [#project, #task] do |f| %>
<%= f.inputs do %>
<%= f.input :name %>
<% end %>
<%= f.actions %>
<% end %>
Update
It seems to work with a before filter. Is this the right way?
class TasksController < ApplicationController
before_filter :set_user, :only => [:create]
load_and_authorize_resource :client
load_and_authorize_resource :task, :through => :client, :shallow => true
...
def set_user()
params[:task][:user_id] = current_user.id.to_s
end
...
if you are using devise you can just pass in the create action you user_id
def create
#task.user = current_user
respond_to do |format|
if #task.save
format.html { redirect_to [#project, #task], notice: 'created.' }
else
format.html { render action: "new" }
end
end
not quiet sure if this is what you mean

Resources