RoR: how can I search only microposts with a certain attribute? - ruby

Right now in app/views/microposts/home.html.erb I have..
<% form_tag purchases_path, :method => 'get', :id => "products_search" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<% form_tag sales_path, :method => 'get', :id => "sales_search" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
and then in micropost.rb I have
scope :purchases, where(:kind => "purchase")
scope :sales, where(:kind => "sale")
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
and then finally in the microposts_controller.rb I have
def home
#microposts=Micropost.all
#purchases=#microposts.purchases
#sales=#microposts.sales
end
Right now I am getting an error saying undefined local variable or method `purchases_path' and it does the same for sales_path.
What I want to be able to do is search only some of the microposts instead of all of them. In my micropost table I have a column called kind which can be either "purchase" or "sale". How can I change these three pieces of code so that one search searches through and displays results for only those microposts with the kind "purchase". And then the other searches through and displays results for only those microposts with the kind "sale"
this question (on another post) has a bounty with 50 rep at RoR: how can I search only microposts with a specific attribute?

You might try this.
Your model:
class Micropost
# ...
scope :purchase_only, where(:kind => "purchase")
# ...
def self.search(search)
if search
self.purchase_only.find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
self.purchase_only
end
end
end
But, this stuff looks very strange to me.
E.g.: You should remove the .find(...), this finder will be deprecated with Rails 4.

Related

Getting a value from an array of hashes in Ruby

I have an array:
address => [{"data"=>{"zip"=>"60628", "state"=>"IL", "city"=>"chicago", "street"=>"123 Main St. Apt 2"}, "primary"=>true}]
I want to show each piece in the right format on my view like:
123 Main St. Apt 2
Chicago, IL 60628
I am having trouble getting the logic correct to show this.
Where should this logic go, as a method in my model or in the actual view?
I tried:
<% #applicant.address.map{|x| x[:data]}.each do |address| %>
<%= address.street %><br><%= address.city %>, <%= address.state %> <%= address.zip %> <br>
<% end %>
but got:
=> [{"zip"=>"60628", "state"=>"IL", "city"=>"chicago", "street"=>"123 main st Apt 2"}]
The map gives you a new array and if you use hashes you need to access the values with the hash[:key] or hash["key"] operator, try this:
<% #applicant.address.each do |address_hash| %>
<% address = address_hash["data"] %>
<%= address["street"] %><br><%= address["city"] %>, <%= address["state"] %> <%= address["zip"] %> <br>
<% end %>
But if I were you , I'd put the data in an array of structs, it's more readable.
In your model or helper:
address = Struct.new(:street, :city, :state, :zip)
address.street = ..
...
#addresses << address
etc
In your view:
<% #addresses.each do |address| %>
<%= address.street %><br><%= address.city %>, <%= address.state %> <%= address.zip %> <br>
<% end %>
For your first question something like this should suffice:
#!/usr/bin/env ruby
require 'ostruct'
address = [
{
'data' => {
'zip' => '60628',
'state' => 'IL',
'city' => 'chicago',
'street' =>'123 Main St. Apt 2'
},
'primary' => true
}
]
class AddressPresenter
def initialize(address)
#address = OpenStruct.new(address)
end
def to_s
"#{#address.street} \n#{#address.city} #{#address.state} #{#address.zip}"
end
end
address.each do |a|
puts AddressPresenter.new(a['data'])
end
Now, for the second question, I would implement a Presenter class whose only goal is to "present" the data in whatever format you need in the view, this allows you to keep your views with 0 presentation logic. So in this case the class AddressPresenter could be reworked to return in the to_s the right HTML you need in your view. And you would do something like:
<% #applicant.address.each do |address| %>
<%= AddressPresenter.new(address['data']).to_s %>
<% end %>
By having a separated presenter class, you get the following benefits:
Your models don't worry about how to present/render stuff because that's not their job
You can test this presenter to confirm it returns whatever you're expecting in the view
Your views don't contain any complicated logic

only showing button to index action when there are objects listed in the index(in the database)

I have a button that links to the projects updates index action through all_project_updates_path i set in my routes. Here is my button code:
<%= button_tag type: "button", :class => "radius" do %>
<%= link_to 'Project Updates', all_project_updates_path(#project), :style => "color: white" %>
<% end %>
I want this button to only be visible when there are project updates in the database. Otherwise I want this button to dissapear. I tried:
<% if all_project_updates_path(#project) != nil %>
<%= button_tag type: "button", :class => "radius" do %>
<%= link_to 'Project Updates', all_project_updates_path(#project), :style => "color: white" %>
<% end %>
<% end %>
And also
<% if #updates != nil %>
<%= button_tag type: "button", :class => "radius" do %>
<%= link_to 'Project Updates', all_project_updates_path(#project), :style => "color: white" %>
<% end %>
<% end %>
but that doesn't seem to work. Looking for a simple explanation as I am a relative beginner with ruby.
This is the route:
get 'all_project_updates/:id' => 'project_updates#index', as: 'all_project_updates'
This is my projects controller(show action)
def show
#project = Project.find(params[:id])
#comments = Comment.all.where(:project_id => #project.id)
#updates = ProjectUpdate.all.where(:project_id => #project.id)
end
And this is my project updates controller index action:
def index
#projectUpdates = ProjectUpdate.where(:project_id => params[:id])
respond_to do |format|
format.html
end
end
You’re examining a path helper, all_project_updates_path, when you need to be querying a model object. The all_project_updates_path call is a helper to return a path for linking between web pages.
all_project_updates_path(#project) # => /all_project_updates/1
So you’re really asking:
'/all_project_updates/1'.nil? # => false
Because it’s just a string, it won’t be nil.
Instead, you should be examining the project_updates directly. I’m not sure how your models are related, but assuming that a Project has_many :project_updates, try this:
if #project.project_updates.any?
That will return true if a #project has any updates.
Beyond your immediate question, I would recommend considering whether nested resources are a better fit for this usage. You could declare your routes like this:
resources :projects do
resources :project_updates
end
Then you would get project_project_updates_path(#project) and no longer need your custom route that pretty much duplicates that functionality.
Try this:
<% if #updates.any? %>
<%= button_tag ... %>
<% end %>
#updates is an empty collection (ActiveRecord_Relation to be precise) of ProjectUpdate objects if no records were found, it's not nil.

Formtastic Creating a form without users

I'm creating a web application with formtastic. I installed the gem and wrote my code like this:
<%= semantic_form_for #index do |form| %>
<%= form.inputs do %>
<%= form.input :name %>
<%= form.input :born_on, :start_year => 1997 %>
<%= form.input :description, :as => :text %>
<%= form.input :female, :as => :radio, :label => "Gender", :collection => [["Male", false], ["Female", true]] %>
<% end %>
<%= form.actions do %>
<%= form.action :submit, :as => :button %>
<% end %>
<% end %>
I want the form to appear on the index page which is why I have #index. For some reason I can't do #index. How would I reference the top line so that it renders a form on the index page? Currently my index page has nothing in it, but it is defined in the controller
form_for helper expects some object that responds to fields You refer inside Your form. Here is an example of using semantic_form_for with plain Ruby object: http://affy.blogspot.com/2010/02/using-formtasic-without-activerecord.html.
Also the object You specify for form doesn't effect which page is being rendered. Are You sure You are not mixing up something? Maybe if You share a bit more of Your controller code we might help You better.

Simple error in my rails app

I have an error in my rails app telling me that the index method is undefined.
I have created a such simple form just for inserting data using the (new method page) only
but it is not working now for some reason
class PeoplesController < ApplicationController
def index
end
def new
#people = People.new
end
def create
#people = People.new(params[:#people])
if #people.save
redirect_to new_people_path
end
end
end
# new.html.haml
<h2>Hello there!</h2>
<hr >
<%= form_for #people do |f| %>
FirstName:<%= f.text_field :first %><br />
LastName:<%= f.text_field :last %><br />
<%= f.submit %>
<% end %>
Here is the error code:
NoMethodError in Peoples#new
Showing /Users/kasim/Desktop/form/app/views/peoples/new.html.erb where line #3 raised:
undefined method `people_index_path' for #<#<Class:0x007fa33da58d58>:0x007fa34031c578>
Extracted source (around line #3):
1: <h2>Hello there!</h2>
2: <hr >
3: <%= form_for #people do |f| %>
4: FirstName:<%= f.text_field :first %><br />
5: LastName:<%= f.text_field :last %><br />
6: <%= f.submit %>
The documentation for form_for says that a form_for call is equivalent to this
<%= form_for #post, :as => :post, :url => post_path(#post), :method => :put, :html => { :class => "edit_post", :id => "edit_post_45" } do |f| %>
...
<% end %>
Notice that the url attribute is calling out to a named route. In your case it appears the named route is people_index_path. I'd run rake routes and make sure that the named route in question really exists.

How to pass name of form_for's method to partial in rails?

Good day! Little newbee question:
let's say I want to generate fields of form_for helper of special appearance. Thus to not to repeat complex code to generate many fields of model, I render some partial and pass there parameters. There is a reference to form object amongst them. Question is what pass to render method to call in the partial necessary method of form object? For example I want to generate this time email_field:
<%= form_for #order do |f| %>
<%= render :partial => 'form_field_special', :locals => {:form => f, :type => :email_field, :labelcaption => "SpcName"} %>
<% end %>
and partial itself:
<div class="control-group">
<%= f.label :name, <%= labelcaption %> , :class => "control-label" %>
<div class="controls">
<%= f.type :name %> # ??????
</div>
</div>
thank you guys!
Use ruby power. Object#send method:
<%= form_for #order do |f| %>
<%= render :partial => 'form_field_special', :locals => {..., :field_type => 'email_field'} %>
<% end %>
<%= f.send(field_type, :name) %>
The following method proved as the fastest way to invoke ruby object's function by its name:
m = form.method(name_of_the_method)
m.call(parameters)

Resources