Converting from object_id to something useful (name, email, etc) in Rails - ruby

I'm on my first Ruby on Rails project and I'm trying to display a list of users in a select box. I want to show all of the users (except the currently logged-in one).
I have that part down right now, using this code in my model, view, and controller:
Request Controller:
def new
#request = Request.new
#users = User.without_user(current_user)
end
New Requests View:
<div class="field">
<%= f.label :user_id, 'Select user' %>
<br />
<%= select_tag(:user_id, options_for_select(#users)) %>
</div>
User Model:
scope :without_user,
lambda{|user| user ? {:conditions =>[":id != ?", user.id]} : {} }
This all works well, but my select box is populated with the object_id of the user. How can I convert that object_id into a first name/last name combination, for example? I tried doing something like:
<%= select_tag(:user_id, options_for_select(#users.first_name)) %>
but that gave me an 'undefined method error.' What would be the best way to handle this?

In the select_tag of your view, you can have:
<%= select_tag(:user_id, options_from_collection_for_select(#users, :id, :first_name)) %>
This would display the first_name and when the user selects one of the options, the user id is what is filled into the value attribute for the select tag.
If you would like to display the full name, you can have a method in your user model:
def full_name
return first_name + " " + last_name
end
And, in your view:
<%= select_tag(:user_id, options_from_collection_for_select(#users, :id, :full_name)) %>
You can find more information about options_from_collection_for_select here

What you need is options_from_collection_for_select.
In your case it would be:
<%= select_tag(:user_id, options_from_collection_for_select(#users, :id, :first_name)) %>
You can read more about it and other helpers here

Related

Saving data in ruby on Rails without resources

Its bit difficult for me to explain what I want, but still I will try my best.
I created a form in Rails where user can fill certain fields. Now once these fields are filled, I know that I can use resources in Router and define a create method in Controller that will save the data to database.
However what I want is to pass data saved in the form to my controller. Then create a custom method in controller that will be just like traditional Create method, but instead of passing parameters using Resource method, I want to pass them as parameter. Is it even possible in Rails:
This is my current View to create form:
<h1> Please add a new product</h1>
<%= form_for #product do |p| %>
<p>
<%= p.label 'Product Name' %><br/>
<%= p.text_field :product_name %><br/>
</p>
<p>
<%= p.label 'Description' %><br/>
<%= p.text_area :description %><br/>
</p>
<p>
<%= p.label 'Price' %><br/>
<%= p.text_field :price %><br/>
</p>
<p>
<%= p.label 'Rating' %><br/>
<%= p.text_field :rating %><br/>
</p>
<% end %>
So may be I am using In Built form in Ruby, but I just want to pass parameters from View to Controller's method.
Thanks for help !!!
I will help you in solving your problem.
Follow these steps:
Create your route in routes.rb:
get "/create_product" => 'products#create_product', as: :create_product
or if you want to pass params through post method:
post "/create_product" => 'products#create_product', as: :create_product
Now change your view file according to the new route helper:
form_for (#products, url:{:controller=>'products', :action=>'create_product'}, html:{method:'post'})
Now the last step modify your controller:
def create_product
#your form values are avaible here in params variable
pp params
puts params[:Price]
#save your params into ur db
end
Note: I assumed that you already have product.rb model

Conditional default from ActionMailer

I'm trying to figure out the logic so when a user selects a dropdown selection, it uses that email address as the default from. For example, if the user selects store1, it should send from test1#example.com, store2 should be test2#example.com, etc.
class ApplicationMailer < ActionMailer::Base
default from: "test1#example.com"
layout 'mailer'
end
This is the form the user uses to select a store:
<%= form_for #entry do |f| %>
<div class="form-group">
<%= f.select :store, Store.all.map { |store| [store.name] }, :selected => #entry.store %>
</div>
<% end %>
In the stores table, I have columns name and email_address.
You won't be able to use default to do this - default is for the case when you don't want to customize the email.
When you write the delivery method, accept entry or store as an argument and use it to pick the from address at runtime. It would look something like
class ApplicationMailer < ActionMailer::Base
layout 'mailer'
def entry_email(entry)
mail(from: entry.store.email_address)
end
end
And you would call it with
ApplicationMailer.entry_email(entry).deliver

removing a document by passing its id using form_tag

Let's say I have book model, book.rb
class Book
include Mongoid::Document
field :book_id, type: String
field :title, type: String
end
(Here I'm using mongoid, but I think for this question it doesn't matter what type of data is.)
The book model has its own controller, views, etc.
Now, I want to create a page with form_tag (let me know if this is not a proper way), where by entering book's id and clicking enter I'll be able to remove the record this this given id from the database.
remove.html.erb:
<%= form_tag books_path, :method => 'get' do %>
<p>book_id:
<%= text_field_tag :book_id, params[:book_id] %>
<%= submit_tag "Remove", :name => nil, :confirm => "Are you sure?" %>
</p>
<% end %>
I know how to remove a given document, but can't figure out how to pass the value entered in the form and where to put the logic that will remove document.
First things first. Why do you need to store a book_id for your Book model ? Mongoid already provide a _id field for this purpose.
The usual way to destroy resources is to hit the destroy action in your controller by making a DELETE HTTP request.
class BooksController
def destroy
Book.find(params[:id]).destroy
redirect_to :back
end
end
Then simply do a link with the following:
link_to "Delete", book_path(#book), method: :delete
Where #book is your book instance.

instance vs local variables in a partial

I'm currently going through Michael Hartl's tutorial Ruby on Rails Tutorial http://ruby.railstutorial.org/ruby-on-rails-tutorial-book. I'm confused about where certain partial variables come from. In his tutorial he creates Users and Microposts. A User can create a Micropost on his main page (called a Feed) and have them posted there. The layout looks like this http://ruby.railstutorial.org/chapters/user-microposts#fig:proto_feed_mockup. Now the User model looks like this (I'm not posting the entire thing):
class User < ActiveRecord::Base
has_many :microposts, dependent: :destroy
def feed
Micropost.where("user_id = ?", id)
end
end
The Micropost model looks like this:
class Micropost < ActiveRecord::Base
belongs_to :user
end
In the text the author says that the feed method inside the User model can be written equivalently like this:
def feed
microposts
end
Why are they the same?
My next questions have to do with partials. On the user's show page (show.html.erb) the _microposts.html.erb is called with this if I'm not mistaken:
<%= render #microposts %>
_microposts.html.erb looks like this:
<li>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
<% if current_user?(micropost.user) %>
<%= link_to "delete", micropost, method: :delete,
data: { confirm: "You sure?" },
title: micropost.content %>
<% end %>
</li>
My question here is where is the micropost variable come from? Is it the same as the #micropost variable which calls this partial?
Now on the users home page (home.html.erb) there is a call to the _feed.html.erb partial like this:
<%= render 'shared/feed' %>
_feed.html.erb looks like this:
<% if #feed_items.any? %>
<ol class="microposts">
<%= render partial: 'shared/feed_item', collection: #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>
I know where #feed_items comes from. It's set in a controller. Now _feed_item.html.erb looks like this:
<li id="<%= feed_item.id %>">
<%= link_to gravatar_for(feed_item.user), feed_item.user %>
<span class="user">
<%= link_to feed_item.user.name, feed_item.user %>
</span>
<span class="content"><%= feed_item.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(feed_item.created_at) %> ago.
</span>
<% if current_user?(feed_item.user) %>
<%= link_to "delete", feed_item, method: :delete,
data: { confirm: "You sure?" },
title: feed_item.content %>
<% end %>
</li>
So a similar question is where does the variable feed_item come from and what does it contain?
thanks,
mike
Ok, let's see. This is a lot of questions in one go, but...
Why is 'feed' equivalent to 'microposts'?
This is Rails' associations at work. When you use has_many to describe an association, Rails creates a whole bunch of methods based on the association name. In this case, you say that User has_many :microposts, which, among others, creates a User#microposts method.
The instance variable used in the render call (#microposts) is presumably set in a controller action. When you call render in this fashion (with an array of ActiveRecord objects), Rails looks for a partial with a name matching the class name of those objects. In this case, they're MicroPost objects, so it looks for a partial named _micropost and renders it once for each object in the array. When rendering a partial, the object that the partial is associated with can be referred to using a local variable with the same name as the partial. Since this is the _micropost partial, the local micropost variable refers to the object it's rendering.
Once again, the local variable with the same name as the partial refers to the object the partial is rendering. #feed_items is a collection, and for each object in it, you get one rendering of the _feed_item partial, in which the feed_item local variable refers to that object.
Because a user's microposts are associated using has_many, and internally, the relationship is based on the user's id. Getting them "by hand" does essentially the same thing, but with more work.
micropost comes from convention–Rails creates it for you. I don't know what you mean by "the #micropost variable which calls this partial".
Same answer, although it's based explicitly on the template name (IIRC) rather than a singularized name. It contains a single one of whatever #feed_items contains.

DataMapper Many-To-Many Association using Sinatra

I just stared learning Sinatra and DataMapper while building a simple blog. I seem to have encountered a problem getting my Many-To-Many association working. I'm trying to associate categories with posts. Upon creation of a post, the category association is not created.
Here are my models:
class Post
include DataMapper::Resource
has n, :categories, :through => Resource
property :id, Serial
property :title, String
property :slug, String
property :body, Text
property :description, Text
property :created_at, DateTime
property :updated_at, DateTime
property :posted_at, DateTime
end
class Category
include DataMapper::Resource
has n, :posts, :through => Resource
property :id, Serial
property :title, String
end
DataMapper successfully builds the category_posts table. I don't think the code is correct in my create form.
<form action="/post/create/" method="post">
<% #category = Category.all %>
<% #category.each_with_index do |cat,i| %>
<input id="category<%=i%>" type="checkbox" value="<%= cat.title %>" name="post.category.<%=cat.id%>" />
<label for="category<%=i%>"><%= cat.title%></label>
<% end %>
<p>
<input type="submit">
</p>
</form>
I have tried manually creating entries in the category_posts table and no records show up. Here is the part of my view related to categories. The count is for debugging, it always reads 0.
<%= #post.categories.count %>
<% #post.categories.each do |category| %>
<p>Test: <%= category.title %></p>
<% end %>
Any ideas what I am doing wrong?
Thanks
The documentation for Datamapper (section for "Has, and belongs to, many (Or Many-To-Many)") has some hints, as #Mika Tuupola points out, it looks like you've set up your models correctly, the problem might be in using your models:
post = Post.create
category = Category.create
# link them by adding to the relationship
post.categories << category
post.save
p post.categories # => [#<Category #id=1>]
I've got limited experience with datamapper, but do you need to define :key => true on both of the IDs?

Resources