I've run into an issue with my Ruby on Rails app. I've a page called /discussion which contains discussions that users can comment on with microposts. The goal here is to have a form below each micropost that, when submitted, will put the text in the discussion. The form shows up - but whenever I click submit I get the error:
NoMethodError in MicropostsController#create
undefined method `micropost' for #<User:0x007f9744091680>
Rails.root: /home/nick/Documents/RailsProjects/buon
Application Trace | Framework Trace | Full Trace
app/controllers/microposts_controller.rb:8:in `create'
the micropost controller
class MicropostsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
def index
end
def create
#micropost = current_user.micropost.build(params[:micropost])
if #micropost.save
flash[:success] = "Posted!"
redirect_to root_url
else
render 'static_pages/home'
end
end
def destroy
end
end
the _discusions.html
<% content_for :script do %>
<%= javascript_include_tag 'hover_content' %>
<% end %>
<li>
<div class = "intro-bar"><span class = "intro"><%=discussion.intro %></span></div>
<div class = "content-bar"><span class = "content"><%= discussion.content %></span></div>
<span class = "timestamp">
Posted <%= time_ago_in_words(discussion.created_at) %> ago.
</span>
</li>
<% if signed_in? %>
<div class = "row">
<aside class = "span4">
<section>
<%= render 'shared/micropost_form', :locals => {:discussion => discussion }%>
</section>
</aside>
</div>
<% end %>
the micropost model
class Micropost < ActiveRecord::Base
attr_accessible :break_votes, :content, :not_votes
belongs_to :user
belongs_to :discussion
validates :content, presence: true, length: { maximum: 200 }
validates :user_id, presence: true
default_scope order: 'microposts.created_at DESC'
end
any ideas?
If this is a has_many association you need to pluralize, so your code should read:
#micropost = current_user.microposts.build(params[:micropost])
Related
I'm trying to create a Library Management app and stuck in comment model
So, this is my relationship for comment model:
class User < ApplicationRecord
has_many :comments, dependent: :destroy
end
class Book < ApplicationRecord
has_many :comments, dependent: :destroy
end
class Comment < ApplicationRecord
belongs_to :user
belongs_to :book
validates :content, presence: true, allow_blank: false
end
comments_controller.rb
class CommentsController < ApplicationController
before_action :load_book, only: :create
def index
#q = Comment.ransack(params[:q])
#comments = #q.result.page(params[:page])
end
def new;
end
def create
#comment = Comment.new(comment_params)
#comment.user_id = current_user.id
#comment.book_id = params[:book_id]
if #comment.save
flash[:success] = "create_success"
redirect_to book_path(#book)
end
private
def comment_params
params.require(:comment).permit(:user_id, :book_id, :content)
end
def load_book
#book = Book.find_by(params[:id])
return if #book
flash[:danger] = "books.load_book.error_message"
redirect_to root_path
end
end
in books_controller.rb
def show
#comment = Comment.new
end
app/view/books/show.html.erb
<% provide :title, #book.name %>
<h1><%= #book.name %></h1>
<div class="container">
<dl>
<dt>Author:</dt><dd><%= link_to #book.author.name, #book.author
%></dd><br>
<dt>Category:</dt><dd>
<% #book.categories.each do |c|%>
<%= link_to c.name, c%> |
<% end %>
<dt>Publisher:</dt><dd><%= #book.publisher %></dd><br>
<dt>Page:</dt><dd><%= #book.page %></dd><br>
<dt>Quantity:</dt><dd><%= #book.quantity %></dd><br>
</dl>
<aside>
<section>
<%= render 'comments/form' %>
</section>
</aside>
</div>
app/view/comments/_form.html.erb
<h3>post_comment</h3>
<p>
<%= form_for(#comment) do |f| %>
<%= f.text_area :content %>
<%= f.submit "post", class: "btn btn-primary" %>
<% end %>
</p>
And the browser show this Error:
Missing template comments/new, application/new with {:locale=>
[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb,
:html, :builder, :ruby, :coffee, :jbuilder]}. Searched in: *
"/home/default/ProjectRails/app/views"
This is the first time I make a many to many relationship, is it ok or the problem is in another part ?
As clearly mentioned in the error message
CommentsController#index is missing a template for this request format and variant.
You need to create the file app/view/comments/index.html.erb with some content
I'm new to Rails. I've created a category model for my posts but when I go to display all posts associated with a particular category I get a NameError page
Here's my categories show.html.erb file:
<h1> <%= "Category: " + #category.name %></h1>
<div align="center">
<%= will_paginate #category_posts %>
</div>
<%= render 'posts/post', obj: #category_posts %>
<div align="center">
<% will_paginate #category_posts %>
</div>
I'm rendering the _post.html.erb partial to display posts that was defined in my post folder.
Looks like the issue is linked to the first line in the code below because the error message points to <li id="post-<%= post.id %>"> in the _post.html.erb code:
<li id="post-<%= post.id %>">
<span class="title"> <%=link_to post.title, post_path(post) %> </span>
<span class="content"><%= truncate(post.content, length: 100) if post.content? %></span>
<span class="content"> <%= image_tag post.picture.url if post.picture? %> </span>
<span class="content">
<% if post.category.any? %>
<p><%= render post.category %></p>
<% end %>
</span>
</li>
And this is my category controller file where I definite the "show" method:
class CategorysController < ApplicationController
before_action :require_admin, except: [:index, :show]
def index
#categories = Category.paginate(page: params[:page])
end
def new
#category = Category.new
end
def create
#category = Category.new(category_params)
if #category.save
flash[:success] = "Category created successfully"
redirect_to categories_path
else
render 'new'
end
end
def show
#category = Category.find(params[:id])
#category_posts = #category.posts.paginate(page: params[:page], per_page: 5)
end
The Post model:
class Post < ApplicationRecord
belongs_to :user
has_many :post_categories
has_many :categories, through: :post_category
default_scope -> { order(created_at: :desc) }
mount_uploader :picture, PictureUploader
validates :user_id, presence: true
validates :title, presence: true
validate :picture_size
private
# validates the size of an upload picture
def picture_size
if picture.size > 5.megabytes
errors.add(:picture, "should be less than 5MB")
end
end
end
The general idea is that when I go to localhost/categories/1 for example, I should have all the posts associated with that category.
Can anyone help me resolve this issue?
You probably mean to render a partial using a collection:
render(partial: 'posts/post', collection: #category_posts)
Where that should expand that partial to repeat once for each post and assign the local post variable.
obj isn't a valid argument, but object is if you want to render the content once with a given object.
I am trying to use fields_for and create a nested form, however only one text field shows up, blank. I have 3 crewmember records.
crewmember model:
class Crewmember < ActiveRecord::Base
belongs_to :production
belongs_to :callsheet
validates :firstname, presence: true
validates :email, presence: true
def name
"#{firstname} #{lastname}"
end
end
callsheet model
class Callsheet < ActiveRecord::Base
attr_accessible :crewmembers_params
has_many :castmembers
has_many :crewmembers
accepts_nested_attributes_for :crewmembers
end
callsheets controller
class CallsheetsController < ApplicationController
def index
#callsheets = Callsheet.all
#departments = Department.where(production_id: current_user.default_working_production_id)
end
def show
#callsheet = Callsheet.find(params[:id])
end
def new
#callsheet = Callsheet.new
#departments = Department.where(production_id: current_user.default_working_production_id)
end
def edit
#callsheet = Callsheet.find(params[:id])
end
def create
#callsheet = Callsheet.new(callsheets_params)
#Callsheet.production_id = current_user.default_working_production_id
if #callsheets.save
redirect_to callsheet_path
else
render 'new'
end
end
def update
#callsheet = Callsheet.find(params[:id])
if #callsheet.update(callsheets_params)
redirect_to callsheet_path, :notice => "callsheets successfully updated."
else
render 'edit', :notice => "callsheets not updated."
end
end
def destroy
#callsheet = Callsheet.find(params[:id])
#callsheet.destroy
redirect_to callsheets_path
end
private
def callsheets_params
params.require(:callsheet).permit(:crewmembers_params [:id, :firstname])
end
end
form for new callsheet:
<%= form_for #callsheet do |f| %>
<% if #callsheet.errors.any? %>
<div id="error_explanation" class="alert alert-danger">
<strong>
<%= pluralize(#callsheet.errors.count, "error") %> prohibited
this call sheet from being saved:
</strong>
<ul>
<% #callsheet.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.fields_for :crewmember do |crewmember| %>
<fieldset>
<%= crewmember.label :firstname, "First Name" %><br />
<%= crewmember.text_field :firstname %>
</fieldset>
<% end %>
<% end %>
You don't need attr_accessible (that's only for Rails 3).
You should also rename all your models to snake_case, referencing with CamelCase:
#app/models/call_sheet.rb
class CallSheet < ActiveRecord::Base
has_many :cast_members
has_many :crew_members
accepts_nested_attributes_for :crew_members
end
As is the custom with fields_for, you also need to build the associated objects (if you're creating a new record) (you don't need to do this if editing):
#app/controllers/call_sheets_controller.rb
class CallSheetsController < ApplicationController
before_action :set_departments
def new
#callsheet = Callsheet.new
#callsheet.crew_members.build
end
def edit
#callsheet = Callsheet.find params[:id]
end
def update
#callsheet = Callsheet.find params[:id]
#callsheet.update callsheet_params
end
private
def set_departments
#departments = Department.where(production_id: current_user.default_working_production_id)
end
def callsheet_params
params.require(:callsheet).permit(crew_members_attributes: [:id, :firstname])
end
end
This will allow you to use:
<%= form_for #callsheet do |f| %>
<%= f.fields_for :crew_members do |crewmember| %>
<%= crewmember.label :firstname, "First Name" %><br />
<%= crewmember.text_field :firstname %>
<% end %>
<%= f.submit %>
<% end %>
--
When passing nested attributes through fields_for, you need several components:
The correct association in your parent model
An instantiated version of the associated model (#parent.build_child)
Correct fields_for definition
Passing correct parameters through your controller
I've outlined how to achieve the above, all of which you had incorrect.
You can also declare multiple validations in the same call:
#app/models/crew_member.rb
class CrewMember < ActiveRecord::Base
validates :firstname, :email, presence: true
end
Try changing
<%= f.fields_for :crewmember do |crewmember| %>
into
<%= f.fields_for :crewmember, #callsheet.crewmember || #callsheet.build_crewmember do |crewmember| %>
I am doing a jewel loan application using ruby 2.2.2p95 (2015-04-13 revision 50295) [i686-linux] and Rails 4.2.1 in that i am having two models:
1)jewelloan.rb
2)jltransaction.rb
I have added foreign key jewelloan_id to get the loan_amount in jltransactions table. Where as loan_amount is a field in jewelloans table.
My problem is foreign key relationship not working. I have searched many stackoverflow questions to solve this but that are not working.
I have attached my model,view,controller and everything. Please tell me where i did a mistake.
jewelloan.rb
class Jewelloan < ActiveRecord::Base
attr_accessor :transaction_amount
attr_accessible :transaction_amount
has_many :jltransactions, :dependent => :destroy
accepts_nested_attributes_for :jltransactions ,:allow_destroy => true
attr_accessible :account_number, :customer_name, :customer_address, :opened_on, :due_date, :amount, :jewel, :no_of_items, :gross_weight, :net_weight, :appraised_amount, :loan_amount, :transaction_mode, :transaction_type, :particulars, :comments, :close_date, :jltransactions_attributes
end
jltransaction.rb
class Jltransaction < ActiveRecord::Base
attr_accessor :loan_amount
attr_accessible :loan_amount
belongs_to :jewelloan
attr_accessible :transaction_date, :transaction_amount, :transaction_mode, :transaction_type, :particulars, :comments, :jewelloan_id
end
jewelloans_controller.rb
class JewelloansController < ApplicationController
def new
#jewelloan = Jewelloan.new
end
def create
#jewelloan = Jewelloan.create(jewelloan_params)
if #jewelloan.save
flash[:success] = "Special JL was successfully created"
redirect_to #jewelloan
else
flash[:danger] = "Special Jewel Loan was not created"
render 'new'
end
end
private
def jewelloan_params
params.require(:jewelloan).permit(:account_number, :customer_name, :customer_address, :amount, :interest_rate, :opened_on, :due_date, :amount_due, :jewel, :no_of_items, :gross_weight, :net_weight, :appraised_amount, :loan_amount, :transaction_mode, :transaction_type, :particulars, :comments, :close_date, :no_of_days, :jltransactions_attributes)
end
end
jltransactions_controller.rb
class JltransactionsController < ApplicationController
def new
#jltransaction = Jltransaction.new
#jewelloan = Jewelloan.new
end
def create
#jltransaction = Jltransaction.create(jltransaction_params)
#jewelloan = #jltransaction.jewelloans(jewelloan_params)
if #jltransaction.save
flash[:success] = "Transaction created"
redirect_to #jltransaction
else
flash[:danger] = "Transaction was not created"
render 'new'
end
end
private
def jltransaction_params
params.require(:jltransaction).permit(:transaction_date, :transaction_amount, :transaction_mode, :transaction_type, :particulars, :comments, :jewelloan_id)
end
end
app/views/jltransactions/_form.html.erb
<%= form_for #jltransaction do |jlt| %>
<%= jlt.hidden_field :jewelloan_id, :value => #jewelloan.id %>
<% if #jltransaction.errors.any? %>
<h2>Transaction Failed</h2>
<ul>
<% #jltransaction.errors.full_messages.each do |error| %>
<li><%= error %></li>
<% end %>
</ul>
<% end %>
<%= jlt.label :loan_amount %>
for<%= jlt.text_field :loan_amount, :disabled => true, :value => #jltransaction.jewelloan.try(:loan_amount) %>
<%= jlt.label :transaction_amount %>
<%= jlt.text_field :transaction_amount %>
<%= jlt.submit "Submit Transaction", class: "btn btn-success" %>
<% end %>
rails console
Completed 500 Internal Server Error in 34ms (ActiveRecord: 0.0ms)
ActionView::Template::Error (undefined method `loan_amount' for nil:NilClass):
Please give some ideas to work the foreign key.
Thanks...
Your relationship might be returning nil result.
Try
#jltransaction.jewelloan.try(:loan_amount)
You may try this:
<%= jlt.text_field :loan_amount, :disabled => true, :value => #jltransaction.jewelloan.try(:loan_amount) if #jltransaction && #jltransaction.jewelloan %>
My link_to in my view is going to a completely different "show.html.erb" than I'd like it to. I'm basically trying to understand why the "link_to #exhibit is linking to an "Investigation" profile. I think it may have to do with my routes file or the fact that its a "belong to" relationship...but can't seem to get it workin...what should that link_to be?
UPDATE: (AS PER BROIS QUESTION)
The missing misbehaving link_to is in the <%= link_to #exhibit do %> in show.html.erb
MY EXHIBIT.RB (MODEL)
class Exhibit < ActiveRecord::Base
attr_accessible :content, :investigation_id, :name, :user_id, :media, :media_html
belongs_to :investigation
has_many :categorizations
has_many :categories, :through => :categorizations
validates :name, presence: true, length: { maximum: 140 }
validates :content, presence: true
default_scope -> { order('created_at DESC') }
auto_html_for :media do
html_escape
image
youtube(:width => 400, :height => 250)
link :target => "_blank", :rel => "nofollow"
simple_format
end
MY EXHIBIT CONTROLLER:
class ExhibitsController < ApplicationController
include AutoHtml
def new
#exhibit = Exhibit.new
end
def show
#exhibit = Exhibit.find(params[:id])
end
def index
#exhibits = Exhibit.paginate(page: params[:page])
end
def create
#investigation = Investigation.find(params[:investigation_id])
#exhibit = #investigation.exhibits.create(params[:exhibit])
if #exhibit.save
flash[:success] = "You've successfully added etc etc..."
redirect_to investigation_path(#investigation)
else
render 'new'
end
end
end
MY ROUTES.RB
resources :sessions, only: [:new, :create, :destroy]
resources :investigations do
resources :players
end
resources :investigations do
resources :exhibits
end
LASTLY MY SHOW.HTML.ERB (INVESTIGATION PROFILE)
<% #investigation.exhibits.each do |exhibit| %>
<div class="row-fluid services_circles">
<%= link_to #exhibit do %>
<div class="media">
<div class="pull-left">
<%= exhibit.media_html %>
</div>
<div class="media-body">
<h4 class="media-heading"><%= exhibit.name %></h4>
<p><%= exhibit.content %></p>
</div>
</div>
<% end %>
<% end %>
ADDED THE INVESTIGATIONS CONTROLLER
class InvestigationsController < ApplicationController
def new
#investigation = Investigation.new
end
def show
#investigation = Investigation.find(params[:id])
end
def index
#investigations = Investigation.paginate(page: params[:page])
end
def create
#investigation = Investigation.new(params[:investigation])
if #investigation.save
flash[:success] = "You've successfully created..."
redirect_to #investigation
else
render 'new'
end
end
end
ADDED THE INVESTIGATION MODEL
class Investigation < ActiveRecord::Base
# belongs_to :user
has_many :players, dependent: :destroy
has_many :exhibits, dependent: :destroy
default_scope -> { order('created_at DESC') }
end
I appreciate the help...if i need to post any more info just let me know
IN YOUR : app/contorollers/exhibits_controller.rb
def show
#investigation = Investigation.find(params[:investigation_id])
#exhibit = Exhibit.find(params[:id])
end
IN YOUR : app/views/exhibits/show.html.erb
<%= link_to investigation_exhibit_path(#investigation, #exhibit) do %>
Maybe, I think.