I'm facing the issue
undefined local variable or method `student_details'
while trying to write a Ruby method that gives dynamic data to display in the browser. I've used view_component gem.
My "component.rb" file looks like following:
module Shared
module Student
class Component < ViewComponent::Base
def initialize(title:)
#title = title
end
student_details = {name: "John Doe", course: "Rails Development", student_id: "1"}
end
end
end
And "component.html.erb" looks as:
<div class="font-montserrat flex flex-col bg-white text-shadow-none">
<%= student_details.student_id %>
<%= student_details.name %>
<%= student_details.course %>
</div>
Related
I'm using chartkick to create some line charts to visualize data in my Rails app. At the moment, however, it shows ALL of the data in my database. Obviously this isn't always ideal. I'd like to give the user the ability to specify the date range of the data shown. I would use the created_at value of the record.
I cannot find any instructions in the documentation on how to do this.
https://github.com/ankane/chartkick.js?files=1
I have created a date picker which will give me a URL like http://localhost:3000/metrics?utf8=%E2%9C%93&search%5Bdate_from%5D=2019-11-01&search%5Bdate_to%5D=2019-11-17&commit=Search
Can chartkicker somehow access those parameters?
In my code a Club has many DailyMetrics, and I've created a metrics action in the clubs controller.
View
<%= javascript_include_tag "https://google.com/jsapi" %>
<div class="row">
<h1>Metrics</h1>
<div class="pull-right range-query">
<%= form_tag metrics_path, method: :get do %>
<%= text_field_tag 'search[date_from]', #search.date_from %>
<%= text_field_tag 'search[date_to]', #search.date_to %>
<%= submit_tag 'Search', class: 'btn search-button' %>
<% end %>
</div>
</div>
<h3>Total active students</h3>
<%= line_chart #club.daily_metrics.group(:created_at).sum(:total_active_students), library: { animation: { easing: 'easeOutQuad'}} %>
<h3>Lost students</h3>
<%= line_chart #club.daily_metrics.group(:created_at).sum(:lost_students), library: { animation: { easing: 'easeOutQuad'}} %>
<h3>New students</h3>
<%= line_chart #club.daily_metrics.group(:created_at).sum(:new_students), library: { animation: { easing: 'easeOutQuad'}} %>
Controller
def metrics
#club = current_club
#search = MetricSearch.new(params[:search])
#metrics = #search.scopeContr
end
Model for searching for metrics
class MetricSearch
attr_reader :date_from, :date_to
def initialize(params)
params ||= {}
#date_from = parsed_date(params[:date_from], 7.days.ago.to_date.to_s)
#date_to = parsed_date(params[:date_to], Date.today.to_s)
end
def scope
DailyMetric.where('created_at BETWEEN ? AND ?', #date_from, #date_to)
end
private
def parsed_date(date_string, default)
Date.parse(date_string)
rescue ArgumentError, TypeError
default
end
end
Is what I'm trying to do possible?
I posted a link to an great article in your comments, but you can use a gem called gem 'groupdate' as well.
# Gemfile
gem 'groupdate'
Assume your user model has_many :orders and you want to find out their spending over the past 6 month:
# order.rb
def self.monthly_spending
group_by_month(:date, last: 6, current: false).sum('orders.total')
end
In your view:
<%= line_chart current_user.orders.monthly_spending %>
Here is another tutorial how to group by date with chartkick and groupdate gem.
If you want to preselect a from-to-date for query you can setup a datepicker in your frontend and send the params to your controller
def show
orders = Order.where('created_at > %s AND created_at < %s', params[:start_date], params[:end_date])
end
call like above the group_by methods on your prefiltered list of orders.
Hopefully I get all the terminology right here - if not please forgive, still very new.
I am working on a course project #Bloc and am having trouble with adding a list of collaborators to my index view for a different controller.
What I am trying to achieve is:
Show all user wikis - working.
Show all wikis where user is listed as a collaborator (link created through a join table and has_many through reference.)
My index view looks like: (/wikis/index)
<h1>My Wikis</h1>
<% if policy(Wiki.new).create? %>
<%= link_to "New Wiki", new_wiki_path, class: 'btn btn-success' %>
<% end %>
<% #wikis.each do |wikis| %>
<div class="media">
<div class="media-body">
<h4 class="media-heading">
<%= link_to wikis.title, wikis %>
</h4>
<small>
Created <%= time_ago_in_words(wikis.created_at) %> ago by <%= wikis.user.name %><br/>
</small>
</div>
</div>
<% end %>
<h1>My Collaborations</h1>
<% #collaborations.each do |collaborations| %>
<div class="media">
<div class="media-body">
<h4 class="media-heading">
<%= link_to collaborations.title, collaborations %>
</h4>
</div>
</div>
<% end %>
<%= will_paginate #wikis %>
My Wikis controller looks like: (shortened)
class WikisController < ApplicationController
respond_to :html, :js
def index
# #user = current_user
#wikis = current_user.wikis.paginate(page: params[:page], per_page: 10)
##collaboration = #wiki.collaboration.build(collaboration_params)
#collaborations = #collaboration.where(:user_id == current_user)
authorize #wikis
end
def show
#wikis = Wiki.friendly.find(params[:id])
if request.path != wiki_path(#wikis)
redirect_to #wikis, status: :moved_permanently
authorize #wikis
end
end
end
private
def collaboration_params
params.require(:collaboration).permit(:user_id, :wiki_id)
end
end
From the Rails Console - I can see that my collaboration relationship is working as expected - I just cannot quite figure out what the syntax is I should be using to make it render on my index view.
2.0.0-p481 :022 > Collaboration.last
Collaboration Load (1.9ms) SELECT "collaborations".* FROM "collaborations" ORDER BY "collaborations"."id" DESC LIMIT 1
log writing failed. Protocol error - /home/vagrant/code/blocipedia/log/development.log
=> #<Collaboration id: 3, user_id: 1, wiki_id: 16>
2.0.0-p481 :023 >
Any pointers would be greatly appreciated. I've tried what feels like about 100 different combinations to figure this out.
Right now the error I trigger on index view is:
undefined method `where' for nil:NilClass
Cheers
Kevin.
Object
The simple error you have is here:
#collaborations = #collaboration.where(:user_id == current_user)
The error here is that you're calling .where on a variable which has not been populated (defined).
Ruby / Rails works somewhat differently to other languages, in that it's object orientated. This means that each time Rails calls an "object", it will actually be defined, just not populated.
As a rule of thumb, the no method error is generally (although not always) a result of the system having not populated the variable correctly.
Model
The way to fix this is very simple -
You just need to be able to declare the #collaboration object before calling the .where method: on it. However, as you're using the .build method to define this object, you're not going to get anywhere.
Essentially, when you perform a .where lookup, you'll be using ActiveRecord to ping the datatables in the backend, populating an object with the various attributes from the Model (look up MVC programming pattern for more about this)
What you need to do (if you want to call .where) is create an instance of the model you wish to query inside the database. To do this, you either have to call the model directly, or through an associative object:
def index
#wikis = current_user.wikis.paginate(page: params[:page], per_page: 10)
#collaborations = Collaboration.where(user_id: current_user.id)
authorize #wikis
end
System
As you're new to Rails, let me give you some details on how to make the system work properly.
Firstly, you need to appreciate the role of ActiveRecord Associations - these are built on the ActiveRecord pattern, making it much simpler to build "objects" around database-driven data
In short, if you associate two or more objects with ActiveRecord, it means you can call the associative data through the primary object:
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :collaborations
end
#app/models/collaboration.rb
Class Collaboration < ActiveRecord::Base
belongs_to :user
end
This means that instead of calling #collaborations = Collaboration.where(user_id: current_user.id), you'll simply be able to call#collaborations = current_user.collaborations`
Fix
The fix should be as follows:
#app/views/wiki/index.html.erb
...
<% current_user.collaborations.each do |collaboration| %>
<div class="media">
<div class="media-body">
<h4 class="media-heading">
<%= link_to collaboration.title, collaboration %>
</h4>
</div>
</div>
<% end %>
#app/controllers/wikis_controller.rb
Class WikisController < ApplicationController
def index
#wikis = current_user.wikis.paginate(page: params[:page], per_page: 10)
authorize #wikis
end
end
Just installed the elasticsearch gem and been configuring it.
I got the search working on the right model. However on the view I also include data from an associated database model called company and it gives me this error:
undefined method `company' for #<Elasticsearch::Model::Response::Result:0x000001032d67d0>
If I try to remove everything related to that associated database in the view, the search works perfectly. So it's just the problem of figuring this out.
My model for application.rb looks like this:
require 'elasticsearch/model'
class Application < ActiveRecord::Base
belongs_to :company
has_many :answers
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
....
my class where I display it (searches_controller.rb:
def index
#application = Application.search(params[:query])
end
and finally the index.html.erb file:
<%= form_tag search_startup_path, method: :get do %>
<p>
<%= text_field_tag :query, params[:query] %>
<%= submit_tag "Search", name: nil %>
</p>
<% end %>
<hr>
<% #application.each do |f| %>
<h2><%= f.company.name %> is looking for a <%= f.work_type %></h2>
<%= image_tag f.company.avatar(:medium), alt:"#{f.company.name.pluralize} logo", height:"100", width:"100" %>
<p><%= link_to "Visit #{f.company.name.pluralize} website", f.company.website, rel: "nofollow" %></p>
<p>Company located in: <%= f.company.city %>, <%= f.company.country %></p>
<p>Required to be on location: <%= f.location %> </p>
<% end %>
So viewing the associated company database without elasticsearch works fine. So there is no error there, again I'm just unsure how to enable elasticsearch to view the ass. model
New elastic search library returns only data from elasticsearch and wraps it into Hashie::Mash gem. So you working only with Elasticsearch::Model::Response::Result class. If you want to work with ActiveRecord your index action have to look like this:
def index
#application = Application.search(params[:query]).records
end
records method returns collection of ActiveRecord models, you can find more info on github read me https://github.com/elasticsearch/elasticsearch-rails/tree/master/elasticsearch-model#search-results-as-database-records
I have a controller that POSTs a new instance of a model into a database after the user fills out a form. This form is created using an each do that loops over a series of inventory items defined in the Application Controller.
In other words, this is the view code:
<%= form_for #requestrecord, :html=> {:id => 'form'} do |f| %>
<div class="col-xs-12">
<p><b>Items we have available</b></p>
</div>
<% #inventory.each do |category, list| %>
<div class="col-xs-2">
<div class="form-group box">
<h5> <%="#{category}"%> </h5>
<% list.each do |thing| %>
<%= f.check_box(:items, {:multiple => true}, "#{thing}") %>
<%= f.label(:items, "#{thing}") %>
</br>
<% end %>
</div>
</div>
<% end %>
There is a method in the application controller that defines inventory:
def inventory
#inventory = { some hash }
end
And then this method is called in the Requests controller that I'm trying to test:
def create
inventory
#requestrecord = Request.new(request_params)
end
The problem is in my Rspec controller test, I now have to manually define this inventory again like so:
before do
#inventory = { some hash }
end
Instead of doing this, is there a way to call the method from the Application Controller in the before statement? The #inventory is a rather long hash...
Thanks!
You can access your controller in rspec with 'controller', so
before do
#inventory = controller.inventory
end
should do the job!
I want to be able to upload an xml file to my rails app and have it then parse through the file and generate ActiveRecord entries based off the contents.
I've put together a parser using nokogiri that works fine in vanilla Ruby, so no problem there, but for some reason Rails seems to want to run through it before I've even hit the upload button to supply it with the file. As soon as I try to go to the upload page, I receive this
TypeError in FoobarsController#create
no implicit conversion of nil into String
what I've got looks like this:
app/models/foobar.rb
class Foobar < ActiveRecord::Base
attr_accessible :xml_file
has_attached_file :xml_file
before_save :parse_file
def parse_file
require 'xml_parser'
myFile = xml_file.queued_for_write[:original]
fooParser = Nokogiri::XML::SAX::Parser.new(FoobarParser.new)
fooParser.parse(File.open(myFile,mode='r'))
end
end
app/controllers/foobars_controller.rb
class FoobarsController < ApplicationController
def new
#foobar = Foobar.new
end
def create
#foobar = Foobar.new(params[:foobar])
if #foobar.save
redirect_to #foobar
else
render 'new'
end
end
end
app/views/foobars/new.html.erb
<h1>Upload foobar</h1>
<div class="row">
<div class="span6 offset3 center">
<%= form_for(#foobar) do |f| %>
<%= f.file_field :xml_file %>
<%= f.submit %>
<% end %>
</div>
</div>
I guess it's a problem with the controller's create method, but I was basing my code on this so I thought it should do what I want. Any help would be appreciated.