I have a class called #Subdomain:
Here is my controller:
class SubdomainsController < ApplicationController
before_action :authenticate_user!, only: [:edit, :update]
before_action :set_subdomain, only: [:show, :edit, :update, :destroy]
before_action :redirect_to_subdomain, only: :show
before_action :redirect_to_subdomain_show, only: :root, unless: '#subdomain.nil?'
def root
render nothing: true
end
def index
#subdomains = Subdomain.all
end
def show
end
def new
#subdomain = Subdomain.new
end
def edit
end
def create
#subdomain = Subdomain.new(subdomain_params)
respond_to do |format|
if #subdomain.save
format.html { redirect_to #subdomain, notice: 'Subdomain was successfully created.' }
format.json { render :show, status: :created, location: #subdomain }
else
format.html { render :new }
format.json { render json: #subdomain.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #subdomain.update(subdomain_params)
format.html { redirect_to #subdomain, notice: 'Subdomain was successfully updated.' }
format.json { render :show, status: :ok, location: #subdomain }
else
format.html { render :edit }
format.json { render json: #subdomain.errors, status: :unprocessable_entity }
end
end
end
def destroy
#subdomain.destroy
respond_to do |format|
format.html { redirect_to subdomains_url, notice: 'Subdomain was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def redirect_to_subdomain_show
redirect_to subdomain_url(#subdomain) if #request_subdomain.eql? #subdomain.address
end
# Redirect to subdomain... if the current one isn't equal to #subdomain.address column
def redirect_to_subdomain
redirect_to subdomain_url(#subdomain, subdomain: #subdomain.address) unless #request_subdomain.eql? #subdomain.address
end
def set_subdomain
#subdomain = Subdomain.find(params[:id])
end
def subdomain_params
#subdomain.assign_attributes(tag_speciality: params[:subdomain][:tag_speciality].split(','))
params.require(:subdomain).permit(
:domain_id,
:address,
:title,
:description,
:is_published,
:button_text_client,
:button_text_service,
:cover,
:primary_colour,
:secundary_colour,
:contrast_colour,
:logo,
:find_clients,
:find_professional,
:start_relation,
:publications_wall,
:tag_speciality,
:cards_wall
)
end
end
On the view i created a condition:
<% if (!#subdomain.id.blank?) %>
<li>
<%= link_to cards_from_subdomain_path(subdomain_id: #subdomain.id) do %>
<i class="fa fa-search fa-lg"></i>
<span class="hidden-medium">
  <%= #subdomain.cards_wall %>
</span>
<% end %>
</li>
<li>
<%= link_to publications_from_subdomain_path(subdomain_id: #subdomain.id) do %>
<i class="icon-grid fa-lg"></i>
<span class="hidden-medium">
  <%= #subdomain.publications_wall %>
</span>
<% end %>
</li>
<% else %>
<li>Some thing</li>
<% end %>
Here is the model:
class Subdomain < ActiveRecord::Base
belongs_to :domain
has_many :cards
mount_uploader :cover, AssetsUploader
mount_uploader :logo, AssetsUploader
end
When the #subdomain exist is ok, everything works fine, but when it doesn't exist, i get this error message:
NoMethodError in Subdomains#index
undefined method `id' for nil:NilClass
<% if (!#subdomain.id.blank?) %>
What could i do to fix that? thanks
The quick and dirty solution would be to use #try (not recommended though)
<% if !#subdomain.try(:id).try(:blank?) %>
By the way, you can use #present? instead of negating a #blank? to make code more readable.
However, if I assume correctly and the #subdomain is an ActiveRecord model, you don't need to check if it's id is present. A following code should be sufficient in your case:
<% if #subdomain %>
(...)
<% else %>
(...)
<% end %>
If the #subdomain is not found, it will be a nil anyway - and then the if #subdomain condition will be evaluated as false - since nil is a falsy value.
And if you get this error because you happen to be rendering a collection like this:
= render 'subdomain', collection: #subdomains
...then you can just put that inside a condition...
<% if #subdomains.present? %>
= render 'subdomain', collection: #subdomains
<% else %>
<% # #subdomains are an empty collection %>
<% end %>
From your create action, id will definitely be created in your table. I don't still understand what you are trying to get to, for negating on #id.blank?.
Change the first line from your view. i.e.
<% if (!#subdomain.id.blank?) %>
to,
<% if #subdomains %>, which will definitely return all attributes on your Subdomain Table since its has being taken care of in your index action.
Another thing I do is wrap my if...else statement inside a loop, such the your view becomes:
<% #subdomains.each do |subd| %>
<% if subd.id.present? %> #you can use another attribute here instead of id. e.g. <% if subd.is_published == true %> since `is_published` is a boolean.
<li>
(#your codes here referenced with the format called `subd.whatever_attribute`)
</li>
<li>
(#your codes here referenced with the format called `subd.whatever_attribute`)
</li>
<% else %>
<li>Some thing</li>
<% end %>
<% end %>
Related
Am relatively new to Rails and have run into a problem I can't seem to solve.
I have setup a nested resource Model called Captable. It belongs_to a Company.
If I navigate to a certain view: for example http://localhost:3000/companies/9/captables/1 - everything works great. I see the right data.
I have 2 core problems I can't seem to solve, that I think have something to do with either naming conventions or routes.
Firstly, when I try access http://localhost:3000/companies/9/captables/new - I get the following error.
NoMethodError in Captables#new
Showing /Users/jamespember/calmcap/app/views/captables/_form.html.erb where line #2 raised:
undefined method `captables_path' for #<#<Class:0x00007f8a08edebc8>:0x00007f8a0984bfa8>
Extracted source (around line #2):
1
2
3
4
5
6
<%= form_with(model: #captable, local: true) do |form| %>
<% if #captable.errors.any? %>
<div id="error_explanation">
<h2>
Secondly - if I try link to link to the company_captables_pathfrom the /companies/ page by using the below, I get the following error.
View Cap Table: <%= link_to(#company.company_captables_path) %>
Error:
Showing /Users/jamespember/calmcap/app/views/companies/show.html.erb where line #30 raised:
undefined method `company_captables_path' for #<Company:0x00007f8a046a6630>
Here's some code snippets:
routes.rb
Rails.application.routes.draw do
devise_for :users
get 'dashboard/index'
root 'companies#index'
resources :companies do
resources :shareholders
resources :captables
end
end
captable.rb
class Captable < ApplicationRecord
belongs_to :company
end
captables_controller.rb
class CaptablesController < ApplicationController
before_action :set_captable, only: [:show, :edit, :update, :destroy]
def index
#captables = Captable.all
end
def show
#captable = Captable.find(params[:id])
end
def new
#captable = Captable.new
end
def edit
end
def create
#captable = Captable.new(captable_params)
respond_to do |format|
if #captable.save
format.html { redirect_to #captable, notice: 'Captable was successfully created.' }
format.json { render :show, status: :created, location: #captable }
else
format.html { render :new }
format.json { render json: #captable.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #captable.update(captable_params)
format.html { redirect_to #captable, notice: 'Captable was successfully updated.' }
format.json { render :show, status: :ok, location: #captable }
else
format.html { render :edit }
format.json { render json: #captable.errors, status: :unprocessable_entity }
end
end
end
def destroy
#captable.destroy
respond_to do |format|
format.html { redirect_to captables_url, notice: 'Captable was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_captable
#captable = Captable.find(params[:id])
end
def captable_params
params.require(:captable).permit(:version, :name, :company_id)
end
end
captables/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Version:</strong>
<%= #captable.version %>
</p>
<p>
<strong>Name:</strong>
<%= #captable.name %>
</p>
<p>
<strong>Company:</strong>
<%= #captable.company_id %>
</p>
captables/_form.html.erb - EDIT Updated
<%= form_with(model: [#company, #captable], local: true) do |form| %>
<% if #captable.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#captable.errors.count, "error") %> prohibited
this article from being saved:
</h2>
<ul>
<% #captable.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= form.submit %>
</p>
<% end %>
schema.rb
Here's the schema for the table:
create_table "captables", force: :cascade do |t|
t.integer "version"
t.text "name"
t.integer "company_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Lastly, here's a screenshot of my rails routes.
Error when trying to access /companies/:id/captables/new
The rails route helper methods are added to the view context and controller - not models.
The link should read:
<%= link_to("Link text", company_captables_path(#company)) %>
Which is an implicit call to to:
<%= link_to("Link text", self.company_captables_path(#company)) %>
self being the view context.
When creating a form for a nested route you should pass an array:
<%= form_with(model: [#company, #captable], local: true) do |form| %>
# ...
<% end %>
You should also create the new instance from the assocation:
class CaptablesController < ApplicationController
before_action :set_company
before_action :set_captable, only: [:show, :edit, :update, :destroy]
# GET /companies/:company_id/captables/new
def new
#captable = #company.captables.new
end
# POST /companies/:company_id/captables
# POST /companies/:company_id/captables.json
def create
#captable = #company.captables.new(captable_params)
respond_to do |format|
if #captable.save
format.html { redirect_to #captable, notice: 'Captable was successfully created.' }
format.json { render :show, status: :created, location: #captable }
else
format.html { render :new }
format.json { render json: #captable.errors, status: :unprocessable_entity }
end
end
end
private
def set_company
#company = Company.find(params[:company_id])
end
# ...
end
I am trying to improve an exercice that I did on treehouse, the idea was to remake a little version of facebook thing, where users could publish statuses.
Now I want that a user can comment any statuses... And I am kinda lost...
The idea is to have all on the same page (if possible?, like on the real facebook)
So the comment form and the "displaying" content...
I hope anyone could help me :)
This is my github repository
I think I haven't understand how to call variables from a controller to another...
If someone could explain me with very easy words ... I am not native english speaker... so sometime it's difficult..
Here are the statuses part
controllers/statuses_controller/rb
class StatusesController < ApplicationController
before_filter :authenticate_user!, only: [:new, :create, :edit, :update]
before_action :set_status, only: [:show, :edit, :update, :destroy]
def index
#statuses = Status.all
#comments = Comment.all
end
def show
#status = Status.find(params[:id])
#comments = #status.comments.all
end
def new
#status = Status.new
#comment = #status.comments.build
end
def create
#status = Status.new(status_params)
#status.user = current_user
respond_to do |format|
if #status.save
format.html { redirect_to #status, notice: 'Status was successfully created.' }
format.json { render :show, status: :created, location: #status }
else
format.html { render :new }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #status.update(status_params)
format.html { redirect_to #status, notice: 'Status was successfully updated.' }
format.json { render :show, status: :ok, location: #status }
else
format.html { render :edit }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
def destroy
#status.destroy
respond_to do |format|
format.html { redirect_to statuses_url, notice: 'Status was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_status
#status = Status.find(params[:id])
end
def status_params
params.require(:status).permit(:user_id, :content, :comments_attribute[:id, :status_id, :content])
end
end
models/status.rb
class Status < ActiveRecord::Base
belongs_to :user
has_many :comments
default_scope -> { order(created_at: :DESC)}
validates :content, presence: true,
length: {minimum: 2}
validates :user_id, presence: true
end
views/comments/_form.html.erb I create a render in my index below:
<% simple_form_for #status.comments do |f|%>
<%= f.input :content %>
<%= f.button :submit %>
<% end %>
view/statuses/index.html.erb
<div class="page-header">
<h1>All of the Statuses</h1>
</div>
<%= link_to "Post A New Status", new_status_path, class: "btn btn-success"%>
<br>
<br>
<% #statuses.each do |status| %>
<div class="status">
<div class="row">
<div class="col-xs-1 avatar">
<%= image_tag status.user.avatar.thumb if status.user.avatar?%>
</div>
<div class="col-xs-7">
<h4><%= status.user.full_name%></h4>
</div>
</div>
<div class="row">
<div class="col-xs-8">
<p><%= simple_format(status.content) %></p>
</div>
</div>
<div class="row">
<div class="col-xs-8">
<%= link_to time_ago_in_words(status.created_at) + " ago", status %>
<% if status.user == current_user %>
<span class="admin">
| <%= link_to "Edit", edit_status_path(status) %> |
<%= link_to "Delete", status, method: :delete, data: {confirm: "Are you sure?"} %>
</span>
<% end %>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<p>Comments</p>
<% #comments.each do |comment| %>
<%= comment.content %>
<% end %>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<%= render "comments/form" %>
</div>
</div>
</div>
Now the comments part:
model/comment.rb
class Comment < ActiveRecord::Base
belongs_to :status
belongs_to :user
end
controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
#comment = Comment.new(params_comment)
end
def index
#statuses = Status.all
#comments = Comment.all
#comment = Comment.find_by(params[:id])
end
private
def params_comment
params.require(:comment).permit(:content)
end
end
routes.rb
resources :statuses do
resources :comments
end
user.rb
that's a part of what I have in there
has_many :statuses
has_many :comments
your comments creation method should look like this:
#status = Status.find(params[:status_id])
#comment = #status.comments.create(comment_params)
#comment.user_id = current_user.id if current_user
#comment.save
This my first ruby on rails application.
Model Location and Post, Location has many post.I create location as tree structure with ancestry gem.
class Post < ActiveRecord::Base
belongs_to :location, :counter_cache => true
end
class Location < ActiveRecord::Base
include Tree
has_ancestry :cache_depth => true
has_many :posts
end
This my Post Controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
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 action: 'show', status: :created, location: #post }
else
format.html { render action: '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 { head :no_content }
else
format.html { render action: '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 }
format.json { head :no_content }
end
end
private
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(:name, :location_id)
end
end
Creating Post with location in Post _form.html.erb
<%= simple_form_for #post do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved: </h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.input :name %>
<%= f.select :location_id, Location.all.at_depth(4) { |l| [ l.name, l.id ] } %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My question are
First question- f.select :location_id , how display location name, not location id, i am using with simple form
Second question- Post index got error in <%= post.location.name %>
<% #posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= post.location.name %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %> </td>
</tr>
<% end %>
First question:
Check the simple_form syntax for a dropdown. It is mentioned in the docs and you should be able to get this working by yourself.
Second question:
Does the offending post really have a related location? If it does not have one, it can not display the name of course. To counter these nil errors, use try:
<%= post.location.try(:name) %>
try will call the method name on location only if location is not nil.
For your first question :
Maybe you should read about "options_for_select"
http://guides.rubyonrails.org/form_helpers.html#option-tags-from-a-collection-of-arbitrary-objects
<% cities_array = City.all.map { |city| [city.name, city.id] } %>
<%= options_for_select(cities_array) %>
For your second question:
What is your error ?
Maybe one of your "post.location" is nil.
If so, try:
post.location.name unless post.location.nil?
Hope this can help
My Rails application have two model. Location and Post, Location have many post.I am Using
ancestry gem.
class Post < ActiveRecord::Base
belongs_to :location, :counter_cache => true
end
class Location < ActiveRecord::Base
include Tree
has_ancestry :cache_depth => true
has_many :posts
end
My Post Controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
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 action: 'show', status: :created, location: #post }
else
format.html { render action: '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 { head :no_content }
else
format.html { render action: '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 }
format.json { head :no_content }
end
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(:name)
end
end
If i am create new Post with which Location belongs in _form.html.erb
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved: </h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<%= select :location_id, Location.all.at_depth(4) { |l| [ l.name, l.id ] } %>
<div class="actions">
<%= f.submit %>
</div>
Browser show error message which is display bellow
ArgumentError in Posts#new
Not sure if this fixes your error, but:
To make the dropdown working, change the select line to:
<%= f.select :location_id, Location.all.at_depth(4) { |l| [ l.name, l.id ] } %>
This is because you want the formbuilder f to handle the creation of the form element.
You also have to whitelist the :location_id parameter in the controller:
def post_params
params.require(:post).permit(:name, :location_id)
end
I'm trying to add answers to questions. Each questions has_one answer. I'm showing them on the comment page through partials except I keep getting this error:
undefined local variable or method `answer'
Here is part of my answers_controller.rb
class AnswersController < ApplicationController
before_action :set_answer, only: [:show, :edit, :update, :destroy]
def index
#question = Question.find params[:question_id]
#question.answers
end
def show
end
def new
#question = Question.find params[:question_id]
end
def edit
end
def create
#question = Question.find(params[:question_id])
#answer = #question.answers.create(answer_params)
respond_to do |format|
if #answer.save
format.html { redirect_to #comment, notice: 'Answer was successfully created.' }
format.json { render action: 'show', status: :created, location: #answer }
else
format.html { render action: 'new' }
format.json { render json: #answer.errors, status: :unprocessable_entity }
end
end
end
Here is my _question.html.erb partial where the answer partial is called:
<%=div_for(question) do %>
<div class="questioncontainer">
<p>
<%= question.body %>
<%= render :partial => #question.answers %>
<% if current_user == #comment.user %>
<div class="answercontainer">
<%= link_to 'Answer', new_question_answer_path(question)%>
</div>
</div>
</p>
<% end %>
<% end %>
Last, here is my _answer.html.erb partial:
<%=div_for(answer) do %>
<div class="questioncontainer">
<p>
<%= answer.body %>
</p>
</div>
<% end %>
Thanks for the help :)
Pass answer as local, via locals: {answer: #answer}
Use
<%= render question.answers %>
instead of
<%= render :partial => #question.answers %>
More info here: http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials