Building sites using rails [closed] - ruby-on-rails

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am new to programming. A friend suggested I start with rails.Once in,I realize,Rails has steep learning curve for a non programmer. Then I come across this tutorial https://www.youtube.com/watch?v=quLmIuIrIigaches
It teaches how to build a website locally in 12 minutes ... JustIt says ... 1. Make a rails app
2. Get an html template
3. Add js,css,images to relevant folder generated in rails_app>>apps>>views.
4. The site is ready
Is that all there is to rails ? The other tutorials are rally hard. or could you suggest me some tutorial that directly gets me into a real life prject and teaches along the way ?
Thank you :)

I am new to programming
Some of the best programmers live on the computer. They have a deep appreciation for the structure, flow & artistry required to craft digital experiences.
If you're new to programming, make a point of looking into what interests you with the system; if it's games, try and look up how games like DOOM were created etc. This will help you more than reading tutorials on how to do generic things.
Foundation
If you're really new to programming, build yourself a website, using HTML and CSS. This will give you appreciation of how Rails works.
Here are some basic tutorials on making HTML/CSS websites (you'd be surprised at how many people got their start making base level websites):
4 Hour Long HTML/CSS Tutorial (long tutorials are generally a waste of time)
15 minute HTML/CSS/JS tutorial (this is more the time you should be looking at)
A 23 minute long tutorial (this looks good but might be a bit long)
Read up on the HTTP protocol, how HTML fits into the the "web", how the world wide web != the "Internet", and was invented in 1989 by Tim Berners Lee.
Read up how Windows95 changed the game, how Marc Andreessen brought people online with Mosaic and NetScape. How Apple brought more people online with iMac and the iPhone.
Read up about how Elon Musk and his merry band of rogues started to monetize the Internet with companies such as Amazon, Zip2, Paypal, Google, etc, etc.
Rails is the distillation of all this stuff.
It will also help you appreciate that web apps are not some golden ticket to riches. Real people use the Internet; your app has to benefit them in some way.
Getting Started
Here's a tutorial:
Download & Install Ruby & RubyGems on your system
If you're using Windows, you can use RubyInstaller, or better still RailsInstaller. It's recommended you use Linux to develop Rails, but it's not essential. We use Windows and people always raise question with it :)
Once you have Ruby installed, in your cmd, you can type gem install rails. This will install the Rails Gem (explained in a second)
4. Once you have Rails installed, you're ready to start developing an "app".
To clarify the role of Ruby and Rails, you have to appreciate that Ruby is the language, Rails the framework.
This means that when dealing with your development environment (OS), you'll be mainly dealing with your Ruby installation. Rails is a layer of abstraction higher than Ruby. Programming issues are typically a Rails problem, environment issues are typically a Ruby issue.
RubyGems is the dependency library for Ruby. Although Rails works perfectly with almost all Ruby Gems, the gems are for Ruby. Most people don't know that Rails is just a gem for Ruby...
First App
Here's how to make a simple app (it will look like shit):
In your CMD, cd to a directory, and type rails new app_name:
This puts all the Rails files in the directory you cd'd into.
This will allow you to then boot up the Rails server. However, before you do that, you need to make sure you have a database.
Rails ships with SQLite, which I've never used. Apparently it stores data in files, which should give you the ability to start developing out of the gate.
We use a simple MYSQL database server on some shared hosting. This gives us the ability to just use it for development, it adds latency but retains data integrity.
I'll let you ask another question about the db. It's another matter in itself.
--
Once you've generated your rails app, you'll be able to boot up the Rails server.
Do this by typing rails s / rails server in your cmd:
(Sorry, this is the best picture I could find)...
The standard Rails server is one called WEBrick. You can alter this later, but I won't go into this now.
All you need to know is that if you're able to successfully boot your server, it is good news, and you'll be able to access it at http://localhost:3000; we use http://lvh.me:3000 which does the same thing.
Once you get to this point, you'll be able to do some programming:
MVC
Rails is made up of 3 components - models, views, controllers (MVC):
MVC is nothing new; tons of other frameworks use it. Since many people enter programming through Rails, they attribute the pattern to this framework, although that's incorrect.
The MVC pattern is very simple (once you understand it):
User browses to your url
Request is sent to your server
Server software passes request to Rails
Rails "middleware" stack handles request, sends to appropriate controller
Controller pulls data from Model (which loads data from the db)
Controller inserts data into view and renders view as HTML, with layout
Controller passes rendered HTML back to web server, which sends to browser
User sees dynamically updated web page
This means if you want to have a simple app, you need to at least have a model, views and controller.
To do this, browse to your Rails application directory (the one you cd'd into at the beginning). Each file below is one you should edit (we use SublimeText):
#config/routes.rb
root "posts#index"
resources :posts
#app/controllers/posts_controller.rb (you have to create this)
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.new post_params
#post.save
redirect_to #post
end
def edit
end
def show
end
def update
redirect_to #post if #post.update
end
def destroy
redirect_to posts_path if #post.destroy
end
private
def post_params
params.require(:post).permit(:title, :body)
end
def set_post
#post = Post.find params[:id]
end
end
This will then mean you have to create certain views:
#app/views/posts/index.html.erb
<% #posts.each do |post| %>
<%= link_to post.title, post %>
<% end %>
<%= link_to "New Post", new_posts_path #-> will have to check the route %>
#app/views/posts/new.html.erb
<%= render "form", locals: {post: #post} %>
#app/views/posts/edit.html.erb
<%= render "form", locals: {post: #post} %>
<%= link_to "Destroy Post", post, method: :delete %>
#app/views/posts/_form.html.erb
<%= form_for post do |f| %>
<%= f.text_field :title %>
<%= f.text_field :body %>
<%= f.submit %>
<% end %>
--
Finally, you should then populate the data model. To do this, you need to make sure you have your database infrastructure set up; if this is in place, stop your Rails server by pressing crtl+c in cmd, then type:
$ rails g migration CreatePostsTable
A file will be created at:
#db/migrate/_____.rb
class CreatePostsTable < ActiveRecord::Migration
def change
#### You'll have to add this part ###
create_table :posts do |t|
t.string :title
t.string :body
t.timestamps
end
end
end
After that, go back to your cmd and type: rake db:migrate.
If your database is set up correctly, this should create a new posts table for Rails to interact with. Then, you just need a Model to work with it:
#app/models/post.rb ##-> you'll have to create this
class Post < ActiveRecord::Base
end
Once that's done, fire up your Rails server again (rails s in cmd), and access the following:
http://lvh.me:3000
It should show you a single button saying "New Post". If you press it, type out a post and it should appear, if all works.

Google search query "rails tutorial" gives that as the first link, and it is (subjectively) the best one: https://www.railstutorial.org/book. So if you really want to learn rails, go through it.

Related

Is there a real problem with using i.e. get method instead of put in an action through clicking on a button

For example I have button for thumbs up or I want to resend a specific mail or I change a specific enum state through clicking on a button (like published/unpublished)
Now regarding the rails implementation, I can make it work using either put, get or patch, since I only have to send a specific id.
In my opinion it seems to be best practice using patch, post or put wheter one or several attributes will change on my objects. So this seems mainly to be a convention here.
On the server side I will have to add some policies to allow only specific users to do so, but beyond adding policies are there any possible issues with not using the conventional http-method here?
One very real problem with using GET is that is supposed to be an idempotent method. Lets say the new guy creates the form:
get '/things/create', to: "things#create"
<%= form_with(model: #post, url: '/posts/create', method: :get) do |f| %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<%= f.submit %>
<% end %>
class PostsController < ApplicationController
def index
#posts = Post.all
end
def create
#post = Post.new(title: params[:post][:title])
#post.save
redirect_to action: :index
end
end
He then tries it out in the browser in and is perfectly happy with it. Mission accomplished.
His boss then attempts to test it. He creates a Post titled "This new guy might not be so bad anyways". And then he hits the back button to try creating another Post. Weirdly it just loops back to the index page. He tries it again - the only thing that happens is that the page starts to fill up with "This new guy might not be so bad anyways" and he is becomes less and less convinced that its actually true.
If you used POST, PATCH, PUT or DELETE the browser would have warned him that he is about to resend a form. Thats why GET should never change anything on the server (besides maybe your pageview stats).
It also opens up for any malicous actor to get users to create, delete or modify resources simply by fooling them into clicking a link. The malicous actor doesn't even have to got though the effort of creating a phishing site and circumventing the anti-CSRF protection that Rails provides.
There is absolutely no difference between how POST, PATCH, PUT or DELETE are treated by the client or server beyond the conventions of Rails.
But since Rails is a highly convention driven framework which adheres to a specific flavor of REST it really befits you to follow those conventions if you want to be productive and not be that new guy.
When it comes to actions beyond the classical CRUD verbs its really down to your best judgement and intent is really what matters. What does the action do? Is it updating something (PATCH)? Is it actually a separate resource? (POST /mails/1/mailouts). As you may see there is no easy answer. Just be clear and document what you're doing if you're unsure.

How do I take this from the console to a controller and view

I'm learning Ruby on Rails (my first MVC) and have successfully setup a many-to-many relationship between "Agents" and "Zipcodes." What I'm trying to do currently is to get the associated agent based on the zip code entered by the user. I'm able to so successfully in the console, but am having a difficult time translating it to a controller and view.
What I do in the console:
zip = Zipcode.find_by_zip(gets.chomp)
=> 92562
zip.agents
The hangup I'm having is how to translate this into an action that I can access from a view with a form.
I've started by defining the action (agents#find), but am stumped as to whether this is correct and what comes after it.
def find
#user_zip = Zipcode.find_by_zip(params[:zip])
end
Hopefully someone awesome in here can point a n00b in the right direction.
When just starting with rails, I'd suggest avoiding custom actions like #find as much as possible, and instead sticking to the "Big 7" RESTful routes. Rails is really smooth when you work with it and do what it expects.
It sounds like maybe you're trying to identify a given zipcode, and then list all the agents associated with it. That sounds like a #show on Zipcode.
config/routes.rb
resources :zipcodes
app/controllers/zipcodes_controller.rb
ZipcodesController < ApplicationController
def show
#zipcode = Zipcode.find_by_zip(params[:id])
end
end
app/views/zipcodes/show.html.erb
<div>
<p>This zipcode has the following agents:</p>
<ul>
<%= #zipcode.agents.each do |agent| %>
<li>Agent #<%= agent.id %></li>
<% end %>
</ul>
</div>
You can see this page by browsing to /zipcodes/[zip].
Just put #user_zip = Zipcode.find_by_zip(params[:zip]) in the controller instead of the model.
In the view you will be able to call #user_zip.
Welcome to Rails! I recently started learning Rails as well, but I think I can help: A controller action will redirect by default to a view with the same name. So after assigning the value of #user_zip, the controller will serve up agents/find.html.erb, which will have access to #user_zip. Since #user_zip is an instance of Zipcode, you'd be able to use #user_zip.agents.
Somewhat tangential, but I also suggest considering using search rather than find for the action name, only because find and its variations are used elsewhere in Rails.

Nested Ressources in Ruby on Rails

It's actually supposed to be very trivial, but I'm experiencing strange issues.
I'm developing a Game Database, where Users can chart Game Entries and also write reviews to those reviews. Of course a Reviews URL (the show view) must be dependent of the game's id, like localhost:3000/games/1/reviews/2
So these are my routes
resources :games do
resources :reviews
end
And I want to open the show-view of a review with
<%= link_to "zum Review", game_review_path(#game, #review) %>
this is all basic tutorial stuff.
But I only recieve a Routing error. Trying instead this approach
url_for([#game, #review])
At least won't result in a routing error, but Not the reviews show-view is opened, but the game's show view, which is where this link is actually placed!
My models associations are set corretly and my controllers actions are all basic tutorial stuff. What am I doing wrong?
In your erb file try passing the local variable in the left argument and the name of the nested model in the field to the right. If you use 2 local variables you will get a routing error. #game is the local variable and review is nested under games so the below code should fix your issue.
Try:
<%= link_to "zum Review", game_review_path(#game, review) %>

Rails3 Admin UI frameworks

We will soon be rewriting a 5 year old rails app, with a very unsound code foundation, from scratch in a brand new Rails 3 app with all the new hotness. The current app has a substantial custom admin UI backend which depends on now admin frameworks at all. Just some base controller classes and some somewhat useful CSS conventions. But maintaining that UI is a lot of work, especially if we want it to look half way nice.
So I'm in the market for an Admin UI framework that will make the simple stuff trivial, but without getting the way of more complex customization in both form and function.
The top contender, ActiveAdmin, seems to be very popular, and after playing with it a bit I have some concerns. It seems to declare a whole unique DSL that exists in a single ruby file. This is kind of neat, but it's also a completely different than how most other Rails apps are architected. It abstracts away the view, the helper the controller, and gives you a pure ruby DSL. It seems to me that this would get in the way of doing tricky things, more advanced custom things in our admin views. DSL's are great, until you want to do something they don't explicitly support.
Example "Resource" from my experimentation, with no controller and no view.
ActiveAdmin.register Region do
menu parent: "Wines"
show title: :name
index do
column(:zone) { |o| link_to o.zone, admin_region_path(o) }
column(:name) { |o| link_to o.name, admin_region_path(o) }
default_actions
end
end
So, the questions:
Is not being based on the standard Rails MVC architecture in separate files, and the typical controller inheritance based implementation of an admin area, actually something I should be concerned about? Will it hamper extensibility in the long term?
Is the DSL in ActiveAdmin better and more flexible than I'm giving it credit for?
Should I be looking at some other framework that lends itself better to my goals of high customization?
Should I stop being lazy and roll my own?
Does the choice of Mongoid instead of MySQL as a database affect any of the above questions?
It is worth mentioning that in ActiveAdmin you can also create your own complex forms by using partials
form partial: 'my_form'
and expand controller functions with a controller block.
controller do
def edit
end
def index
end
end
+1 for active admin, I use it in many projects, including a cms I'm building. It indeed is more flexible than many people who are newer with it give it credit for, at the end of the day you can always do:
controller do
def custom_action
Puts "hi"
end
end
(Think that's the right syntax writing from phone so all this is off top of head)
Also, I swear by inherited resources, which active admin controllers extend, as they really force you (in a good way) into writing restful, reuse able code. Bottom line is I believe active admin is leaps and bounds ahead of the others I've tried (railsadmin and at least one other)
Update:
Sure, here is the inherited_resources documentation
https://github.com/josevalim/inherited_resources
And here is an example of modifying the controller directly, from my little CMS project.
ActiveAdmin.register Channel do
index do
column :title
column :slug
column "Fields" do |channel|
"#{link_to('View Fields', admin_channel_entry_fields_path(channel))} #{link_to 'Add Field', new_admin_channel_entry_field_path(channel)}".html_safe
end
column "Actions" do |channel|
"#{link_to('View Entries', admin_channel_entries_path(channel))} #{link_to 'Create Entry', new_admin_channel_entry_path(channel)}".html_safe
end
default_actions
end
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs "Channel" do
f.input :title
f.input :display_name
f.input :image
end
f.buttons
end
controller do
def begin_of_association_chain
current_site
end
def tags
query = params[:q]
if query[-1,1] == " "
query = query.gsub(" ", "")
ActsAsTaggableOn::Tag.find_or_create_by_name(query)
end
#tags = ActsAsTaggableOn::Tag.all
#tags = #tags.select { |v| v.name =~ /#{query}/i }
respond_to do |format|
format.json { render :json => #tags.collect{|t| {:id => t.name, :name => t.name }}}
end
end
end
end
Basically, I am using the inherited resources, begin_of_association_chain method (one of my favorite things about IR), to scope all the data within channels, or any of the admin resources that inherit from my channels resource, to the current site, without having a url like /admin/sites/1/channels -- Because I am already setting current_site based on the url the visitor enters with. -- Anyways, basically once you are inside:
controller do
puts self.inspect
end
Returns the actual controller itself, e.g. Admin::ChannelsController (which < InheritedResources::Base, maybe not directly but all the IH controller methods should be available at this point).

Basecamp API Rails

I was wondering if someone could do me massive favour..
I really don't understand how to make use of APIs - so I was wondering if, using Basecamp as an example, someone could talk me though the basics.
So far I have an application with a dashboard controller/view, I have put basecamp.rb into my /lib directory, added the following to my application_controller:
def basecamp_connect
Basecamp.establish_connection!('XXXXXX.basecamphq.com', 'USER', 'PASS', false)
#basecamp = Basecamp.new
end
Obviously changing the required parts to my credentials.
Next up I have added the following to my dashboard_controller:
def index
Basecamp::TodoList.find(:all)
end
Next I presume I have to somehow list the Todos on the dashboard using some sort of loop.
Am I doing the right thing, if so - how on earth do I display all the todo items and if not - what am I doing wrong/missing.
It doesn't have to be todos, anything from Basecamp or any other popular API service would be a good start. It's just that I happen to have a basecamp account!
Thanks,
Danny
Your view expects to have some variables defined. You can loop through those variables and display their content as you want.
So you could do, in your action :
def index
#list = Basecamp::TodoList.find(:all)
end
Then in your view you have access to the #list variable and you can to the following :
<ul>
<% #list.each do |item| %>
<li><%= item.to_json</li>
<% end %>
</ul>
Replacing the json dump by the elements as you wish to display them of course.
You might want to read the rails guides to get a lot more of informations.

Resources