Rails Object attribute value is getting modified while accessing it in Controller - ruby-on-rails

I have a News Model with attributes like email, title, slug, ..etc.I wanted to access the slug attribute of an object inside a method in my visitors_controller.
In the rails console, the value of slug attribute is
2.3.3 :002 > #news = News.order(created_at: :asc).last(1)
The result is:
slug: "north-korea-threatens-to-shoot-down-u-s-warplanes"
I also checked the slug value in my database
select slug from news where id = xxx;
The result is :
north-korea-threatens-to-shoot-down-u-s-warplanes
The value of slug is appended with " . . . " while accessing it inside of a method in a controller .
class VisitorsController < ApplicationController
def getSlug
#news = News.order(created_at: :asc).last(1)
#news.each do |news|
slug = news.slug
# raise slug.to_yaml
end
end
When I raised it, the slug value is
--- north-korea-threatens-to-shoot-down-u-s-warplanes ...
getSlug.html.erb
<% #news.each do |bubble_gum| %>
<tr>
<td><%= bubble_gum.title %></td>
<td><%= bubble_gum.slug %></td>
</tr>
<% end %>
in the view, the slug value is rendering correct, without (. . .) appended to the slug.
How can I get the value of the slug attribute without the appended content( . . .) inside of a method in a controller.
Any Help is Highly Appreciated.Thanks in advance!!

This has got nothing to do with the ActiveRecord query, or being inside a controller.
The ... you are seeing is simply caused by converting the string to YAML:
"north-korea-threatens-to-shoot-down-u-s-warplanes".to_yaml
# => "--- north-korea-threatens-to-shoot-down-u-s-warplanes\n...\n"
From wikipedia:
Three periods (...) optionally end a document within a stream.
In the controller, you are converting the string to YAML (raise slug.to_yaml), and in the view you are just displaying the string directly (<%= bubble_gum.slug %>). That's why you are seeing a difference.

Related

Rails error in inline edit using gem 'best_in_place'

I am trying use gem 'best_in_place' in table edit, but having error while using it
in controller only index method for display all users details from db.
Error: undefined method name' for "Rohit":String`
Code used:
<% #user_record.each do |record| %>
<tr>
<td><%= best_in_place record.name, :name %></td>
</tr>
<% end %>
controller Code:
def index
#user_record = MUser.search(params[:name],params[:gender])
end
def create
end
as I see from the docs the first argument you pass to the method best_in_place should be an object record and the second - a field you need to edit with this gem, in your case it is name.
So it will get provided field name from the record.
And since you've called name by yourself, it returns the actual value of the name instead of the whole object record and then tries to get name from that value which results in this error.
So you need to change that line to <td><%= best_in_place record, :name %></td>.

Alter all attributes printed in views on ruby on rails

My rails application only reads data on it's database. There's no save.
Mostly all my views are a form with a few fields to filter my search and a table printing every column's value. Something like that:
<table>
<tr>
<th> Col1 </th>
<th> Col2 </th>
<th> Col3 </th>
...
</tr>
<% Model.all.each do |model| %>
<tr>
<td> <%= model.col1 %> </td>
<td> <%= model.col2 %> </td>
<td> <%= model.col3 %> </td>
...
</tr>
<% end %>
There's over 50 models each with 10-20 fields, almost 100 tables. It's all very straightforward.
Now my client asked me that when any cell is empty (the data is null or '') he wants it to print '-' instead of the blank cell on the table
At first I thought about something like this on my application_helper.rb:
def avoid_empty(object)
if object == nil or object == ""
return "-"
else
return object
end
end
and everywhere on my views I would just change
<%= model.col1 %>
to
<%= avoid_empty(model.col1) %>
but I actually have 2659 lines like that. I'm not sure it's the healthier approach.
Is there any way I can change it everytime I try to print any value from those models that I could go through that method or something similar first, without having to change every single one of my 2659 lines?
You can use the power of ruby's meta-programming and ActiveSupport::Concern.
Create a model extension module to overwrite the getter of all columns dynamically. Below code can do that:
module ModelExtension
extend ActiveSupport::Concern
# To exclude some columns
EXCLUDE_COLUMNS = ['id', 'created_at', 'updated_at']
included do
(self.column_names - EXCLUDE_COLUMNS).each do |col|
define_method col do
self[col].blank? ? '-' : self[col]
end
end
end
end
Include this module in each model to get '-' instead of blank or nil. To include model, you can do:
class MyModel
include ModelExtension
end
You can monkeypatch NilClass.
class NilClass
def to_s
'-'
end
end
Everytime you invoke, say, nil.to_s, it will print '-'. If you type puts nil in the console, will print -. Try the following example:
class NilClass
def to_s
'-'
end
end
foo = nil
foo.to_s #=> '-'
puts foo #=> -
In your case, all occurrences of empty (nil) attributes will output - in the view when trying to print (and, be warned, in other parts of your application too).
PS.: #to_s returns a string representing the instance object.
A solution maybe
The Null Object Pattern
Null Object is an object with some default behavior that implements the same interface as an other object that might be used in a given case. Ok, cool, but how can we apply it to the example below? Let's start with the user method:
def user
#user ||= User.find_by(email: email) || NullUser.new
end
And now we can implement NullUser:
class NullUser
def name
"Anonymous user"
end
end

