I'm baffled...
I have a model called Distributor and when I do Distributor.all in the console I get the array of all the records as I should (there are currently 657 records in there according to this query).
However, I created a controller action to show this distributors in an index view. And an empty array is returned from the same query Distributor.all
I've restarted the server
I've checked for spelling mistakes (literally copied and pasted the Distributor.all from controller to
console to make sure and it worked in console)
I've used binding.pry to debug and no problems are showing there
I've checked the logs and no errors are showing up
I've checked the logs vs the console and the same SQL query is being run Distributor Load (10.9ms) SELECT "distributors".* FROM "distributors" for both, but returning different results
generating the CSV or HTML isn't a problem because both load without errors
Any suggestions?
Distributor Model:
class Distributor < ActiveRecord::Base
belongs_to :brand
def self.to_csv
attributes = %w{distributor_id mfg_brand_id company_name address_one address_two city state postcode country address_type primary_address users_count created_at}
CSV.generate(headers: true) do |csv|
csv << attributes
all.each do |d|
csv << d.attributes.values_at(*attributes)
end
end
end
end
Distributors Controller
class DistributorsController < ApplicationController
before_action :authenticate_user!
def index
#user = current_user
if #user.admin?
#distributors = Distributor.all
respond_to do |format|
format.html
format.csv { send_data #distributors.to_csv }
end
else
flash["danger"] = "You must be a logged in Admin to access this route"
redirect_to root_path
end
end
end
Distributors index.html.erb
<h1>Distributors#index</h1>
<p>Find me in app/views/distributors/index.html.erb</p>
<%= #distributors.each do |d| %>
<%= d %>
<% end %>
In your controller, if you replace #distributors = RheemruudDistributor.all with #distributors = Distributor.all it should work, right? Or am I missing something?
Finally figured it out...and I figured it was something simple.
This is a multi-tenant app using the apartment gem and I had to put this newly created model in the excluded models part of the apartment.rb initializer.
Figured I'd leave this hear in case anyone else is in this situation.
use
<% #distributors.each do |d| %>
<%= d %>
<% end %>
instead of
<%= #distributors.each do |d| %>
<%= d %>
<% end %>
on your view
Related
I have what I believe is fairly simple model setup:
class Booking < ApplicationRecord
has_many :payments
end
class Payment < ApplicationRecord
belongs_to :booking
end
Now, I want to create a form that allows a user to register payments in batch. That is, the form should have a number of input rows, each one representing a payment for some booking (i.e., each row has some fields for the columns of Payment plus a booking_id field). Upon submitting, each row should cause the creation of a corresponding Payment, which should be associated with the Booking indicated by the user for that row.
This seems to be surprisingly tricky, and my Google-Fu is failing me. I've tried the following (inspired by this post describing a solution without associations), which I thought would work, but which, well, doesn't:
class Admin::PaymentController < Admin::Controller
def batch
#payments = []
5.times do
#payments << Payment.new
end
end
def submit
params["payments"].each do |payment|
if payment["booking_id"] != "" || payment["amount"] != ""
Payment.create(payment_params(payment))
end
end
end
private
def payment_params(p)
p.permit(:booking_id, :amount)
end
end
<%= form_tag admin_payment_submit_path do %>
<% #payments.each do |payment| %>
<%= fields_for 'payments[]', payment do |p| %>
<%=p.text_field :booking_id%>
<%=p.number_field :amount%>
<% end %>
<% end %>
<%= submit_tag %>
<% end %>
This renders the form without erroring out, but the HTML names work out such that only a single payment (the last one) is submitted (e.g., name="payments[booking_id]"). Furthermore, upon submitting, I get the error
undefined method `permit' for "booking_id":String Did you mean? print
Which is less than helpful.
I've tried other variations too, but I feel like at this point I'm just feeling my way in the dark. Any guidance would be greatly appreciated!
params in controller is a instance of ActiveController::Parameter that has permit method.
But params["payments"] is a just array as subset of params.
For multiple payment params
def submit
payment_params.each do |payment|
if payment["booking_id"].present? || payment["amount"].present?
Payment.create(payment)
end
end
end
private
def payment_params
params.permit(payments: [:booking_id, :amount])["payments"]
end
For Single payment param
def submit
if payment_param["booking_id"].present? || payment_param["amount"].present?
Payment.create(payment_param)
end
end
private
def payment_param
params.require(:payments).permit(:a, :b)
end
I am fairly new to Rails and have been making steady progress on a Mobile Web App I am working on for our local high school but have run into an issue which I am stumped on. I am hoping the collective knowledge here will point me in the right direction.
I have a model for the school athletes (first name, last name, height, weight, graduation years, - standard stuff) which is working (CRUD via standard scaffold generation) and now I want to add the ability to import records via CSV upload.
In an effort to not reinvent the wheel, I am following this example from Rich on Rails. To get familiar with it, I created a separate Rail project and followed the example and it all works as expected. Great. Now to integrate into my existing project.
Everything seems to integrate fine with one exception - the CSV file is never passed to my model in the params I cannot figure out why. I am sure it is something obvious but I have stared at this problem for several hours and am unable to see what I am doing wrong.
Here is a portion of my Athletes controller:
class AthletesController < ApplicationController
before_action :set_athlete, only: [:show, :edit, :update, :destroy]
# GET /athletes
# GET /athletes.json
def index
#athletes = Athlete.all.order(:lastname, :firstname)
end
# POST /athletes/import
# POST /athletes/import.json
def import
logger.info(params.to_yaml)
begin
Athlete.import(params[:file])
redirect_to page_path('admin'), notice: "Athletes imported."
rescue
redirect_to page_path('admin'), notice: "Invalid CSV file format."
end
end
# GET /athletes/1
# GET /athletes/1.json
def show
end
# GET /athletes/new
def new
#athlete = Athlete.new
end
# GET /athletes/1/edit
def edit
end
My model looks like this:
class Athlete < ActiveRecord::Base
# an athlete can be on more than one team
has_and_belongs_to_many :teams, through: :athletes
require 'csv'
## CSV import
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
athlete_hash = row.to_hash # exclude the ? field
athlete = Athlete.where(id: athlete_hash["id"])
if athlete.count == 1
athlete.first.update_attributes
else
Athlete.create!(athlete_hash)
end # end if !athlete.nil?
end # end CSV.foreach
end # end self.import(file)
I've added this onto my index view for testing, later on it will be in an admin area:
<div>
<h3>Import a CSV File</h3>
<%= form_tag import_athletes_path, multipart: true do %>
<%= file_field_tag :file %>
<%= submit_tag "Import CSV" %>
<% end %>
</div>
No matter what I do, I never get the value of the file_field_tag to come through to the controller. If I add other fields using text_field_tag they come through as expected but the file_field_tag value never does.
--- !ruby/hash:ActionController::Parameters
utf8: "✓"
authenticity_token: it3yBxBnzA4UQ/NILP5GNoYJeO5dyg+Z+VfhE/C6p7k=
commit: Import CSV
action: import
controller: athletes
Redirected to http://localhost:3000/
Completed 302 Found in 8ms (ActiveRecord: 0.0ms)
I am stumped - if anyone has any ideas as to what I might be doing wrong, I would be grateful. I have about 300 athletes which I want to import and have no desire to type them in.
It turns out because I am using jQuery Mobile for my framework, I need to add "data-ajax=false" to my form tag. This change to my form allowed the file parameter to be visible in the controller:
<h3>Import a CSV File</h3>
<%= form_tag(import_athletes_path, { :multipart => true, :'data-ajax' => false }) do %>
<%= file_field_tag :file %>
<%= submit_tag "Import CSV" %>
<% end %>
</div>
A short while ago I recalled reading something about file uploads and jQuery Mobile not working by default. It is due to the standard AJAX navigation employed by jQM.
I'm new on rails and I have a book to study them. In one practice, I created a helper in my Application Helper, the test from RSpec work fine, until I have to print the result of my helper. No show any result and no error happens.
application_helper.rb
module ApplicationHelper
def title(*parts)
unless parts.empty?
content_for :title do
(parts << "Ticketee").join(" - ")
end
end
end
end
show.html.erb
<% title(#project.name) %>
projects_controller.rb
class ProjectsController < ApplicationController
def show
#project = Project.find(params[:id])
end
end
and when I go to the show link I supposed to see "Random Project name - Ticketee", however only they show me "Ticketee".
Any help...
<% title(#project.name) %>
Means don't show to the user
<%= title(#project.name) %>
Means show to the user - notice the equals.
I really don't know the way to display error on a view when we post datas which are associated from another model.
My needs :
I have a form displayed in app/view/libraries/show.html.erb
The comments are associated to library in my app. Means that for a library we can have one or many comments.
In model/comment.rb i put that :
validates :name, presence: true
in app/view/libraries/show.html.erb : i need to display error but don't know the way to retrieve it :
<% if #library.comment.errors.any? %>
<%= #library.comment.errors.count %>
<% end %>
CommentsController
class CommentsController < ApplicationController
def new
end
def create
#library= Library.find(params[:library_id])
#comment = #library.comments.create(params[:comment].permit(:name, :commenter))
redirect_to #library
end
end
This does not work someone can please explain to me the way it works ?? I am doing the guide rails getting start but want to add some features simple in it...
Thanks a lot guys !
If all you need is the count, you can put it in flash
def create
#library= Library.find(params[:library_id])
#comment = #library.comments.create(params[:comment].permit(:name, :commenter))
flash[:error_count] = #comment.errors.count
flash.keep[:error_count]
redirect_to #library
end
<% if flash[:error_count] > 0 %>
<%= flash[:error_count] %>
<% end %>
I'm new to Ruby on Rails and programming in general. So far I've successfully used my console to return JSON data from an API but I can't seem to make it work on my local server.
In the console I entered:
httparty "http://rubygems.org/api/v1/versions/httparty.json"
and it returned the JSON after I managed to install/configure everything.
So then in the console I wrote:
rails new Catalog
rails generate controller new index
I followed the tutorial to get <h1>Hello, Rails!</h1> to display on my page when I go to:
http://localhost:3000/
Now I am trying to get the JSON data returned and display on that same page where it says "Hello, Rails".
In index.html.erb I have:
<h1>Hello, Rails</h1>
<%= #result %>
In home_controller.rb I have:
class HomeController < ApplicationController
def get_catalog
include HTTParty
#result = HTTParty.get("http://rubygems.org/api/v1/versions/httparty.json")
end
end
In routes.rb I have:
Catalog::Application.routes.draw do
get "home/index"
root :to => 'home#index'
end
Nothing appears under "Hello, Rails" when I go to the page.
I'm still trying to wrap my head around how all of this stuff interacts with each other. Can anyone see what I'm doing wrong here perhaps?
--- Update
I'm trying to output just the product names into li elements. My files now are:
index.html.erb:
<ul>
<% #http_party_json.each do |event| %>
<% event.each do |e| %>
<li><%=h e['Products']['Name'] %></li>
<% end %>
<% end %>
</ul>
controller:
class HomeController < ApplicationController
def index
#response = HTTParty.get("myURL")
#http_party_json = JSON.parse(#response.body)
end
end
The error I am getting is:
undefined method `[]' for nil:NilClass
Extracted source (around line #5):
2: <ul>
3: <% #http_party_json.each do |event| %>
4: <% event.each do |e| %>
5: <li><%=h e['Products']['Name'] %></li>
6: <% end %>
7: <% end %>
8: </ul>
When I take off the ['Name'] I get JSON starting with:
[{"Name"=>"3x4 Vinyl Magnet", "Description"=>"Made of durable high-gloss vinyl. Measures 3x4 inches and has rounded corners. Waterproof and scratch resistant."
Why can't I target ['Name'] to get just the product names?
HTTParty parses XML/JSON responses for you. Simply use parsed_response to get it:
#response = HTTParty.get("URL").parsed_response
HTTParty.get returns an object of the type HTTParty::Response, which is documented in HTTParty (Check out the examples.)
There is a nice helper method on HTTParty::Response called `#parsed_response. This returns the JSON string parsed into a Hash or Array:
HTTParty.get("URL").parsed_response
Alternatively, in order to get the body of this message, you can call #result.body. This returns a string, which you can safely output to your page as you did. However, I'm guessing you want to do more with it than just output it to a page.
In order to parse this into a hash/Array that you can use/manipulate/return as true JSON you would do something like:
http_party_json = JSON.parse(#response.body)
So with this, you could do something like the following in your controller if you wanted to be able to return JSON:
#response = HTTParty.get("http://rubygems.org/api/v1/versions/httparty.json").parsed_response
respond_to do |format|
format.json { render :json => JSON.parse(#result) }
format.html { render "index.html.erb" }
end
Updated answer based on your updated information:
It appears as though e['Products'] returns an array (notice the square brackets on the outside.) So, if you are only expecting one you could do:
e['Products'][0]['Name']
If it might return multiple products, you might, instead, need to account for the possibility of many products and use an each block:
e['Products'].each do |product|
#do something with product['Name']
end
It just depends on your needs for the app.