Rails- How can I create view for nasted tables - ruby-on-rails

I want to get data like this in the show.html.erb , but it doesn't work.
How can I get data from spot table?
here is the code.
show.html.erb
<% #planaction.each do |action| %>
<hr>
<%= action.spot.name %>
<%= action.spot.description %>
<hr>
<%= action.title %>
<%= action.experience %>
<% end %>
plan.rb
class Plan < ActiveRecord::Base
has_many :plan_actions
end
plan_action.rb
class PlanAction < ActiveRecord::Base
belongs_to :plan
has_one :spot
end
spot.rb
class Spot < ActiveRecord::Base
belongs_to :plan_action
end
plan_actions_controller.erb
class PlanPagesController < ApplicationController
def show
#plan = Plan.find(params[:id])
#planaction = #plan.plan_actions
end
end
and error message here
undefined method `name' for nil:NilClass
and here is migration file for spot table.
class CreateSpots < ActiveRecord::Migration
def change
create_table :spots do |t|
t.integer :spot_id
t.integer :plan_action_id
t.string :name
t.text :description
t.time :time_open
t.time :time_close
t.date :dayoff
t.string :address
t.integer :tel
t.string :image
t.string :image2
t.string :image3
t.timestamps null: false
end
end
end

Looks good to me.
The issue is probably (can't be certain without seeing your logs) that the plan_action doesn't have an associated spot record.
To fix this, you should use some conditional logic:
<% #planaction.each do |action| %>
<hr>
<% if action.spot %>
<%= action.spot.name %>
<%= action.spot.description %>
<hr>
<% end %>
<%= action.title %>
<%= action.experience %>
<% end %>
Again, this is speculation. I wrote the answer because I felt it best to provide some sort of idea as to how to resolve it. The above should work.

I also think as Rich Peck that you don't have a record in spots table with plan_action_id corresponding to a plan action.
Following rails convention, I suggest the following:
class PlanAction < ActiveRecord::Base
belongs_to :plan
has_one :spot
delegate :name, :description, to: :spot, prefix: true, allow_nil: true
end
and in your view:
<%= action.spot_name %>
<%= action.spot_description %>
Finally, get your validations corrected. For example, if a plan_action should have a spot, then you need to use nested forms for both spot and plan action.

Related

How to query another tables when Loop a records collection?

I want to loop a collection of records, and check the answers status from another tables. The detail describle in the View part.
Model
# Quiz
class Quiz < ApplicationRecord
has_many :quiz_questions
has_many :questions, :through => :quiz_questions
has_many :quiz_details
end
# QuizDetail
class QuizDetail < ApplicationRecord
belongs_to :quiz
end
# QuizQuestion
class QuizQuestion < ApplicationRecord
belongs_to :quiz
belongs_to :question
end
Controller
# quiz_questions_controller.rb
def index
#questions = #quiz.questions
# #quiz_details = #quiz.quiz_details
end
DB
create_table "quiz_details", force: :cascade do |t|
t.integer "quiz_id"
t.integer "question_id"
t.integer "user_id"
t.boolean "is_correct", default: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
View
<ul>
<% #questions.each do |question| %>
<li>
# I want to check the answers status
# The status in the quiz_details table
# `is_correct` : true or false
<%= link_to question.title, quiz_question_path(#quiz, question) %>
</li>
<% end %>
</ul>
I want to know if there is a way to do this clearly?
I think you need to add some more associations to make this work smoothly. If I am reading your database table correctly, quiz_details also belongs to questions. You can add that association as follows:
Add to your Models
# Question
class Question < ApplicationRecord
has_many :quiz_details do
def by_quiz(quiz)
where(quiz_id: quiz.id)
end
end
end
# QuizDetail
class QuizDetail < ApplicationRecord
belongs_to :quiz
belongs_to :question
end
In your Controller
def index
# If you iterate over questions use this:
#questions = #quiz.questions.includes(:quiz_details)
# If you iterate over quiz_details use this:
#quiz_details = #quiz.quiz_details.includes(:question)
end
In your View
If you definitely need to iterate over questions:
<ul>
<% #questions.each do |question| %>
<li>
<%= question.quiz_details(#quiz).first.is_correct %>
<%= link_to question.title, quiz_question_path(#quiz, question) %>
</li>
<% end %>
</ul>
However, this will likely generate a nasty N+1 query that is inefficient. You can check your console to see if it does.
A better approach is to iterate over quiz_details if possible:
<ul>
<% #quiz_details.each do |detail| %>
<li>
<%= detail.is_correct %>
<%= link_to detail.question.title, quiz_question_path(#quiz, detail.question) %>
</li>
<% end %>
</ul>

Active record "date" and "nationality" function giving me error. (Undefined method)

I am trying to create a profile page where I can input "born_on". It will be using the
class CreateWineMakers < ActiveRecord::Migration
def change
create_table :wine_makers do |t|
t.string :name
t.date :born_on
t.text :nationality
t.text :profile
t.text :wine
t.integer :wine_list_id
t.timestamps
end
add_index :wine_makers, :wine_list_id
end
end
Here is my view file.
<%= simple_form_for WineMaker.new do |f| %>
<%= f.input :name %>
<%= f.input :profile %>
<%= f.input :wine %>
<%= f.input :born_on %>
<br/>
<%= f.submit "Create", :class => 'btn btn-primary' %>
<% end %>
The "born_on" is giving me error saying the method is not defined. I am confused since all other inputs are working except "born_on" and "nationality". Before, my "born_on" was named "birth_date", and I thought the naming convention was wrong and changed it to "born_on". Here is the controller.
class WineMakersController < ApplicationController
def new
#wine_maker = WineMaker.new
end
def create
#wine_maker = WineMaker.create(wine_maker_params)
redirect_to wine_list_path(#wine_list)
end
def show
end
private
def wine_maker_params
params.require(:wine_maker).permit(:name, :born_on, :nationality, :profile, :wine )
end
end
This seems like such an easy question that I couldn't find similar problems..
Thank you.

Rails ActiveRecord can't find method from many-to-many association

My application is pretty simple, I have User which can have many Videos and Video is many-to-many to Tag
Here's my model
class User < ActiveRecord::Base
def authenticate
return true
end
end
class Video < ActiveRecord::Base
belongs_to :user
end
class Tag < ActiveRecord::Base
end
class VideoTag < ActiveRecord::Base
belongs_to :video
belongs_to :tag
end
And here's my form
<%= form_for(#video, html: { class: "directUpload" }, multipart: true) do |f| %>
<% if #video.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#video.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #video.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :path %><br>
<%= f.file_field :path%>
</div>
<div class="field">
<%= f.label :tags %><br>
<%= f.text_field :tags %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
But I'm getting this error.
NoMethodError in Videos#new Showing
/Users/user/MyProjects/video-archiver/app/views/videos/_form.html.erb
where line #24 raised:
undefined method `tags' for #
How can I fix this?
UPDATE
class CreateVideos < ActiveRecord::Migration
def change
create_table :videos do |t|
t.string :title
t.string :path
t.references :user, index: true
t.timestamps null: false
end
add_foreign_key :videos, :users
end
end
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :title
t.timestamps null: false
end
end
end
class CreateVideoTags < ActiveRecord::Migration
def change
create_table :video_tags do |t|
t.references :video, index: true
t.references :tag, index: true
t.timestamps null: false
end
add_foreign_key :video_tags, :videos
add_foreign_key :video_tags, :tags
end
end
The Video model should look like:
class Video < ActiveRecord::Base
belongs_to :user
has_many :video_tags
has_many :tags, through: :video_tags
end
First of all, the relationship should be setup as follows.
class User < ActiveRecord::Base
has_many :videos
def authenticate
return true
end
end
This is because if a video belongs_to a user, and you said a user has many videos, this relationship makes more sense. And while lunr is not quite answering the question, same as I unfortunately, he is right on his answer as well.
My only answer for your question is that you should use :tag not :tags on line #24.
Without more info, I don't think I can help much more.
So here is the problem with your code as I see it. Below is the offending section of code.
<div class="field">
<%= f.label :tags %><br>
<%= f.text_field :tags %>
</div>
The reason is because :tags is not a field in your database. It's simply an object. In other words, look at your migrations below.
create_table :videos do |t|
t.string :title
t.string :path
Both :title and :path are columns in your database now for your video table. But, there is no column in your database for a :tags field. A tag in your database is an object/row of your database and does not represent a single field. Each tag has a :title...
create_table :tags do |t|
t.string :title
But there is no field for :tags or :tag or anything like it. This is why you are getting the error NoMethodError. What Ruby On Rails does, or more specifically Active Records does, is link database columns to getter and setter methods in your models. So, your video model has pre made setters and getters for your :title and :path fields that are setup in the background without you having to see it first hand. That's how your forms can see that your are filling in a #video object and your :title and :path are linked to those getters and setter magically. This happens for all columns for any table that has a model as well in RoR.
So, since you don't have a single editable field in your database called :tags, Ruby On Rails doesn't have a setter and getter for it to bind to your html form. Thus, when you try to call it, it complains and says it cannot find the method that by design of RoR should be there for the form to work.
So, my suggestion to you would be to redesign your database layout a bit as suggested by lunr and I and then keep the above in mind when doing it. This part of Ruby On Rails isn't really said clearly all the time. It's right in the documentation, but takes a bit to find and truly wrap you head around so most people I have seen make this mistake early on. Once you get comfortable with it though, it's amazing how handy it all really is.
Hope this helps!

