I'm very new to rails. What I'm trying to do is display info i have in a seed file to my views/show page. This is some of my seed file, it's just made up organizations for a school project I'm doing.
`Organization.create(
name: "St. John's church",
location: "222 Bathurst st.",
description: "Church"
)
Organization.create(
name: "Women's Shelter Toronto",
location: "777 Yonge St.",
description: "Womens Shelter"
)
Organization.create(
name: "Toronto Homeless Shelter",
location: "111 King St.",
description: "Shelter"
)`
here is my show page
<h1>Organization#show</h1>
<div class="container">
<h1>Organization:</h1>
<%= #organization.name %>
</div><br>
<div class="container">
<h1>Description:</h1>
</div><br>
and organization controller
def show
#organization = Organization.all
end
def new
#organization = Organization.new
end
def create
#organization = Organization.new(organization_params)
if #organization.save
redirect_to root_url
else
render "new"
end
end
private
def organization_params
params.require(:organization).permit(:name, :description, :location)
end
end
This very basic i know i'm just learning.
First, you should probably use use create! in your seed file so that if any of your creates fail you will see an exception flagged.
Second, what you are using as a show action should more likely be the #index action in your controller as that is the rails convention. When you stray from rails conventions your programming life gets a whole lot heavier and slower.
As an interim manual test you can run between first and second is this: After your seed file has been run, you can do things like:
rails console
Organization.count
Organization.all
to verify that your data is seeded properly.
At that point, you may find implementing and debugging your show, edit and new actions more straightforward.
The purpose of the seeds.rb file is to populate the database after the first time it's created.
After you do that, you can display the newly created data in your database on the page using Active Record.
I see 2 possible problems here:
You don't need the `` at the beginning and end of the seeds.rb file.
You didn't run rake db:seed - This command takes the seeds.rb file and actually creates the records in the database.
In your OrganizationsController#show method you are setting #organization to a list of all organization entries in your database. #organization.name is therefore not a valid method. You can do one of two things. If you only want to show one organization on the show page, which would be typical, you would have to find that organization somehow. When a user requests a show page for a particular organization he typically does so in a RESTful manner, that is through /organizations/:id, where :id is the id of the particular organization he or she would like to show. In your controller try:
def show
#orginazation = Organization.find(params[:id])
end
params[] is how Rails passes information between views and controllers. In this case params[:id] would be 1 if the user requested /organizations/1. Your controller would then go to the database and find the organization whose id was 1.
Now if you want to show a list of all organizations you would do so typically in the #index method. Something like this.
def index
#organizations = Organization.all
end
Then you would have an index.html.erb file in which you would iterate through the #organizations, like so.
<% #organizations.each do |organization| %>
<%= organization.name %>
<%= organization.location %>
<%= organization.description %>
<% end %>
This way when your user requests /organizations, he or she will see a listing of all the organizations in your database.
Edit: Your post also suggests that your controller is called OrganizationController, it should be plural, OrganizationsController and the associated filename should be organizations_controller.rb
Related
I am on Rails 4 and have a very simple question.
Say you have a User model which has_one Account and Account belongs_to the User
On the user show page, I would like to display user attributes as well as account attributes.
In the users_controller I could do it like this:
def show
#user = User.find(params[:id])
#account = #user.account
end
and then in the view:
<%= #user.name %>
<%= #account.id %>
OR
I could just set the user instance variable:
def show
#user = User.find(params[:id])
end
and in the view:
<%= #user.name %>
<%= #user.account.id %>
Is there a difference in these? Is one of them the 'Rails Way'? I may be over thinking this, but am just curious as to what is correct here.
I would argue that it's really a matter of preference. If I were the one writing it, I would assign it to a variable if it were going to be used multiple times across the view. If it is only used once, it seems redundant to assign it.
Recommended best practice is that you limit to one instance variable per controller action and #person.account.id (chaining) is not allowed.
See https://robots.thoughtbot.com/sandi-metz-rules-for-developers
Using decorators is good idea (e.g. Draper). The above example too simple to add another gem. You can use delegate in rails
See http://apidock.com/rails/Module/delegate
I stored all the tablename I've created to Menu table. And every time I add the table in Menu, it will automatically create a link under Menu list
see below.
I want each table in Menu to have a Listing, New, Edit, and Delete.
see below.
I have a controller prj_menus_controller, I will just pass the id of the table from Menu table.
here is the code for index and new in my controller.
Class PrjMenusController < ApplicationController
def index
#prj_menus = Menu.find(params[:id]).tablename.singularize.classify.constantize.all
end
def new
#prj_menu = Menu.find(params[:id]).tablename.singularize.classify.constantize.new
end
def create
#prj_menu = Menu.find(params[:id]).tablename.singularize.classify.constantize.new(prj_menu_params)
if #prj_menu.save
redirect_to :action => 'index'
else
render :new
end
end
private
def prj_menu_params
params.require("HERE IS MY PROBLEM").permit(:name)
end
end
and in my
new.html.erb
<%= simple_form_for (#prj_menu),:url => prj_menus_path, :method => :post do |f| %>
<%= f.input :name %>
<%= f.submit 'Save', class: 'btn btn-primary' %>
<%= link_to "Cancel", :back, {:class=>"btn btn-default"} %>
<% end %>
I can get the list in my index.html.erb, it is working. My problem is that I don't know how to get all params when I click the submit in new.html.erb. I got this hash
{"sample1_table"=>{"name"=>"test 6"}, "commit"=>"Save","controller"=>"prj_menus", "action"=>"create"}
It is correct but I don't know what to put in my controller. I tried this params.require(["#{#prj_menu}"]).permit(:name), it creates new record but params[:name] does not save.
I am still a noob to Ruby On Rails and I don't know what to search for this.
I think you are mostly confused on what parameter whitelisting does and how parameters are passed from the form to the controller.
I does not really matter if the name of the form hash matches the name of the database table. It just does in most cases since that makes the most sense. It's simply representative of the REST interface of your app.
Let's say you have a action which creates Pets:
POST /pets
And in our form we have a bunch of inputs like so:
<input name="pet[name]">
Rails will map create a params[:pet] hash { name: 'Spot' }. But we want to save the pets as an Animal.
class PetsController < ApplicationController
def new
#pet = Animal.new()
end
def create
#pet = Animal.new(pet_params)
if #pet.save
# ...
end
def pet_params
params.require(:pet).permit(:name)
end
end
Animal does not care what the params key is, it just gets a hash. But we also need to tell simple_form what parameter key we want to use since it looks at the model_name attribute.
simple_form_for(#pet, as: :pet)
Gives us pet[name] instead of animal[name].
I don't get why you are so adamant about making things so difficult for yourself though unless you are creating a database administration tool in the vein of PHP_MyAdmin. And even that case you don't even want to be altering the schema of the app database at runtime.
You are going to run into huge problems when it comes to creating effective queries for getting all the menus.
I am quite new at rails and I am having some trouble designing an admin dashboard.
What I want to achieve is this:
Have a list of multiple users from database.
Have the ability to select multiple records.
Have the ability to apply different actions to all of the
selected records.
The actions MAY not be directly translatable into SQL queries. (for example send an email)
I am not looking for a complete solution to the problem just a general description on how to approach this. I have a feeling I started on a wrong path.
So far I am doing this:
view
<%= form_tag("some_path", method: "get") do %>
<% #users.each do |user| %>
<%= check_box_tag "user_ids[]", users.id %>
<%end%>
<%= submit_tag("Send Email") %>
<%end%>
controller
def send_email
#recipients = User.find(params[:user_ids])
#recipients.each do |recipient|
Notifier.raw_email(recipient.email, params[:user_email][:subject], params[:user_email][:body]).deliver
end
end
This works as it is but i can only apply one action, send email that is.
I want to be able to choose an action to apply to all selected records or apply multiple actions to the selected records
Any thoughts?
You can use the send method to call methods of the model.
class User
def send_email(subject, body)
Notifier.raw_email(self.email, subject, body).deliver
end
end
Let /some_path also accept an array of actions
In our case actions = ['send_email']
In the action that some_path resolves to,
class SomeController < ActionController::Base
def some_action # that some_path resolves to in your config/routes.rb
#recipients = User.find(params[:user_ids])
#actions = params[:actions]
#recipients.each do |recipient|
#actions.each do |action|
recipient.send(action, params[:subject], params[:body])
end
end
end
end
In this way you can call multiple methods. Make sure you only accept valid action values or else the admin can simply call any of the User's methods.
You can have a select tag with the different actions you need.
Then on change of the select tag, you can update the action attribute of the form. eg, using jQuery.
$('#my-action-select').change(function() {
$('#myform').attr('action', $(this).val)
})
There doesn't appear to be a gem for this, and I think a CMS is overkill as the client only wants to edit the welcome message on the home page!
Here's what I think I should do:
1) Create Page model:
rails g model Page name:string
2) Create Field model:
rails g model Field name:string content:string page_id:integer
3) Create relationship, Page h1:b2 Field
4) Create rake task to set up the message field that belongs to the welcome page:
namespace :seeder do
namespace :initial_seed do
task pages: :environment do
p = Page.create(name: "Welcome")
p.fields.create(name: "welcomemessage", content: "everything goes here. The long rambling welcome!")
end
end
end
5) Create a 'static' controller for the 'static'-ish pages. The home, the about us etc...
class Static < ApplicationController
def home
#fields = Page.where().fields
end
end
6) In the view, populate the welcome message from the database (I'll create a helper for this):
<% field = #fields.find {|x| x[:name] == 'welcomemessage' } %>
<%= field.content %>
So that's the reading done. Now onto the creation, updation and deletion:
6) Create a control panel controller:
class Panel < ApplicationController
def pages
#pages = Page.all
end
end
7) Display fields in the view at panel/pages.html.erb: (I'll use partials here)
<% #pages.each do |page| %>
Title: <%= page.name %>
<% page.fields.each do |field|%>
Field: <%= field.name %>
<% form_for(field) do |f| %>
<% f.text_area :content%>
<% f.submit %>
<%= end %>
<% end %>
<% end %>
Now this is just a rough run down of what I want to do. There are a few problems I want to query, though.
Is this sort of how you would do this?
How should I configure my routes? What is a clever way of populating the #fields variable (see step 5) with the fields for the page we're viewing?
If I do have a panel/pages.html.erb view, should it simply display all of the editable fields in text areas? How should it update these areas? Multiple submit buttons inside multiple forms? What if someone wants to edit many fields at once and submit them all at once?
Where should these forms go? Should I create multiple RESTful actions all inside the Panel controller like this?:
class Panel < ApplicationController
# new and create not present as the pages have to be created manually
# Enabling the user to create their own pages with their own layouts is a bit insane
def pages
#pages = Page.all
end
def pages_update
end
def pages_destroy
end
end
Multiple restful routes in one controller doesn't strike me as organised, but it would make it easier to lock down the panel controller with a before_action hook to redirect if not admin...
Also, I'm nearing the end of a big job, and all I need to do is add the ability to edit one field on one page and them I'm done and I really don't want to have to figure out alchemy_cms or whatever. In future, yes, but, please, please, please someone give me some small pointers here.
I would strongly advise against building your own CMS. It's fraught with difficulties, and it seems like you're running up against some of those now. You should go and check out something like AlchemyCMS.
I'm building a martial arts related database, currently I have the following associations set up:
Student has_and_belongs_to_many :styles
Style has_many :ranks
Student has_many :ranks, through: :gradings (and vice versa)
I'm generating a form as follows, depending on the student's styles:
So the headings are generated by the Style model (Tai Chi, Karate...), then their rankings listed below (taken from the Rank model), and the "Dojo" and "Date" fields should belong to the Grading model once created.
The question: I know how to build a form that creates one association (or one association + its children), but how do I build a form that creates multiple associations at once?
Also, what would be a clean way to implement the following:
Only lines which are ticked become associations
Dojo and date must be filled in for ticked lines to save successfully
If a line is unticked it will destroy any previously created associations
This is what I've currently implemented to retrieve the correct records:
class GradingsController < ApplicationController
before_filter :authenticate_sensei!
def index
#student = Student.includes(:styles).find(params[:student_id])
#ranks = Rank.for_student_styles(#student)
split_ranks_by_style
end
private
def split_ranks_by_style
#karate = #ranks.select_style("Karate")
#tai_chi = #ranks.select_style("Tai Chi")
#weaponry = #ranks.select_style("Weaponry")
end
end
# Rank model
def self.for_student_styles(student)
includes(:style).where("styles.id in (?)", student.styles.map(&:id))
end
def self.select_style(style)
all.map { |r| r if r.style.name == style }.compact
end
Complicated forms like this are best handled in a service object initiated in the primary resource's create or update action. This allows you to easily find where the logic is happening afterwards. In this case it looks like you can kick off your service object in your GradingsController. I also prefer formatting a lot of the data in the markup, to make the handling easier in the service object. This can be done a'la rails, by passing a name like "grade[style]" and "grade[rank]". This will format your params coming in as a convenient hash: {grade: {style: "karate", rank: "3"}}. That hash can be passed to your service object to be parsed through.
Without really grasping the full extent of your specific requirements, let's put together an example form:
<%= form_for :grading, url: gradings_path do |f| %>
<h1><%= #rank.name %></h1>
<%- #grades.each do |grade| %>
<div>
<%= hidden_field_tag "grade[#{grade.id}][id]", grade.id %>
<%= check_box_tag "grade[#{grade.id}][active]" %>
...
<%= text_field_tag "grade[#{grade.id}][date]" %>
</div>
<%- end %>
<%= submit_tag %>
<%- end %>
With a form like this, you get your params coming into the controller looking something like this:
"grade"=>{
"1"=>{"id"=>"1", "active"=>"1", "date"=>"2013-06-21"},
"3"=>{"id"=>"3", "date"=>"2013-07-01"}
}
Nicely formatted for us to hand off to our service object. Keeping our controller nice and clean:
class GradingsController < ApplicationController
def index
# ...
end
def create
builder = GradeBuilder.new(current_user, params['grade'])
if builder.run
redirect_to gradings_path
else
flash[:error] = 'Something went wrong!' # maybe even builder.error_message
render :action => :index
end
end
end
So now we just need to put any custom logic into our builder, I'd probably recommend just making a simple ruby class in your /lib directory. It could look something like this:
class GradeBuilder
attr_reader :data, :user
def self.initialize(user, params={})
#user = user
#data = params.values.select{|param| param['active'].present? }
end
def run
grades = data.each{|entry| build_grade(entry)}
return false if grades.empty?
end
private
def build_grade(entry)
grade = Grade.find(entry['id'])
rank = grade.rankings.create(student_id: user, date: entry['date'])
end
end
There will obviously need a lot more work to pass all the specific data you need from the form, and extra logic in the GradeBuilder to handle edge cases, but this will give you a framework to handle this problem in a maintainable and extensible way.