Converting string to active record query statement - mysql

inside one of my view pages I'm using old fashion way of presenting data but I have problem in converting a string like "User.country.name" to a query statement.
I'm using a loop like below :
#columns = ['id','email','name','country.name']
table = User.all
<% table.each do |row| %>
<% #columns.each do |field| %>
<%= row[field] %>
<% end %>
<% end %>
The table shows almost all data except for column "country.name". I can't use constantize for country.name it gives me error. Any solution ? Thanks

Your User doesn't have an attribute country.name, it has an association country and that association has an attribute name.
You could set up a delegate:
class User < ActiveRecord::Base
delegate :name, to: :country, prefix: true
# ...
end
This creates a method User#country_name, returning country.name.
Now you can adapt your loop, using public_send to call the methods: (I've changed the variable names to make it clearer)
#methods = [:id, :email, :name, :country_name]
records = User.all
<% records.each do |record| %>
<% #methods.each do |method| %>
<%= record.public_send(method) %>
<% end %>
<% end %>

#users = User.select(:id, :email).joins(:countries)
<% #users.each do |user| %>
<%= user.id %>
<%= user.email %>
<%= user.countries %>
<% end %>
http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-joins
Wish it helps

Related

Hash being saved to database but unable to render its values in Rails forms?

I added a new column to model Plan, named :per_unit_quantities_configuration which is a hash with min, max and step key/values.
t.jsonb "per_unit_quantities_configuration", default: {}
When I edit a Plan, the hash is being correctly saved to the DB (I can access each key/value from the console), but the forms are not displaying any of its values (the fields are empty).
I tried adding a store_accessor for the column in the Plan model, but it is not working:
store_accessor :per_unit_quantities_configuration, :min, :max, :step
Example of a simple_form html that does not display hash values:
<%= simple_form_for [:admin, #base_plan, #plan] do |f| %>
<% if f.object.base_plan.per_unit? %>
<div class="d-flex">
<%= f.simple_fields_for :per_unit_quantities_configuration do |fields| %>
<% if f.object.errors[:per_unit_quantities_configuration].any? %>
<%= f.error :per_unit_quantities_configuration, id: "per_unit_price_error", class: "invalid-feedback", error_prefix: "gato" %>
<% end %>
<%= fields.input :min %>
<%= fields.input :max %>
<%= fields.input :step %>
<% end %>
</div>
<% end %>
<%= f.button :submit, class: "pull-right" %>
<% end %>
What am I doing wrong?
since you setup store_accessor :per_unit_quantities_configuration then you can access directly 3 attributes min, max, step, so that you no need to wrap those attributes on simple_fields_for :per_unit_quantities_configuration and treat them as normal fields (that mean on controller you have to permit them as normal fields)
# view
<%= f.input :min %>
<%= f.input :max %>
<%= f.input :step %>
# controller
def plan_params
params.require(:plan).permit(:min,:max,:step)
end

Rails: Get form to only render when certain conditions are met

Im trying to get this loop to only render the reviews form for services which doesnt already have a review. I can't get it to function properly. Any ideas?
<% #services.each do |service| %>
<% if service == #booked && !#hasReview %>
<%= form_for(service, service.reviews.new) do |f| %>
<label>Create review for</label> <%= label_tag service.title %>
<div id="user_stars"></div>
<div class form-group>
<%= f.text_area :comment, rows: 3, class: "form-control" %>
</div>
<%= f.hidden_field :service_id, value: service.id %>
<div class="actions">
<%= f.submit "Create", class: "btn btn-primary" %>
</div>
<% end %>
<% end %>
<% end %>
The #booked and #hasReview actions are working correctly by themselves. So I guess Im setting it up wrongly with the IF
EDIT:
services_controller.rb
def show
#user = User.find(params[:id])
#services = #user.services
#booked = Booking.where("service_id = ? AND user_id = ?", #service.id, current_user_id).present? if current_user
#reviews = #service.reviews
#hasReview = #reviews.find_by(user_id: current_user_id) if current_user
end
reviews_controller.rb
def create
#review = current_user.reviews.create(review_params)
redirect_to request.referer
end
Your logic looks good, so I'm guessing your problem is with this part of your if statement:
if service == #booked
Judging from this line in your services_controller:
#booked = Booking.where("service_id = ? AND user_id = ?", #service.id, current_user_id).present? if current_user
it looks like the #booked instance variable is a boolean. So you're comparing a boolean to service, but it doesn't look like service is a boolean.
So you'll want to change the if statement so that you're comparing two equivalent types, and in your case you probably want to compare two boolean values.

If i pluck 2 values, how can i read them in html ruby

In my controller i find a uniq notebook and user name.
but i want to be able to check in my html code that it shows only one type of user.
in controller
def index
#allnotebooks = Note.uniq.pluck(:string, :notebook)
#notes = Note.all
end
in my html
<% #allnotebooks.each do |notebook| %>
<% if notebook.string == c_user.name %>
<option><%= notebook %></option>
<% end %>
<% end %>
notebook.string does not work. what am i missing
Also you can do in different way other than using pluck, using select you can do it
like-
In controller code-
def index
#allnotebooks = Note.uniq.select([:string, :notebook])
#notes = Note.all
end
in your html
<% #allnotebooks.each do |notebook| %>
<% if notebook.string == c_user.name %>
<option><%= notebook %></option>
<% end %>
<% end %>
Thanks!!!
Pluck returns an array.
Try notebook.first or notebook[0]
Docs here: http://apidock.com/rails/ActiveRecord/Calculations/pluck
Second example at the bottom applies here.
In your example it should be:
<% #allnotebooks.each do |notebook| %>
<% if notebook[0] == c_user.name %>
<option><%= notebook[1] %></option>
<% end %>
<% end %>
btw you might want to improve this by only loading notebooks where the string equals your user's name.
I am not a good ruby guy, You can write it like
<% #allnotebooks.each_with_index do |notebook, index| %>
<%= notebook[index].string %> => <%= notebook[index].notebook %>
<% end %>
for "a" unique notebook, you do you need to loop it?
just to say:
#allnotebooks.each{|notebook| <%= notebook[0] %> <%= notebook[1] %> }
But there can be better ways.

passing params throught rails forms

I am using rails 4 and have a subject and comment models. Subject is a one to many relationship with comments. I want a simple page that can add comments to many subjects on the same page. So in my form I know how to submit a comment to create but I dont know how to find the right subject in my controller to add it to. Any advice?
class CommentsController < ApplicationController
def create
comment = Comment.create(comment_params)
if comment.save
# The line below is incorrect, I dont know what to do
Subject.find(params[:subject_id]).comments << comment
redirect_to(:controller => 'static_pages', action: 'home')
end
end
def new
end
private
def comment_params
params.require(:comment).permit(:text, :user_name)
end
end
StaticPages#home Find me in
app/views/static_pages/home.html.erb
<% #subjects.each do |subject| %>
<div class="subjects <%= cycle('odd', 'even') %>">
<h1><%= subject.name %></h1>
<h3><%= subject.description %></h3>
<% subject.comments.each do |comment|%>
<div class="comment">
<h4><%= comment.user_name%></h4>
<%= comment.text %>
</div>
<% end %>
<%= form_for(#comment) do |f| %>
<%= f.label :user_name %>
<%= f.text_field :user_name %>
<%= f.label :text %>
<%= f.text_field :text %>
<%= f.submit('Create comment', subject_id: subject.id) %>
<% end %>
</div>
<% end %>
The simplest way would be to populate the subject_id attribute of your #comment form, like this:
<%= form_for(#comment) do |f| %>
<%= f.label :user_name %>
<%= f.text_field :user_name %>
<%= f.label :text %>
<%= f.text_field :text %>
<%= f.hidden_field :subject_id, value: subject.id %>
<%= f.submit('Create comment', subject_id: subject.id) %>
<% end %>
This will populate the subject_id attribute of your new Comment object, which will essentially associate it through Rails' backend:
#app/controllers/your_controller.rb
Class YourController < ApplicationController
def create
#comment = Comment.new comment_params
#comment.save
end
private
def comment_params
params.require(:comment).permit(:subject_id, :text, :user_name)
end
end
--
foreign_keys
This works because of the Rails / relational database foreign_keys structure
Every time you associate two objects with Rails, or another relational database system, you basically have a database column which links the two. This is called a foreign_key, and in your case, every Comment will have the subject_id foreign_key column, associating it with the relevant subject
So you may have many different forms using the same #comment variable - the trick is to populate the foreign_key for each one

Search box in ruby on rails not displaying results

I'm working with Ruby on Rails, trying to get my search bar to display the results. I've tried searching for similar issues, but most already had search working and weren't getting it to work right.
in my html I have:
<%= form_tag users_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<div class="scrollBox">
<%= will_paginate%>
<ul>
<% #users.each do |user| %>
<li>
<%= link_to user.name, user, {:class=>"signout-style"} %>
</li>
<% end %>
</ul>
<%= will_paginate %>
</div>
In my users controller I have:
def index
#users = User.paginate(page: params[:page])
#searches = User.search(params[:search])
end
In my users model I have:
def self.search(search)
if search
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
I was using the railscast episode #37
Any help is appreciated!
Update the index action as below:
def index
#users = User.search(params[:search]).paginate(page: params[:page])
end
Currently, you are storing the search results in instance variable #searches with this line:
#searches = User.search(params[:search])
BUT in your view you are accessing #users which is set as #users = User.paginate(page: params[:page]). So, you always see all the users in the view and not the searched users.
UPDATE
As you are using Rails 4.0.2, I would suggest you to refactor your search method as below:
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
all
end
end