Active Record Association Error - Undefined Method - ruby-on-rails

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

Related

Error in foreign key association in Rails

I have two models:
user.rb
class User < ActiveRecord::Base
...
has_many :reports, :foreign_key => "assigned_user_id"
...
end
report.rb
class Report < ActiveRecord::Base
belongs_to :assigned_user, :class_name => "User"
end
index action
def index
#all_reports = Report.all
end
index.html.erb
<% #all_reports.each do |report| %>
<%= report.user.email %> </br>
<% end %>
This throws me the error:
undefined method `user' for #<Report:0x007f90dc642e80>
What am I missing? My other - standard rails - associations work perfectly.
Change this line:
<%= report.user.email %> </br>
To:
<%= report.assigned_user.email %> </br>

Rails- How can I create view for nasted tables

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.

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!

RAILS 4 - How to show NAME instead of ID in index view?

rails newbie here.
I want my questions/view/index to show the name of the language associated with a question, rather than the language_id.
My question model is:
class Question < ActiveRecord::Base
validates :phrase, presence: true
has_many :answers, dependent: :delete_all
belongs_to :language
end
class CreateQuestions < ActiveRecord::Migration
def change
create_table :questions do |t|
t.string :phrase
t.string :language
t.timestamps
end
end
end
class AddLanguageIdToQuestions < ActiveRecord::Migration
def change
add_column :questions, :language_id, :integer
end
end
My language model is:
class Language < ActiveRecord::Base
end
class CreateLanguages < ActiveRecord::Migration
def change
create_table :languages do |t|
t.string :name
t.timestamps
end
end
end
In my questions controller:
def index
#questions = Question.all
#language = Language.find(#questions.language_id)
end
In the questions/_form.html.erb:
<p>
<%= f.label :language_id %><br>
<%= f.select :language_id, #languages.map { |l| [l.name, l.id] }, {:prompt => 'select language'} %>
</p>
And in the questions/view/index.html.erb:
<% #questions.each do |question| %>
<li>"<%= link_to question.phrase, question %>" in <%= question.language.name %>?%></li>
<% end %>
The error I keep getting, despite trying several variations of "question.language.name" (which works just fine in the show view) is "undefined method "language_id" in the index view.
Any help would be very much appreciated.
just change your index action to:
def index
#questions = Question.all.includes(:language)
end
edit
<% #questions.each do |question| %>
<% unless question.language.nil? %>
<li>"<%= link_to question.phrase, question %>" in <%= question.language.name %>?%></li> <% end %>
<% end %>
OR
<% #questions.each do |question| %>
<li>"<%= link_to question.phrase, question %>" in <%= question.language.name unless question.language.nil? %>?%></li>
<% end %>
Both will work fine depends on you what do you want.
feel free to ask if problem continues or not solved.
Your Problem
What you were doing wrong was:
finding all questions and then this line was wrong finding all question's language at once.
#language = Language.find(#questions.language_id)
And to avoid this: better solution is to avoid N + 1 query problem using includes
ActiveRecord Associations
This sounds like a job for ActiveRecord Associations, specifically the has_many association:
ActiveRecord associations basically use a foreign_key in your database to pull relational data & append to your object. Currently, you're only focused on using a single object, without any associated data.
--
Your problem can be fixed using the following:
#app/models/question.rb
Class Question < ActiveRecord::Base
belongs_to :language
end
#app/models/language.rb
Class Language < ActiveRecord::Base
has_many :questions
end
This will allow you to call the following in your controller & view:
#app/controllers/questions_controller.rb
Class QuestionsController < ApplicationController
def index
#questions = Question.all
end
end
#app/views/questions/index.html.erb
<% #questions.each do |question| %>
<%= question.language.name %>
<% end %>
--
Bonus
You can use the .delegate method to provide you with the ability to stop the law of dementer issue:
#app/models/question.rb
Class Question < ActiveRecord::Base
belongs_to :language
delegate :name, to: :language, prefix: true #-> #question.language_name
end
#questions.language_id is incorrect because you are trying to retrieve a single id from an array. i.e. Question.all returns an array. Also, Language.find requires a single id parameter to return a single language.
What exactly are you trying to return with Language.find(#questions.language_id) ? An array of languages that have a question that belong to it?
Also, where is the _form.html.erb partial called? By default, rails scaffold will call the partial in the new and edit actions and therefore if you are trying to set #languages for the select field in the form partial, then you would not do it in the index action. Also, Consider using a collection select for this field as it is for an association.

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