undefined method `order' for "1":String

On my landing_pages "show" page, I'm trying to show the leads that came in via that page and sort them via their "score".
My landing_page model has:
has_many :page_leads
My page_lead model has:
belongs_to :landing_page
In my index method within my page_leads controller, I have this, which works:
def index
#page_leads = PageLead.order(score: :desc)
end
I try to duplicate this in the landing_pages controller for the show method. Here is what I have:
def show
#landingpage = LandingPage.find(params[:id]).order(score: :desc)
end
When I try to go to the "Show" page, I get an error "undefined method `order' for "1":String". How can I get this to work?
My show page has the following code:
<tbody>
<% #landingpage.page_leads.each do |page_lead| %>
<tr>
<td><%= page_lead.fname %></td>
<td><%= page_lead.lname %></td>
<td><%= page_lead.score %></td>
</tr>
<% end %>
</tbody>
It is just:
def show
#landingpage = LandingPage.find(params[:id])
end
Cause find returns the LandingPage with id == params[:id]. No need to sort a single item.
find returns an array or records if the params[:id] is an array.. the order can't be applied to the array, because order isn't part of the array class.
If params[:id] is a single element then the find returns the record. Again order doesn't apply, because it's just one record not a container of records..
If you want an sorted list then use
LandingPage.where(id: params[:id]).order
But since this is in the show I suspect you want the single item... As spickermann said drop the order
LandingPage.find(params[:id])
If you want to sort Page Leads, you would do something like
def show
#landingpage = LandingPage.find(params[:id])
#page_leads = #landingpage.page_leads.order(score: :desc)
end
As #spickermann mentioned, .find() only returns one model instance. You can't order this using ActiveRecord query methods.
If you want to order the page leads, you have to call .order on the set of page_leads that belong to the landing page

How to display all instances of a model in Rails?

In my web application the user can select certain instances of an entity. For instance on the class BubbleGum, now the user can select certain instances of BubbleGum by adressing their identifier:
gums/details?show=3532667
Now, in addition I also want to make it possible to display all BubbleGums. For this I have introduced the convention of using * to identify all
gums/details?show=*
This works nice so far, but often I have to add a bit code to process the * selection. Is there a nice way to represent an all-instances object in Ruby and/or Rails?
I have thought of using simply a dedicated symbol, constants, or an actual object of the class BubbleGum that represents all the other bubble gums.
To display all the entities in a rails application generally we use a index page.
bubble_gums_controller.rb
def index
#bubble_gums = BubbleGum.all
end
views/bubble_gums/index.html.erb
<% #bubble_gums.each do |bubble_gum| %>
<tr>
<td><%= bubble_gum.name %></td>
<td><%= bubble_gum.price %></td>
</tr>
<% end %>
Refer this for further details.
http://guides.rubyonrails.org/getting_started.html#listing-all-posts
I think you want to use the query string param show.
So, you can try in your gums controller:
def details
if params[:show] == "*"
#bubble_gums = BubbleGum.all
# ...
elsif params[:show]
#bubble_gum = BubbleGum.find(params[:show])
# ...
else
render :status => 404
end
end

Passing a single record from an ActiveRecord model object into a param (or how to pass multiple fields in a param)?

Rails 2.3.5
I have a view displaying 'employee' records in a table where each table row haas a check_box_tag to select that (row) employee record (the table is inside a form_tag). The checkbox is passing an array of employee numbers to a method but I also need it to pass some of the other information from the record (first_name, last_name, etc) in the params.
Orignally this looked like (just passing an param with an array of employee numbers)
<% #employee_search.each do |e| %>
<td><%= check_box_tag 'selected_subordinates[]', e.employee_number %></td>
<td><%= e.employee_number %></td>
<td><%= e.first_name %></td>
<td><%= e.last_name %></td>
...
<% end %>
I'm not sure this was right, but I thought I should pass the entire record ('e') in the param:
<% #employee_search.each do |e %>
<td><%= check_box_tag 'selected_subordinates[]', e %></td>
<td><%= e.employee_number %></td>
<td><%= e.first_name %></td>
<td><%= e.last_name %></td>
...
<% end %>
The param array now looks like:
"selected_subordinates"=>["#<Employee:0xa946970>", "#<Employee:0xa946910>", "#<Employee:0xa9468b0>"]
I thought at this point I would be fine and just itterate through the objects in the param array referring to the record fields, but got an undefined method error:
params[:selected_subordinates].each do |s|
puts s.last_name
end
undefined method `last_name' for "#<Employee:0xa946970>":String
I started wondering if for some reason the entire model object was passed instead of just one record from the object. But, trying [0].last_name resulted in a different error.
params[:selected_subordinates].each do |s|
puts s.last_name
end
undefined method `last_name' for 35:Fixnum
Maybe I should have been using the fields I need to build an array for the param - so the param would be an array of arrays? I haven't had any luck so far trying to search for example of what to do when you need to setup a param array made of arrays, or pass a single model object record (and refer to it).
Thank You - Much Appreciated!
When you used e as the param, Rails was converting e to a String and passing that (you can't pass an object in an HTML form, right? Just values). When you saw "#<Employee:0xa946970>" in your params hash, it wasn't an Employee object, but instead a String with the contents of #<Employee:0xa946970> (which is what you get if you called .to_s on an Employee object).
Passing the ID gets you on the right track, but once you have the ID, you should look up the Employee with that ID from the database.
params[:selected_subordinates].each do |s|
employee = Employee.find(s)
puts employee.last_name
end
Of course, this loads them one at a time, so if you have a lot of checkboxes you could end up generating a large number of queries. You can also use the find method to find multiple objects based on an array of IDs:
employees = Employee.find(params[:selected_subordinates])
employees.each do |e|
puts e.last_name
end

Resources