Active Record Association Error - Undefined Method

I have the following line of code which seems to work okay.
<% current_user.blockedshows.map(&:tvshows).each_with_index do |blocked, index| %>
However, when I call it on blocked.title and image_tag(blocked.image), (full code below) I am getting the following error: undefined method title for <ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Tvshow:0x007fd4e24b9448>
View
<%= blocked.title %>
<%= image_tag(blocked.image) %> </br>
Tweets containing the following keywords will be removed from your timeline: </br>
<%#keywords = blocked.phrases.map(&:text) %>
<%=#keywords %> </br>
Blockedshow Model
class Blockedshow < ActiveRecord::Base
has_many :tvshows
belongs_to :user
end
Tvshow Model
class Tvshow < ActiveRecord::Base
has_many :phrases
belongs_to :blockedshow
end
Tvshow Table
class CreateTvShows < ActiveRecord::Migration
def change
create_table :tvshows do |t|
t.string :title
t.string :image
t.timestamps
end
end
end
That's because tvshows itself is an ActiveRecord association object.
You need to loop over it also:
current_user.blockedshows.map(&:tvshows).each_with_index do |blocked, index|
blocked.each do |b|
<%= b.title %>
end
end

How do I create a select box using two tables with a relationship?

I'm trying to create a select box that shows all my ejecutive_name and last_name from my table Ejecutives in my Policies view,but i need to create a search button to get parameters from Ejecutives that i selected
My models have a relationship:
class Policy < ActiveRecord::Base
unloadable
belongs_to :ejecutive
has_many :policy
end
class Ejecutive < ActiveRecord::Base
has_many :policies
end
My tables have a relationship by ejecutive_id:
class CreateEjecutives < ActiveRecord::Migration
def self.up
create_table :ejecutives do |t|
t.string :name,:null=>false
t.string :lastname1,:null=>false
t.timestamps
end
end
def self.down
drop_table :ejecutives
end
end
class CreatePolicies < ActiveRecord::Migration
def self.up
create_table :policies do |t|
t.string :num_policy, :null=>false
t.integer :ejecutive_id
t.timestamps
end
end
def self.down
drop_table :policies
end
end
This is my controller:
class PolicyManagement::PolicyController < ApplicationController
#ejecutives = Ejecutive.find(:all)
#policies = Policy.find(:all)
end
This is my view:
Select Ejecutive:
%= select_tag 'ejecutives',"<option value=\"\">Seleccione</option>"+options_for_select(#ejecutives.collect {|t| [t.name.to_s+" "+t.lastname1.to_s,t.id]})%>
Results
<% #policies.each do |policy| %>
<p> <%= policy.num_policy%> </p>
<p> <%= policy.ejecutive.name %> </p>
<p> <%= policy.ejecutive.last_name %> </p>
<% end %>
I tried this
<% form_tag :controller=>"policy_management/policy",:action =>"generate_print_ejecutive_comercial", :method => 'get' do %>
<p>
<%= text_field_tag :search,params[:search] %>
<%= select_tag "Ejecutives", options_from_collection_for_select(#ejecutives, "id", "name") %>
#Here i in select_tag "ejecutives" need to add searh params..
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
I'm using Rails 2.3.5.
Does somebody know about this problem? I'd really appreciate help.
If i understand correctly, you want the policies for a selected ejecutive, you can do this by saying Ejecutive.find().policies. If want a search button, put your select box in a form tag and post it. In the controller action, you will get the selected id, with which you can execute the line i mentioned above.Hope this helps.

Resources